Web Services com REST e PHP, parte 2
Agora que você já viu que pra implementar um web service RESTful você não precisa de nada além da sua boa vontade, podemos nos aprofundar no assunto sem grandes riscos. Fiz questão de iniciar este série com um texto focado na parte programática, deixando de lado boa parte da filosofia REST, uma abordagem meio reversa, propositalmente. REST é um conjunto grande de conceitos que engloba a adoção de todo um ponto de vista diferente em relação a Web (se você anda seguindo a cartilha do bom desenvolvedor direitinho, muita coisa nem vai ser tão nova assim), e começar por esta parte pode fazer parecer que as coisas são muito mais complicadas do que são realmente.
REST, como já mencionei, não é um protocolo ou uma especificação, e sim um conjunto de princípios. A idéia é a seguinte: tudo o que existe na rede é visto como um recurso, que possui estados, e pode ser acessado e manipulado por meio de um endereço único e universal. Isto soa abstrato demais, por isto quis colocar o código primeiro (no final deste artigo você vai entender por quê o exemplo do primeiro artigo não é uma aplicação RESTful em seu sentido mais “puro”, apesar de utilizar o mesmo mecanismo de acesso).
Se na primeira parte nos implementamos um código “estilo REST”, mas sem constituir uma aplicação RESTful no seu estado mais puro, agora nós vamos discutir um exemplo de aplicaçao seguindo uma arquitetura totalmente REST, porém contornando a aplicação de métodos PUT e DELETE, para sua (e minha) conveniência; no entanto, deixei comentários nas partes onde eu contornei o uso destes métodos, indicando uma possível implementação que os utilize.
O exemplo é o seguinte: uma loja virtual. Vamos nos concentrar exclusivamente na que diz respeito aos produtos. Todos os resultados das operações abaixo (o que é enviado para o navegador do usuário, ou aplicação que estiver acessando sua aplicação) é feito sob a forma de XML e Headers HTTP indicando o status do recurso acessado. Uma arquitetural RESTful iria resultar em uma aplicação web com uma interface mais ou menos assim:
dominio.com/produtos
- Ao receber um request do tipo POST, um produto é criado no banco de dados da loja;
- Ao receber um request do tipo GET, sem parametros, os produtos da loja são listados (a ordem ou quantidade depende da lógica de negócio do lojista);
dominio.com/produtos/mesa-de-centro
- Exemplo de um request do tipo GET com parametro: o nome do produto. Pressupoe-se que este os nomes são únicos. URLs como dominio.com/produtos/?p=mesa-de-centro devem ser evitadas; use mod_rewrite ou qualquer outra coisa para tratar os requests e permitir URLs inteligentes;
- Ao receber um request do tipo POST, o produto é atualizado com os dados enviados. Sinta-se livre para pensar num modelo de autenticação, não é tão difícil assim. Este é um dos contornos para ausência do método PUT; na verdade, o correto seria que um request do tipo PUT para esta URL realizasse a atualização do conteúdo ou a criação do mesmo no endereço especificado, caso não exista nada ali e o conteúdo possa ser criado.
dominio.com/produtos/mesa-de-centro/delete
- Ao receber um input do tipo POST com alguma informação de autenticação, caso a autenticação ocorra, exclui o produto do banco de dados da loja. O mais correto seria realizar esta operação através de um request do tipo DELETE para dominio.com/produtos/mesa-de-centro; esta é uma maneira de contornar isto, já que DELETE não é exatamente o método mais popular do HTTP.
Agora você tem uma interface RESTful para manipular os produtos da sua loja. Parece bobagem? Não vale a pena? E se você pensar que, através do acesso a dominio.com/produtos/mesa-de-centro, quem fez o request recebe um XML com as informações do produto e um link para sua loja, e nada mais, o que possibilita que qualquer um adicione links para seus produtos em seus sites, com a descrição dos produtos? E que tal se com uma aplicação simples no seu celular você pudesse manipular os produtos na sua loja, sem complicação nenhuma? Estes são apenas alguns exemplos do que pode ser facilmente alcançado com uma arquitetura REST.
As coisas ficam ainda melhores se você pensar que, identificando o cliente que fez o request (coisa trivial), você pode decidir se vai retornar simplesmente um XML com os dados necessários ou a interface completa da sua loja (em XHTML, por exemplo) com menus e tudo mais, pronta para ser exibida num navegador. As possibilidades são enormes.
“Mas e o PHP, Rafael? No título você falou que tinha PHP!”. Tudo bem. Não vou escrever aqui o código para o exemplo acima, nem sonhe com isto; no entanto, vão alguns toques de como fazer as coisas que eu mencionei:
Identificar o user agent
As informações sobre o autor do request (uma string) ficam guardadas aqui:
$_SERVER['HTTP_USER_AGENT']
Para testar:
echo $_SERVER['HTTP_USER_AGENT'];
Retornar um XML com Header 200/OK (operação foi um sucesso, dados retornados)
header('Content-Type: text/xml');
echo '<?xml version="1.0" encoding="UTF-8"?>'
echo '<produto>';
echo '<nome>Mesa de centro</nome>';
echo '<link>http://meudominio.com/mesa-de-centro</link>';
echo '</produto>';
Já é o suficiente. O content-type do header é alterado para text/xml, permitindo que o conteúdo seja corretamente interpretado; o header 200/OK não precisa ser gerado manualmente, já que é o header padrão quando tudo corre bem. Gerar os valores dinamicamente é com você e sua paciência para trabalhar com bancos de dados.
Nos outros casos, quando ocorrer algum erro ou alguma situação diferente, basta definir o status no header com o código correspondente; a W3C (é claro) tem todas as definições que você precisa:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
E definir um header é algo tão simples como:
header('HTTP/1.1 304 Not Modified');
Se quiser, pode usar echo para exibir alguma mensagem indicando o que aconteceu, mas não é recomendável. O header deve prover informação suficiente sobre o status (dê uma olhada na quantidade de headers no link mencionado acima), e deve ser interpretado por quem for acessar seu Web Service. Nada de repetir informação!
Agora é com você. Já deu pra perceber que implementar aplicações RESTful não é nada de outro mundo e não requer nada além do que você já tem; também ficou claro que a arquitetura da aplicação, o grande ponto do REST, resulta numa interface extremamente simples e funcional para acessar sua aplicação num abiente distribuído.
em Setembro 20, 2008 em 12:17 pm
[...] a parte 1 deste artigo (esta que você está lendo) tem tido muito mais visualizações do que a parte 2, o que me deixou um pouco receoso; isto é uma introdução programática ao REST, uma abordagem [...]
em Dezembro 16, 2008 em 1:24 am
Oi Rafael,
Minha dúvida é o seguinte: tenho um link que retorna um arquivo XML.
Só que para ter o retorno do conteúdo, o browser abre uma janela pedindo login e senha. Eu já tenho o login e a senha, mas preciso saber como colocar este login e senha no código php na hora de chamar o link XML.
Assim evito de o usuário ter que digitar este login e senha toda vez que o sistema for acessar o arquivo XML.
em Novembro 8, 2009 em 12:25 pm
Legal sua abordagem sobre restful. Bem simples e direta informando o que é o que se pode fazer.
Sou novato no php e achei muito informativo.
Estava olhando exemplos de grids com extjs: http://www.extjs.com
E vi em um deles uma abordagem restful, para fazer update, insert e delete de uma grid então resolvi pesquisar sobre o que era restful.
Agora vou procurar saber mais sobre os metodos put e delete do http.
Thank you.