├── README.md ├── soap ├── mode-non-wsdl │ └── user │ │ ├── index.php │ │ └── server.php ├── mode-wsdl │ └── user │ │ ├── api.wsdl │ │ ├── index.php │ │ └── server.php └── xml │ └── user │ ├── request │ ├── requestCreate.xml │ ├── requestDelete.xml │ └── requestUpdate.xml │ └── response │ ├── responseCreate.xml │ ├── responseDelete.xml │ └── responseUpdate.xml └── xml-rpc ├── user ├── curl.php ├── index.php └── server.php └── xml └── user ├── request ├── requestCreate.xml ├── requestDelete.xml └── requestUpdate.xml └── response ├── responseCreate.xml ├── responseDelete.xml └── responseUpdate.xml /README.md: -------------------------------------------------------------------------------- 1 |

WEB SERVICES PHP - UMA ABORDAGEM SOBRE RPC, SOAP

2 | 3 | 4 |

1 - WEB SERVICES - DEFINIÇÃO E APLICABILIDADE

5 | 6 |

7 | Tem se tornado cada vez mais comum pensar em aplicações que são criadas consumindo ou expondo algum tipo de funcionalidade através de implementações de serviços. Web services definem como pode acontecer essas interações entre softwares que estão sendo executados em plataformas distintas. 8 | Essa interação comumente acontece fazendo uso de um meio comun de tráfego como por exemplo, o protocolo HTTP e um formato de arquivo que de formato comum tais como, XML ou JSON. 9 |

10 |

11 | Algumas variações de web services seriam, Rpc (Xml-rpc), Soap e Rest, cada um possuindo características próprias de implementação. Serviços web são úteis para que softwares em diferentes máquinas executando com diferentes tecnologias possam se comunicar, por exemplo um sistema legado que só executa suas funções em ambiente local, pode expor esssas funcionalidades utilizando algum dos serviços mencionados acima, tornando possível o consumo dessas funcionalidades por clientes web ou mobile. 12 | Será demonstrado e explicado como pode acontecer a implementação de uma Api de Usuários, utilizando serviços XML-RPC, SOAP e REST. 13 |

14 | 15 | 16 |

2 - SERVIÇOS RPC - O QUE SÃO E COMO FUNCIONAM?

17 | 18 |

19 | Uma implementação de web service seriam os serviços RPC que significam Remote Procedure Call, para o português, Chamada para Procedimentos Remotos. Serviços RPC consistem na chamada de funções entre duas máquinas seguindo o conceito de cliente/servidor, onde cada cliente realiza uma requisição HTTP POST normalmente para um único ponto de entrada enviando um documento XML que específica a função a ser chamada e seus respectivos parâmetros, de maneira similar a realização de chamadas de funções locais. 20 |

21 |

22 | Para se trabalhar com serviços RPC uma abordagem comum seria seguir uma implementação XML-RPC (http://xmlrpc.scripting.com/spec.html), no caso o PHP possui uma série de funções que permitem a criação de clientes e servidores XML-RPC. 23 |

24 | 25 |

2.2 - FUNÇÕES PHP PARA XML-RPC

26 | 27 |

28 | O PHP fornece um conjuntos de funções úteis para que seja possível trabalhar com serviços XML-RPC. Utilizando as funções nativas da linguagem conseguimos de forma relativamente simples criar um cliente e um servidor XML-RPC. 29 |

30 |

31 | Através do uso de recursos oferecidos pela própria linguagem PHP será criado um cliente XML-RPC que irá consumir uma Api de usuários que estará disponível através de um servidor XML-RPC. 32 |

33 | 34 | ```php 35 | [ 46 | 'method' => "POST", 47 | 'header' => "Content-Type: text/xml", 48 | ‘content' => $request]]); 49 | 50 | $server = 'http://localhost/web-services/xml-rpc/user/server.php'; 51 | 52 | $file = file_get_contents($server, false, $context); 53 | 54 | $response = xmlrpc_decode($file); 55 | 56 | var_dump($response); 57 | ``` 58 | 59 |

60 | O código acima ilustra como pode ser feita uma chamada a um procedimento remoto utilizando recursos do PHP. 61 | A primeira linha do script é responsável por codificar o arquivo XML a ser enviado no corpo de uma uma requisição POST. Abaixo exemplo do arquivo enviado na chamada de função getUser(): 62 |

63 | 64 | ~~~xml 65 | 66 | 67 | getUser 68 | 69 | 70 | ~~~ 71 |

72 | O exemplo do arquivo de envio para uma chamada á função createUser() seria: 73 |

74 | 75 | ~~~xml 76 | 77 | 78 | createUser 79 | 80 | 81 | 82 | eduardo 83 | 84 | 85 | 86 | 87 | ~~~ 88 | 89 |

90 | A chamada a qualquer método descrito no código é válida, após codificar o arquivo a ser enviado na requisição é criado um stream de rede utilizando o protocolo HTTP possuindo as seguintes características o método POST, o content-type para text/xml, o content possuindo o arquivo gerado por xmlrpc_encode_request(), a seguir é utilizado a função file_get_contents() para ler o conteúdo retornado desse stream para uma string, que então através da função xmlrpc_decode() é decodificada e seu resultado exibido. 91 |

92 | 93 |

94 | Este mesmo processamento poderia ser feito utilizando curl, como pode ser visto no código abaixo: 95 |

96 | 97 | ```php 98 | 125 | Variando a forma como pode ser feita a requisição. 126 | O servidor que irá responder por cada requisição pode ser representado pelo seguinte código: 127 |

128 | 129 | ```php 130 | 153 | Acima estão descritas as funções que podem ser chamadas remotamente, elas recebem em seu primeiro parâmetros uma string $method_name, que é o nome pelo qual essa função será referenciada, e chamada externamete, já o segundo parâmetro trata-se de um array contendo os dados a serem processados pelas funções. 154 |

155 | 156 | ```php 157 | 177 | O código acima inicia recuperando os valores enviados no corpo de uma requisição HTTP utilizando file_get_contents("php://input"), em seguida através da função xmlrpc_server_create() é iniciado um servidor XML-RPC, 178 | o que permite registrar funções que possam ser chamadas por um client XML-RPC. Com o uso da função xmlrpc_server_register_method(), é possível registrarmos funções no servidor que foi iniciado, ela recebe 3 parâmetros de entrada, o primeiro é o server que foi iniciado a partir de xmlrpc_server_create(), o segundo parâmetro se refere ao $method_name, 179 | valor este, pelo qual o client XML-RPC chama a função, o terceiro parâmetro é a função própriamente dita que foi referenciada por method_name. 180 | Logo ao registrar xmlrpc_server_register_method($server, "getUser", "get"), o client irá chamar getUser e não get, podendo ser usado para a criação de uma Api mais 181 | condizente com a realização do serviço. 182 | Em seguida é definido o content-type para text/xml para ser enviado no retorno e, então, é realizada uma chamada para 183 | xmlrpc_server_call_method(), recebendo 3 parâmetros, o primeiro é o servidor a ser executado, o segundo o 184 | request enviado por POST, e o terceiro um array, essa função é encarregada por executar a função informada no request 185 | no servidor que ela estiver registrada. 186 |

187 | 188 |

3 - SOAP - O QUE É SOAP E SEU FUNCIONAMENTO?

189 | 190 |

191 | SOAP provê um mecanismo para troca de informação em ambientes descentralizados, é especificado pela w3c 192 | contendo duas versões SOAP 1.1 e SOAP 1.2. 193 | Baseado em XML consiste na troca de informações utilizando HTTP ou outro protocolo 194 | para o trafégo de dados. 195 | SOAP é um tipo de serviço que pode ou não trabalhar em conjunto com 196 | WSDL que seriam WEB SERVICES DESCRIPTION LANGUAGE, consiste em um documento xml 197 | que contém informações relevantes sobre o serviço, como por exemplo, 198 | métodos que podem ser chamados, parâmetros de entrada e saída, meios de acesso. 199 |

200 | 201 |

202 | Abaixo segue um exemplo de WSDL utilizado para a Api de usuários: 203 |

204 | 205 | ~~~xml 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | ~~~ 295 | 296 |

297 | Acima está o código de wsdl utilizando durante o exemplo. Nele estão descritos os métodos 298 | e seus parâmetros e entrada, retorno e formas de acesso. 299 | Para mais detalhes sobre consulte (https://www.w3.org/TR/wsdl). 300 |

301 | 302 |

303 | Possui um formato de requisição bem específicado, os documentos XML que são trocados nas requisições são conhecidos como Envelopes Soap, sendo estes determinados pelas marcações presentes nestes documentos, por exemplo: 304 |

305 | 306 | ~~~xml 307 | 308 | 315 | 316 | 317 | eduardo 318 | 319 | 320 | 321 | ~~~ 322 | 323 |

324 | O código acima demonstra o formato existente em um envelope soap. As características presentes, 325 | a definição de envelope SOAP-ENV:Envelope, elementos estes 326 | obrigatórios para que esse documento possa ser compreendido por um servidor Soap, 327 | outra característica obrigatória são os elementos body, descritos SOAP-ENV:Body, 328 | entre o elemento body estão descritos o método de acesso e os parâmetros a serem 329 | processados, elemento que pode estar presente mas não é obrigatório, são os elementos header. 330 |

331 |

332 | Da mesma maneira será enviado na resposta um documento XML possuindo marcação semelhante ao de requisição. 333 | Abaixo é apresentado o documento XML enviado na resposta: 334 |

335 | 336 | ~~~xml 337 | 338 | 345 | 346 | 347 | user eduardo created with success 348 | 349 | 350 | 351 | ~~~ 352 |

353 | As marcações e definições de envelope SOAP continuam sendo respeitadas. Para se obter mais detalhes sobre (https://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383494). 354 |

355 | 356 |

3.1 - INTERAGINDO COM SOAP EM PHP

357 | 358 |

359 | O fato de SOAP ser um protocolo muito bem específicado e padronizado junto a w3c 360 | faz com que implementações para este padrão existam nativamente na maioria das linguagens de programação 361 | e, com PHP não é diferente. 362 | Para se trabalhar com SOAP em PHP existem duas bibliotecas nativas SoapClient e SoapServer, 363 | ambas possuem um uso bem direto, por exemplo o código abaixo ilustra como poderia 364 | ser realizadas as chamadas a um serviço soap exemplificando uma Api de usuários: 365 |

366 | 367 | ```php 368 | 'http://localhost/web-services/soap/mode-non-wsdl/user', 373 | 'location' => 'http://localhost/web-services/soap/mode-non-wsdl/user/server.php']; 374 | $api = new SoapClient(null, $options); 375 | //$api = new SoapClient("api.wsdl", ['trace' => 1]); 376 | 377 | $users = $api->get(); 378 | 379 | foreach($users as $user) 380 | echo $user; 381 | 382 | echo $api->create('luiz'); 383 | echo $api->update(1, 'cesar'); 384 | echo $api->delete(1); 385 | ``` 386 | 387 |

388 | A primeira linha altera a opção de cache que está configurada no php.ini, 389 | isso se deve ao fato de estar configurada para 1, mantendo um cache de wsdl ativo. 390 | O primeiro caso trata-se de iniciar um SoapCLient sem o uso de wsdl, 391 | para isso é necessário informar um array que é criado na segunda linha do script que contém uri, 392 | que representa o namespace onde este serviço está alocado 393 | e o segundo índice se trata da localidade do serviço, estes valores só são obrigatórios 394 | para o uso sem wsdl, e estão representados por este trecho de 395 | código SoapClient(null, $options), iniciando assim um soap client sem wsdl. 396 | Da mesma forma é possível estar criando client soap informando um caminho válido para 397 | um wsdl. 398 |

399 |

400 | Feito isso, é possível então interagir com a Api de serviços que for oferecida, 401 | como por exemplo para criar um novo usuário $api->create('luiz'), 402 | acessando o método create do serviço soap, ou qualquer outro método que esteja 403 | disponível. 404 | Para criar um servidor que será capaz de responder a essas chamadas é utilizada a classe SoapClient, a partir dela é possível registrarmos classes ou funções como sendo serviços Soap, que podem ser acessados externamente, abaixo segue um exemplo de como poderia ser implementado os serviços de uma Api de usuários: 405 |

406 | 407 | ```php 408 | 'http://localhost/web-services/soap/mode-non-wsdl/user']); 431 | //$server = new SoapServer("api.wsdl"); 432 | 433 | $server->setClass('UserService'); 434 | 435 | $server->handle(); 436 | ``` 437 | 438 |

439 | Da mesma forma que SoapClient, SoapServer pode ser iniciada com ou sem wsdl, seguindo a mesma regra, porém desta vez o unico elemento necessário no modo sem wsdl, 440 | é a uri do serviço, onde ele está alocado. 441 |

442 | 443 |

444 | Com isso feito, é possível registrar uma classe ou um conjunto de funções como serviço, no caso é definido a 445 | class UserService, e qualquer método existente nele é disparado a partir de $server->handle(). 446 |

447 | -------------------------------------------------------------------------------- /soap/mode-non-wsdl/user/index.php: -------------------------------------------------------------------------------- 1 | 'http://localhost/web-services/soap/mode-non-wsdl/user', 4 | 'location' => 'http://localhost/web-services/soap/mode-non-wsdl/user/server.php' 5 | ]); 6 | 7 | $users = $api->get(); 8 | 9 | foreach($users as $user) 10 | echo $user. "
"; 11 | 12 | echo "Request for method create user.: " .$api->create('eduardo'). "
"; 13 | 14 | echo "Request for method update user.: " .$api->update(1, 'cesar'). "
"; 15 | 16 | echo "Request for method delete user.: " .$api->delete(1). "
"; -------------------------------------------------------------------------------- /soap/mode-non-wsdl/user/server.php: -------------------------------------------------------------------------------- 1 | 'http://localhost/web-services/soap/mode-non-wsdl/user']); 25 | 26 | $server->setClass('UserService'); 27 | 28 | $server->handle(); -------------------------------------------------------------------------------- /soap/mode-wsdl/user/api.wsdl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /soap/mode-wsdl/user/index.php: -------------------------------------------------------------------------------- 1 | 1]); 5 | 6 | $users = $api->get(); 7 | foreach($users as $user) 8 | echo $user; 9 | 10 | echo $api->create('luiz'); 11 | echo $api->update(1, 'cesar'); 12 | echo $api->delete(1); -------------------------------------------------------------------------------- /soap/mode-wsdl/user/server.php: -------------------------------------------------------------------------------- 1 | users = ['eduardo', 'paula', 'pedro']; 11 | } 12 | 13 | public function get() : array 14 | { 15 | return $this->users; 16 | } 17 | 18 | public function create(string $name) : string 19 | { 20 | return "user ".$name." created with success \n"; 21 | } 22 | 23 | public function update(int $id, string $name) : string 24 | { 25 | return "user updated with success \n"; 26 | } 27 | 28 | public function delete(int $id) : string 29 | { 30 | return "user ".$id." deleted with success \n"; 31 | } 32 | } 33 | 34 | $server = new SoapServer("api.wsdl"); 35 | 36 | $server->setClass('UserService'); 37 | 38 | $server->handle(); -------------------------------------------------------------------------------- /soap/xml/user/request/requestCreate.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | eduardo 12 | eduardo@teste.com.br 13 | 14 | 15 | -------------------------------------------------------------------------------- /soap/xml/user/request/requestDelete.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 1 12 | 13 | 14 | -------------------------------------------------------------------------------- /soap/xml/user/request/requestUpdate.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 1 12 | cesar 13 | cesar@teste.com.br 14 | 15 | 16 | -------------------------------------------------------------------------------- /soap/xml/user/response/responseCreate.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | user eduardo created with success 12 | 13 | 14 | -------------------------------------------------------------------------------- /soap/xml/user/response/responseDelete.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | user 1 deleted with success 12 | 13 | 14 | -------------------------------------------------------------------------------- /soap/xml/user/response/responseUpdate.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | user 1 updated with success 12 | 13 | 14 | -------------------------------------------------------------------------------- /xml-rpc/user/curl.php: -------------------------------------------------------------------------------- 1 | [ 13 | 'method' => "POST", 14 | 'header' => "Content-Type: text/xml", 15 | 'content' => $request 16 | ] 17 | ]); 18 | 19 | $server = 'http://localhost/web-services/xml-rpc/user/server.php'; 20 | 21 | $file = file_get_contents($server, false, $context); 22 | 23 | $response = xmlrpc_decode($file); 24 | 25 | var_dump($response); -------------------------------------------------------------------------------- /xml-rpc/user/server.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | createUser 4 | 5 | 6 | 7 | eduardo 8 | 9 | 10 | 11 | 12 | eduardo@teste.com.br 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /xml-rpc/xml/user/request/requestDelete.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | deleteUser 4 | 5 | 6 | 7 | 1 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /xml-rpc/xml/user/request/requestUpdate.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | updateUser 4 | 5 | 6 | 7 | 1 8 | 9 | 10 | 11 | 12 | eduardo 13 | 14 | 15 | 16 | 17 | eduardo@teste.com.br 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /xml-rpc/xml/user/response/responseCreate.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | user eduardo created with success 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /xml-rpc/xml/user/response/responseDelete.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | user 1 deleted with success 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /xml-rpc/xml/user/response/responseUpdate.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | user 1 updated with success 7 | 8 | 9 | 10 | --------------------------------------------------------------------------------