(41) 9225-6319
contato@felipemarques.com.br

Usando FRAPI (Vídeo Demo) sem configurar virtualhost

Vídeo Demo FRAPI sem virtualhost.
Unable to display content. Adobe Flash is required.

Fala pessoal,

Recentemente estive no PHP Conference 2011 em OSASCO-SP (UNIFIEO), e participei de diversas palestras sensacionais, e uma delas me chamou muito a atenção, e foi a palestra do caro colega Alex Piaz (link para avaliação da palestra).

Ele apresentou a todos um exemplo de utilização do FRAPI, um sistema que automatiza a criação de APIs, desenvolvimento em PHP, e que permite a criação de APIs online, ou seja, você não precisa desenvolver local e depois subir os arquivos pro ambiente de produção. Não é muito correto porem em certos casos agiliza muito o processo inicial.

Bom, opinões a parte, vou postar aqui a minha versão do FRAPI que necessitei alterar, para que pudesse funcionar em subdiretórios, sem a necessidade de configurar 2 virtualhosts, o que eu achei muito ruim. Eu precisei fazer isso porque no projeto que estou trabalhando atualmente, não existe a possibilidade de se criar um virtualhost, porque o serviço de hospedagem é compartilhado e não temos como configurar o apache.

Então por isso, baixei o tarball do Github (https://github.com/frapi/frapi/) e comecei as alterações. Até agora ja havia testado diversos modulos do sistema e tudo estava funcionando.
Abaixo, segue a lista dos arquivos que foram alterados:

Se você não quiser seguir os passos que eu executei abaixo para chegar a este resultado, pode efetuar o download do projeto modificado clicando aqui.

/custom/AllFiles.php

// altera a linha 3 para a linha abaixo, caso você nao tenha como instalar nenhum dos sistemas de cache usados no FRAPI
define('FRAPI_CACHE_ADAPTER', 'dummy');
// adicione a linha
define('URL_BASE', substr($_SERVER['PHP_SELF'],0,strpos($_SERVER['PHP_SELF'],'public/index.php') - 1).'/public');

/admin/application/views/layouts/header.phtml

// altere a tag head deste arquivo para o conteudo abaixo

<script type="text/javascript" src="<?php echo URL_BASE; ?>/scripts/jquery.js"></script>
<script type="text/javascript" src="<?php echo URL_BASE; ?>/scripts/jquery.metadata.js"></script>
<script type="text/javascript" src="<?php echo URL_BASE; ?>/scripts/jquery.uitablefilter.js"></script>
<script type="text/javascript" src="<?php echo URL_BASE; ?>/scripts/jquery.tablesorter.min.js"></script>

<!-- compliance patch for microsoft browsers -->
<!--&#91;if lt IE 8&#93;><script src="<?php echo URL_BASE; ?>/scripts/IE8.js" type="text/javascript"></script><!&#91;endif&#93;-->

<script type="text/javascript" src="<?php echo URL_BASE; ?>/bespin/BespinEmbedded.js"></script>
FRAPI <!--?php echo $this--->tr-&gt;_('ADMIN_INTERFACE'); ?&gt;

/admin/application/views/layouts/footer.phtml

// altere para o conteudo abaixo
<div class="footer">FRAPI — © <!--?php echo date('Y'); ?-->, echolibre.</div>
<script type="text/javascript">// <!&#91;CDATA&#91;
	   $(document).ready(function() {
	       $('#sync').live('click', function() {
	           document.location.href = '<?php echo URL_BASE; ?>/action/sync';
	       });
	   });

// &#93;&#93;></script>

/admin/application/views/scripts/menu.phtml

// altere para o conteudo abaixo
<!--?php $request = Zend_Controller_Front::getInstance()--->getRequest();
$this-&gt;menuItem = $request-&gt;getRequestUri();
$this-&gt;menuItem = str_replace(URL_BASE,'',$this-&gt;menuItem);

$string = substr($this-&gt;menuItem, 1);
$pos = strpos($string, '/');
$lpos = strpos($string, '/');
if ($pos !== false &amp;&amp; $pos === $lpos) {
$data = explode('/', $string);
if (count($data) &gt; 2) {
$this-&gt;menuItem = '/' . $data[0] . '/' . $data[1];
$item = '/' . $data[0];
} else {
$item = '/' . substr($string, 0, $lpos);
}
} else {
$item = '/' . $string;
}

?&gt;
<div class="navigation"><a class="active"> href="<!--?php echo URL_BASE; ?-->/"&gt;<!--?php echo $this--->tr-&gt;_('DASHBOARD'); ?&gt;</a>
<a class="active"> href="<!--?php echo URL_BASE; ?-->/action"&gt;<!--?php echo $this--->tr-&gt;_('ACTIONS'); ?&gt;</a>
<a class="active"> href="<!--?php echo URL_BASE; ?-->/errors"&gt;<!--?php echo $this--->tr-&gt;_('ERRORS'); ?&gt;</a>
<a class="active"> href="<!--?php echo URL_BASE; ?-->/partners"&gt;<!--?php echo $this--->tr-&gt;_('PARTNERS'); ?&gt;</a>
<a class="active"> href="<!--?php echo URL_BASE; ?-->/configuration"&gt;<!--?php echo $this--->tr-&gt;_('CONFIGURATION'); ?&gt;</a>
<a class="active"> href="<!--?php echo URL_BASE; ?-->/tester"&gt;<!--?php echo $this--->tr-&gt;_('TESTER'); ?&gt;</a></div>

/admin/application/views/scripts/submenu.phtml

<!--?php $request = Zend_Controller_Front::getInstance()--->getRequest();
$this-&gt;menuItem = $request-&gt;getRequestUri();
$this-&gt;menuItem = str_replace(URL_BASE,'',$this-&gt;menuItem);

$string = substr($this-&gt;menuItem, 1);
$pos = strpos($string, '/');
$lpos = strpos($string, '/');
if ($pos !== false &amp;&amp; $pos === $lpos) {
$data = explode('/', $string);
if (count($data) &gt; 2) {
// This has to be fixed. Too restrictive to one level of hierarchy
$this-&gt;menuItem = '/' . $data[0] . '/' . $data[1];
$item = '/' . $data[0];
} else {
$item = '/' . substr($string, 0, $lpos);
}
} else {
$item = '/' . $string;
}

?&gt;

&nbsp;
<div class="sidenav">
<h2></h2>
&nbsp;
<ul>
	<li class="active">&gt;</li>
</ul>
&nbsp;

&nbsp;
<ul>
	<li class="active">&gt;</li>
</ul>
&nbsp;

&nbsp;
<ul>
	<li class="active">&gt;</li>
</ul>
&nbsp;

&nbsp;
<ul>
	<li class="active">&gt;</li>
</ul>
&nbsp;

&nbsp;
<ul>
	<li class="active">&gt;</li>
</ul>
&nbsp;

&nbsp;
<ul>
	<li class="active">&gt;</li>
</ul>
&nbsp;

&nbsp;
<ul>
	<li class="active">&gt;</li>
</ul>
&nbsp;

&nbsp;
<ul>
	<li class="active">&gt;</li>
</ul>
&nbsp;

&nbsp;

</div>
&nbsp;

/admin/application/modules/default/views/scripts/tester/index.phtml

<script type="text/javascript" src="<?php echo URL_BASE; ?>/scripts/syntaxhighlighter/shCore.js"></script>
<script type="text/javascript" src="<?php echo URL_BASE; ?>/scripts/syntaxhighlighter/shBrushJScript.js"></script>
<script type="text/javascript" src="<?php echo URL_BASE; ?>/scripts/syntaxhighlighter/shBrushPhp.js"></script>
<script type="text/javascript" src="<?php echo URL_BASE; ?>/scripts/syntaxhighlighter/shBrushPlain.js"></script>
<script type="text/javascript" src="<?php echo URL_BASE; ?>/scripts/syntaxhighlighter/shBrushXml.js"></script>
<script type="text/javascript" src="<?php echo URL_BASE; ?>/scripts/customBrushHeaders.js"></script>
<script type="text/javascript" src="<?php echo URL_BASE; ?>/scripts/beautify.js"></script>

<script type="text/javascript">// <!&#91;CDATA&#91;
    SyntaxHighlighter.config.clipboardSwf = '<?php echo URL_BASE; ?>/scripts/syntaxhighlighter/clipboard.swf';
    var highlight_response = function () {
        window.SyntaxHighlighter.highlight()
    };
// &#93;&#93;></script>

<!--?php echo $this--->form;
?&gt;
<div id="submitter-div"><input id="submitter" type="button" value="<?php echo $this->tr->_('RUN_TEST'); ?>" /></div>
<div id="testing"><img id="loading" src="<?php echo URL_BASE; ?>/gifs/ajax-loader.gif" alt="Loading" /></div>
&nbsp;
<h2 id="request-header" style="display: none;"></h2>
<h2 id="post-fields-header" style="display: none;"></h2>
<h2 id="response-header" style="display: none;"></h2>
<script type="text/javascript">// <!&#91;CDATA&#91;
    var url = 'api.frapi';

    $('#action').change(function() {
        var selected = $(this).val();
        var selectedText = $('#action :selected').text();
        var type  = (selected.match(/^&#91;0-9&#93;+$/)) ? ("action") : ("route")

        $('#params').empty();
        if ("route" == type) {
            $('#query_uri').val(selectedText);
        } else {
            $('#query_uri').val("?action=" + selectedText);
        }
    });

    $('#action').change();

    $("form input").keypress(function (e) {
        if ((e.which &#038;& e.which == 13) || (e.keyCode &#038;& e.keyCode == 13)) {
            $('#submitter').click();
            return false;
        } else {
            return true;
        }
    });

    function addParamInput(paramName, paramValue)
    {
        var value = paramName ? paramName + "=" : "";
        var value = paramValue ? value + paramValue : "";
        $("#params").append('
<input type="text" name="param&#91;&#93;" value="'+value+'" /> <img src="<?php echo URL_BASE; ?>/images/delete.png" class="remove" />

');
        $("#params input:last").focus();
    }

    $(function(){
        $("#add").live("click", function(ev) {
            addParamInput();
        });

        $(".remove").live('click', function () {
            var target = $(this);
            target.parent().remove();
        });
    });

    $('#emailkey').change(function() {
        var selected = $(this).val();
        var selectedText = $('#emailkey :selected').text();
        var valid  = (selected.length > 0);

        if (valid) {
            var split = selectedText.split(" / ", 2);
            $('#email').val(split&#91;0&#93;);
            $('#key').val(split&#91;1&#93;);
        }
    });

    $('#submitter').live('click', function() {

        $('#submitter').attr('disabled', true)
                       .attr('value', '<?php echo $this->tr->_('TESTING'); ?>...');
        $('#testing').show();

        var queryURI = $('#query_uri').val();
        var method   = $('#method').val();
        var email    = $('#email').val();
        var key      = $('#key').val();
        var format   = $('#format').val();

        var url      = $('#url').val();
        var ssl      = $('#ssl').is(':checked');

        var extraParams = new Array();

        $("#message").remove();

        jQuery.each($('#params input'), function(){
            extraParams&#91;extraParams.length&#93; = $(this).val();
        });

        if (!queryURI) {
            alert('<?php echo $this->tr->_('NO_QUERY_URI'); ?>?'); return false;
        }

        queryURI += '.' + format.toLowerCase();

        var finalParams = 'email=' + escape(email);
        finalParams += '&#038;secretKey=' + key;

        switch (method.toLowerCase()) {
            case 'get':
            case 'post':
            case 'delete':
            case 'put':
                method = method.toLowerCase();
                break;
            default:
                method = 'get';
                break;
        }

        finalParams += '&#038;method=' + method;
        finalParams += '&#038;url=' + url;
        finalParams += '&#038;query_uri=' + escape(queryURI);
        if (ssl === true) {
            finalParams += '&#038;ssl=true';
        }

        if (extraParams.length > 0) {
            for (var i = 0; i < extraParams.length; i++) {                 finalParams += '&#038;param&#91;&#93;=' + escape(extraParams&#91;i&#93;);             }         }         if (format.indexOf('JSON') >= 0) {
            $('#beautify').live('click', function() {
                var code = $('#response-container').attr('data-content')
                code = js_beautify(code);
                $('#response-container div.syntaxhighlighter').remove();
                $('#response-container').append('

<pre id="response" />');
                $('pre#response').html(code).addClass('brush: jscript');
                highlight_response();
            });
        }

        $.ajax( {
           type:    "GET",
           url:     "<?php echo URL_BASE; ?>/tester/ajax",
           data:    finalParams,
           success: function(data) {
               var brush = "jscript";
               switch (format.toLowerCase()) {
                   case "xml":
                       brush = "xml";
                       break;
                   case "php":
                       brush = "php";
                       break;
                   case "cli":
                       brush = "plain";
                       break;
               }

               var RequestString = '<?php echo $this->tr->_('REQUEST'); ?>';
               var ResponseString = '<?php echo $this->tr->_('RESPONSE'); ?>';
               var CodeString = '<?php echo $this->tr->_('CODE'); ?>';

               $('#request-header').html(RequestString + " ("+ data.method +")").show();
               $('#response-header').html(ResponseString + " (" + CodeString + " "+ data.status +")").show();
               $('#request-container').empty().append(
                   $('
<input>').attr({id: "#request_url", style: "width: 100%"}).val(data.request_url)
               );

               $('#post-fields-header').hide();
               $('#post-fields-container').empty();
               if (data.request_post_fields) {
                   $('#post-fields-header').show();
                   $('#post-fields-container').append(
                       $('<textarea>').attr({id: "#post-fields-textarea", style: "width: 100%"}).val(data.request_post_fields)
                   );
               }

               $('#response-container').empty();
               $('#response-container').append(
                   $('

<pre>').attr('id', '#response_headers').addClass("brush: headers").html(data.response_headers)
               );

               var responseContent = '';
               responseContent = $('

<pre>').attr('id', 'response').addClass("brush: " + brush).html(unescape(data.content));

               $('#response-container').attr('data-content', data.content).append(
                   $('

<h2><?php echo $this->tr->_('CONTENT_BODY'); ?></h2>

')
               ).append(responseContent);

               var abeauty = $('<a id="beautify">Beautify</a>').css({cursor: 'pointer'});
               if (format.indexOf('JSON') >= 0) {
                   $('#response-container').append(abeauty);
               } else {
                   $('#beautify').remove();
               }

               highlight_response();

               $('#submitter').attr('disabled', false)
                              .attr('value', '<?php echo $this->tr->_('RUN_TEST'); ?>');

               var inHistory = false;
               var uri       = queryURI.replace('\.' + format.toLowerCase(), '');
               $('#action optgroup&#91;label=History&#93; option').each(function() {
                   if ($(this).val() == uri) {
                     inHistory = true;
                   }
               });
               if (!inHistory) {
                   $('#action optgroup&#91;label=History&#93;').append('
<option value="' + uri + '"" selected="selected">' + uri + '</option>

');
               }

               $('#testing').hide();
           },
           dataType: "json",
           error: function (XMLHttpRequest, textStatus, errorThrown) {
               if (XMLHttpRequest.status == 403) {
                   var ResponseString = '<?php echo $this->tr->_('TESTER_REQUEST_ERROR'); ?>';
                   $(".content").prepend($('

<div>').attr('id', 'message').html(ResponseString));
               }

               $('#submitter').attr('disabled', false)
                              .attr('value', '<?php echo $this->tr->_('RUN_TEST'); ?>');
               $('#testing').hide();
               this;
           }
        });

        return false;
    });

    $('#action').live('change', function() {
        var inHistory = false;
        var queryURI  = $('#query_uri').val();

        $('#action optgroup&#91;label=History&#93; option').each(function() {
            if ($(this).val() == queryURI) {
                inHistory = true;
            }
        });

        if (inHistory) {
            $.ajax({
                type:    "GET",
                url:     "<?php echo URL_BASE; ?>/tester/history",
                data:    "url=" + escape(queryURI),
                success: function(data) { 
                    $("#query_uri").val(data.query_uri);
                    $("#format").attr("value", data.format.toUpperCase());
                    $("#method").attr("value", data.method.toLowerCase());
                    $("#email").val(data.email);
                    $("#key").val(data.secretKey);
                    $("#url").val(data.url);

                    if (typeof(data.ssl) != "undefined") {
                        $("#ssl").attr("checked", data.ssl); 
                    }

                    if (typeof(data.param) != "undefined") {
                        for(i in data.param) {
                            var param_parts = data.param&#91;i&#93;.split("=")
                            addParamInput(param_parts&#91;0&#93;, param_parts&#91;1&#93;);
                        }
                    }
                },
                dataType: "json",
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                    alert('<?php echo $this->tr->_('HISTORY_ERROR'); ?>');
                }
            });
        }
    });
// &#93;&#93;></script>

/admin/public/css/template.css

- linha 23: background: #CCD8E0 url(../images/template/bg.png) repeat left top;
- linha 51: background: url(../images/template/quote.gif) no-repeat;
- linha 116: background: #B3C2C7 url(../images/frapi-transparent.png) no-repeat;
- linha 134: background: #D9E1E5 url(../images/template/nav.gif);
- linha 140: background: #D9E1E5 url(../images/template/nav.gif);
- linha 155: background: url(../images/template/bgmain.gif) repeat-y;
- linha 202: list-style: url(../images/template/li.gif);
- linha 209: background: url(../images/template/bgfooter.gif) repeat-x;

/admin/application/modules/default/models/Tester.php

// altere somente o metodo, na verdade somente precisa colocar o URL_BASE na imagem add.png
public function buildForm()
{
$tr = Zend_Registry::get('tr');
return '
<div id="params-container">

<em>'.$tr-&gt;_('TESTER_ADD_PARAMETER').'</em>:<img id="add" src="'.URL_BASE.'/images/add.png" alt="" />

</div>
';
}

/library/Lupin/Form.php

// adicione esta linha abaixo logo depois de:
parent::__construct($options);

// aproximadamente na linha 40 , adicione isto
$this->setAction(URL_BASE.str_replace(URL_BASE,'', $_SERVER['REQUEST_URI']));

Finalizando…

### /library/Frapi/Router.php
- inserir linha logo apos linha 134: $queryPath = str_replace(URL_BASE,'',$queryPath);

### /admin/application/modules/default/views/scripts/action/add.phtml
- linha 28: html = html + '

';

### /custom
- crie um arquivo .htaccess e cole o seguinte conteudo:

Order allow,deny
Deny from all

### /public
- altere o .htaccess e no inicio do arquivo cole o seguinte conteudo:

Order allow,deny
Allow from all

Se você fizer todas estas configurações vai conseguir rodar o frapi em um subdiretório sem usar um virtualhost e os 2 últimos arquivos .htaccess servem pra bloquear e pra habilitar a visualização de arquivos xml no projeto, isso evita que algum espertinho consiga visualizar diretamente a senha do admin acessando /custom/Config/users.xml.

E por hoje é só pessoal!!!

Até a próxima!!!

Sobre o autor
Felipe Marques é Consultor e Analista de Sistemas Web e Mobile. Mais de 10 anos de experiência.
  1. Pingback: FRAPI – Web APIs de forma fácil no PHP ← ROGERIO PRADO J | rogeriopradoj.com

Faça um comentário

*

Facebook Auto Publish Powered By : XYZScripts.com