A especificação do SOAP define uma metodologia para o relato de erros do servidor para o cliente. Já vimos exemplos em que o cliente verifica se ocorreram erros do lado do servidor e vai atuar de acordo com as situações detetadas. Nalguns casos os erros são gerados não por código de quem implementou o servidor mas automaticamente, por exemplo, quando um cliente invoca uma funcionalidade que não existe do lado do servidor.
Suponha que queríamos adicionar a verificação de tipos ao exemplo anterior. Podíamos verificar o tipo dos parâmetros enviados e gerar um erro para as situações anómalas: SOAP Fault. Note que nesta verificação teremos de ser um pouco permissivos para acomodar a tipagem implícita: quando estivermos à espera dum xsd:float também devemos aceitar um xsd:integer ou mesmo uma string (se esta contiver apenas digitos), ou seja, para um tipo mais específico devemos aceitar os menos específicos. Esta situação é normal se usarmos Forms para ler os argumentos ou passarmos estes no URL. Nestas situações o PHP assume sempre os valores como sendo do tipo string.
Apresentam-se a seguir as modificações introduzidas no servidor.
Exemplo 2.18. Verificação de tipos no servidor
... function soma($n1, $n2) { // verifica se é int ou se é uma string com um int if (!(( is_int($n1) || ctype_digit($n1) )&&( is_int($n2) || ctype_digit($n2) ))) { return new soap_fault('SERVER', '', 'n1 e n2 devem ser inteiros', 'O valor recebido para n1 é '.gettype($n1). ' e para n2 é '.gettype($n2)); } else { return new soapval('res', 'xsd:integer', $n1+$n2); } } ...
É preciso alterar os métodos para incluir a verificação de tipos; No caso do inteiro temos de verificar duas coisas: se o parâmetro é inteiro (e está tudo bem) ou se é uma string contendo apenas digitos; A função is_int(var) verifica se var é do tipo inteiro; A função ctype_digit(var) testa se var é uma string e neste caso se é composta apenas por digitos. | |
No método
| |
Com o método soapval constrói-se um resultado devidamente tipado. Os parâmetros são os seguintes:
|
No nosso servidor temos dois serviços que tratam inteiros, como vimos acima, e temos dois serviços que lidam com números reais: a multiplicação e a divisão.
As modificações introduzidas nestes últimos apresentam-se a seguir.
Exemplo 2.19. Verificação de tipos nos métodos mul e div
... function mul($n1, $n2) { // verifica se é float if (!(is_numeric($n1) && is_numeric($n2) )) { return new soap_fault('SERVER', '', 'n1 e n2 devem ser reais', 'O valor recebido para n1 é ' .gettype($n1). ' e para n2 é '.gettype($n2)); } else { return new soapval('res', 'xsd:float', $n1*$n2); } } ...
O nosso cliente não precisa ser alterado. Relembre que os dois parâmetros lidos são usados para invocar todos os métodos. Como dois métodos aceitam parâmetros inteiros e os outros parâmetros reais, para um determinado par de parâmetros dois dos métodos irão originar erros. Vejamos as mensagens geradas para determinados pares de parâmetros.
Exemplo 2.20. Parâmetros inteiros: 7 e 5
POST /nusoap-0.9.5/Soma2nums/serv-aritmetica3.php HTTP/1.0 Host: localhost:8888 User-Agent: NuSOAP/0.9.5 (1.123) Content-Type: text/xml; charset=ISO-8859-1 SOAPAction: "uri:ws.di.uminho.pt/Aritmetica/mul" Content-Length: 532 <?xml version="1.0" encoding="ISO-8859-1"?> <SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <ns8216:div xmlns:ns8216="uri:ws.di.uminho.pt/Aritmetica"> <n1 xsi:type="xsd:string">7</n1> <n2 xsi:type="xsd:string">5</n2> </ns8216:div> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
Repare nos parâmetros que são enviados como xsd:string.
HTTP/1.1 200 OK Date: Wed, 19 Dec 2012 20:52:00 GMT Server: Apache/2.2.21 (Unix) mod_ssl/2.2.21 OpenSSL/0.9.8r DAV/2 PHP/5.3.6 X-Powered-By: PHP/5.3.6 X-SOAP-Server: NuSOAP/0.9.5 (1.123) Content-Length: 510 Connection: close Content-Type: text/xml; charset=ISO-8859-1 <?xml version="1.0" encoding="ISO-8859-1"?> <SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <ns1:divResponse xmlns:ns1="uri:ws.di.uminho.pt/Aritmetica"> <res xsi:type="xsd:float">1.4</res> </ns1:divResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
O nosso cliente está a chamar os 4 métodos para o mesmo par de parâmetros. Cada chamada corresponde a um par de mensagens SOAP, pedido e resposta. Este par, pedido e resposta, correspondem à última chamada, para o método div.
Neste caso, como a divisão inteira não é exata o resultado devolvido é do tipo xsd:float. Vejamos um caso em que a divisão é exata.
Exemplo 2.21. Parâmetros inteiros: 8 e 4
POST /nusoap-0.9.5/Soma2nums/serv-aritmetica3.php HTTP/1.0 Host: localhost:8888 User-Agent: NuSOAP/0.9.5 (1.123) Content-Type: text/xml; charset=ISO-8859-1 SOAPAction: "uri:ws.di.uminho.pt/Aritmetica/mul" Content-Length: 532 <?xml version="1.0" encoding="ISO-8859-1"?> <SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <ns8216:div xmlns:ns8216="uri:ws.di.uminho.pt/Aritmetica"> <n1 xsi:type="xsd:string">8</n1> <n2 xsi:type="xsd:string">4</n2> </ns8216:div> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
HTTP/1.1 200 OK Date: Wed, 19 Dec 2012 20:52:00 GMT Server: Apache/2.2.21 (Unix) mod_ssl/2.2.21 OpenSSL/0.9.8r DAV/2 PHP/5.3.6 X-Powered-By: PHP/5.3.6 X-SOAP-Server: NuSOAP/0.9.5 (1.123) Content-Length: 510 Connection: close Content-Type: text/xml; charset=ISO-8859-1 <?xml version="1.0" encoding="ISO-8859-1"?> <SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <ns1:divResponse xmlns:ns1="uri:ws.di.uminho.pt/Aritmetica"> <res xsi:type="xsd:int">2</res> </ns1:divResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
A figura seguinte mostra as respostas depois de tratadas pelo cliente.
Podemos observar que todos os resultados são inteiros apesar de termos indicado explicitamente que a divisão e a multiplicação retornariam resultados reais.
O contrário também se verifica se um dos parâmetros for real como já vimos atrás.