]> granicus.if.org Git - php/commitdiff
HTTP compression support (gzip and deflate)
authorDmitry Stogov <dmitry@php.net>
Wed, 25 Feb 2004 14:04:41 +0000 (14:04 +0000)
committerDmitry Stogov <dmitry@php.net>
Wed, 25 Feb 2004 14:04:41 +0000 (14:04 +0000)
ext/soap/TODO
ext/soap/php_http.c
ext/soap/php_soap.h
ext/soap/soap.c

index 70416df660224a241186b45fcfc59cf44f5a8180..edee329fdbeb5ccb2b42602953fe0e997ad94ea9 100644 (file)
@@ -88,7 +88,7 @@ Transport
 ---------
 ? HTTP status codes
 ? HTTP chunked Transfer-Encoding
-- support for HTTP compression (gzip,x-gzip,defalte)
+? support for HTTP compression (gzip,x-gzip,defalte)
 - transport abstraction layer???
 
 Interop Testing
index 137e50f7154d11822952b98cc3af533b2f0996dc..bc73e31464f9cd5459796c72e029ac40b22411c8 100644 (file)
@@ -173,9 +173,9 @@ static php_stream* http_connect(zval* this_ptr, php_url *phpurl, int use_ssl, in
 
 int send_http_soap_request(zval *this_ptr, xmlDoc *doc, char *location, char *soapaction, int soap_version TSRMLS_DC)
 {
-       xmlChar *buf;
+       xmlChar *buf, *request;
        smart_str soap_headers = {0};
-       int buf_size,err;
+       int buf_size, request_size, err;
        php_url *phpurl = NULL;
        php_stream *stream;
        zval **trace, **tmp;
@@ -305,8 +305,62 @@ int send_http_soap_request(zval *this_ptr, xmlDoc *doc, char *location, char *so
                                smart_str_append_const(&soap_headers, "\"\r\n");
                        }
                }
+
+         request = buf;
+         request_size = buf_size;
+               if (zend_hash_find(Z_OBJPROP_P(this_ptr), "compression", sizeof("compression"), (void **)&tmp) == SUCCESS && Z_TYPE_PP(tmp) == IS_LONG) {
+                       int level = Z_LVAL_PP(tmp) & 0x0f;
+                       int kind  = Z_LVAL_PP(tmp) & SOAP_COMPRESSION_DEFLATE;
+
+                 if ((Z_LVAL_PP(tmp) & SOAP_COMPRESSION_ACCEPT) != 0) {
+                               smart_str_append_const(&soap_headers,"Accept-Encoding: gzip, deflate\r\n");
+                 }
+                 if (level > 0) {
+                               zval func;
+                               zval retval;
+                       zval param1, param2, param3;
+                               zval *params[3];
+                               int n;
+
+
+                               params[0] = &param1;
+                               INIT_PZVAL(params[0]);
+                               params[1] = &param2;
+                               INIT_PZVAL(params[1]);
+                               params[2] = &param3;
+                               INIT_PZVAL(params[2]);
+                               ZVAL_STRINGL(params[0], buf, buf_size, 0);
+                               ZVAL_LONG(params[1], level);
+                   if (kind == SOAP_COMPRESSION_DEFLATE) {
+                       n = 2;
+                                       ZVAL_STRING(&func, "gzcompress", 0);
+                                       smart_str_append_const(&soap_headers,"Content-Encoding: deflate\r\n");
+                   } else {
+                     n = 3;
+                                       ZVAL_STRING(&func, "gzencode", 0);
+                                       smart_str_append_const(&soap_headers,"Content-Encoding: gzip\r\n");
+                                       ZVAL_LONG(params[2], 1);
+                     /* (SOAP_COMPRESSION_GZIP */
+                   }
+                               if (call_user_function(CG(function_table), (zval**)NULL, &func, &retval, n, params TSRMLS_CC) == SUCCESS &&
+                                   Z_TYPE(retval) == IS_STRING) {
+                                       request = Z_STRVAL(retval);
+                                       request_size = Z_STRLEN(retval);
+                               } else {
+                       php_url_free(phpurl);
+                       if (request != buf) {efree(request);}
+                       xmlFree(buf);
+                       smart_str_free(&soap_headers);
+                       php_stream_close(stream);
+                       zend_hash_del(Z_OBJPROP_P(this_ptr), "httpsocket", sizeof("httpsocket"));
+                       zend_hash_del(Z_OBJPROP_P(this_ptr), "_use_proxy", sizeof("_use_proxy"));
+                       add_soap_fault(this_ptr, "HTTP", "Compression Failed", NULL, NULL TSRMLS_CC);
+                       return FALSE;
+                               }
+                 }
+               }
                smart_str_append_const(&soap_headers,"Content-Length: ");
-               smart_str_append_long(&soap_headers, buf_size);
+               smart_str_append_long(&soap_headers, request_size);
                smart_str_append_const(&soap_headers, "\r\n");
 
                /* HTTP Authentication */
@@ -358,12 +412,13 @@ int send_http_soap_request(zval *this_ptr, xmlDoc *doc, char *location, char *so
                        }
                }
                smart_str_append_const(&soap_headers, "\r\n");
-               smart_str_appendl(&soap_headers, buf, buf_size);
+               smart_str_appendl(&soap_headers, request, request_size);
                smart_str_0(&soap_headers);
 
                err = php_stream_write(stream, soap_headers.c, soap_headers.len);
                if (err != soap_headers.len) {
                        php_url_free(phpurl);
+                       if (request != buf) {efree(request);}
                        xmlFree(buf);
                        smart_str_free(&soap_headers);
                        php_stream_close(stream);
@@ -376,6 +431,7 @@ int send_http_soap_request(zval *this_ptr, xmlDoc *doc, char *location, char *so
 
        }
        php_url_free(phpurl);
+       if (request != buf) {efree(request);}
        xmlFree(buf);
        return TRUE;
 }
@@ -386,9 +442,10 @@ int get_http_soap_response(zval *this_ptr, char **buffer, int *buffer_len TSRMLS
        int http_header_size, http_body_size, http_close;
        php_stream *stream;
        zval **trace, **tmp;
-       charconnection;
+       char *connection;
        int http_1_1 = 0;
        int http_status = 0;
+       char *content_encoding;
 
        if (zend_hash_find(Z_OBJPROP_P(this_ptr), "httpsocket", sizeof("httpsocket"), (void **)&tmp) == SUCCESS) {
                php_stream_from_zval_no_verify(stream,tmp);
@@ -473,11 +530,6 @@ int get_http_soap_response(zval *this_ptr, char **buffer, int *buffer_len TSRMLS
                return FALSE;
        }
 
-       if (zend_hash_find(Z_OBJPROP_P(this_ptr), "trace", sizeof("trace"), (void **) &trace) == SUCCESS &&
-           Z_LVAL_PP(trace) > 0) {
-               add_property_stringl(this_ptr, "__last_response", http_body, http_body_size, 1);
-       }
-
        /* See if the server requested a close */
        http_close = TRUE;
        connection = get_http_header_value(http_headers,"Proxy-Connection: ");
@@ -591,8 +643,55 @@ int get_http_soap_response(zval *this_ptr, char **buffer, int *buffer_len TSRMLS
                efree(cookie);
        }
 
-       *buffer = http_body;
-       *buffer_len = http_body_size;
+       content_encoding = get_http_header_value(http_headers,"Content-Encoding: ");
+       if (content_encoding) {
+               zval func;
+               zval retval;
+         zval param;
+               zval *params[1];
+
+               if ((strcmp(content_encoding,"gzip") == 0 ||
+                    strcmp(content_encoding,"x-gzip") == 0) &&
+                    zend_hash_exists(EG(function_table), "gzinflate", sizeof("gzinflate"))) {
+                       ZVAL_STRING(&func, "gzinflate", 0);
+                       params[0] = &param;
+                       ZVAL_STRINGL(params[0], http_body+10, http_body_size-10, 0);
+                       INIT_PZVAL(params[0]);
+               } else if (strcmp(content_encoding,"deflate") == 0 &&
+                          zend_hash_exists(EG(function_table), "gzuncompress", sizeof("gzuncompress"))) {
+                       ZVAL_STRING(&func, "gzuncompress", 0);
+                       params[0] = &param;
+                       ZVAL_STRINGL(params[0], http_body, http_body_size, 0);
+                       INIT_PZVAL(params[0]);
+               } else {
+                       efree(content_encoding);
+                       efree(http_headers);
+                       efree(http_body);
+                       add_soap_fault(this_ptr, "HTTP", "Unknown Content-Encoding", NULL, NULL TSRMLS_CC);
+                       return FALSE;
+               }
+               if (call_user_function(CG(function_table), (zval**)NULL, &func, &retval, 1, params TSRMLS_CC) == SUCCESS &&
+                   Z_TYPE(retval) == IS_STRING) {
+                       efree(http_body);
+                       *buffer = Z_STRVAL(retval);
+                       *buffer_len = Z_STRLEN(retval);
+               } else {
+                       efree(content_encoding);
+                       efree(http_headers);
+                       efree(http_body);
+                       add_soap_fault(this_ptr, "HTTP", "Can't uncompress compressed response", NULL, NULL TSRMLS_CC);
+                       return FALSE;
+               }
+               efree(content_encoding);
+       } else {
+               *buffer = http_body;
+               *buffer_len = http_body_size;
+       }
+       if (zend_hash_find(Z_OBJPROP_P(this_ptr), "trace", sizeof("trace"), (void **) &trace) == SUCCESS &&
+           Z_LVAL_PP(trace) > 0) {
+               add_property_stringl(this_ptr, "__last_response", *buffer, *buffer_len, 1);
+       }
+
        efree(http_headers);
        return TRUE;
 }
index 080279893f398dde56908c6fdcc0cda48d36da6b..1ccbfd59514ec592a73062ecccf6215569a6dfd7 100644 (file)
@@ -138,6 +138,10 @@ struct _soapService {
 #define SOAP_1_2_ACTOR_NONE             "http://www.w3.org/2003/05/soap-envelope/role/none"
 #define SOAP_1_2_ACTOR_UNLIMATERECEIVER "http://www.w3.org/2003/05/soap-envelope/role/ultimateReceiver"
 
+#define SOAP_COMPRESSION_ACCEPT  0x20
+#define SOAP_COMPRESSION_GZIP    0x00
+#define SOAP_COMPRESSION_DEFLATE 0x10
+
 ZEND_BEGIN_MODULE_GLOBALS(soap)
        HashTable  defEncNs;     /* mapping of default namespaces to prefixes */
        HashTable  defEnc;
index ed512c24821b33fc2473d96ee8315767d1bd41c1..b933adecabce8f6b74400d00d08699fc9e728d8b 100644 (file)
@@ -505,6 +505,10 @@ PHP_MINIT_FUNCTION(soap)
        REGISTER_LONG_CONSTANT("SOAP_ACTOR_NONE", SOAP_ACTOR_NONE, CONST_CS | CONST_PERSISTENT);
        REGISTER_LONG_CONSTANT("SOAP_ACTOR_UNLIMATERECEIVER", SOAP_ACTOR_UNLIMATERECEIVER, CONST_CS | CONST_PERSISTENT);
 
+       REGISTER_LONG_CONSTANT("SOAP_COMPRESSION_ACCEPT", SOAP_COMPRESSION_ACCEPT, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("SOAP_COMPRESSION_GZIP", SOAP_COMPRESSION_GZIP, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("SOAP_COMPRESSION_DEFLATE", SOAP_COMPRESSION_DEFLATE, CONST_CS | CONST_PERSISTENT);
+
        REGISTER_LONG_CONSTANT("UNKNOWN_TYPE", UNKNOWN_TYPE, CONST_CS | CONST_PERSISTENT);
 
        REGISTER_LONG_CONSTANT("XSD_STRING", XSD_STRING, CONST_CS | CONST_PERSISTENT);
@@ -1251,7 +1255,42 @@ PHP_METHOD(soapserver, handle)
        if (ZEND_NUM_ARGS() == 0) {
                if (zend_hash_find(&EG(symbol_table), HTTP_RAW_POST_DATA, sizeof(HTTP_RAW_POST_DATA), (void **) &raw_post)!=FAILURE
                        && ((*raw_post)->type==IS_STRING)) {
-                       doc_request = soap_xmlParseMemory(Z_STRVAL_PP(raw_post),Z_STRLEN_PP(raw_post));
+                       zval **server_vars, **encoding;
+
+                       if (zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void **) &server_vars) == SUCCESS &&
+                           Z_TYPE_PP(server_vars) == IS_ARRAY &&
+                           zend_hash_find(Z_ARRVAL_PP(server_vars), "HTTP_CONTENT_ENCODING", sizeof("HTTP_CONTENT_ENCODING"), (void **) &encoding)==SUCCESS &&
+                           Z_TYPE_PP(encoding) == IS_STRING) {
+                               zval func;
+                               zval retval;
+                         zval param;
+                               zval *params[1];
+
+                               if ((strcmp(Z_STRVAL_PP(encoding),"gzip") == 0 ||
+                                    strcmp(Z_STRVAL_PP(encoding),"x-gzip") == 0) &&
+                                   zend_hash_exists(EG(function_table), "gzinflate", sizeof("gzinflate"))) {
+                                       ZVAL_STRING(&func, "gzinflate", 0);
+                                       params[0] = &param;
+                                       ZVAL_STRINGL(params[0], Z_STRVAL_PP(raw_post)+10, Z_STRLEN_PP(raw_post)-10, 0);
+                                       INIT_PZVAL(params[0]);
+                               } else if (strcmp(Z_STRVAL_PP(encoding),"deflate") == 0 &&
+                          zend_hash_exists(EG(function_table), "gzuncompress", sizeof("gzuncompress"))) {
+                                       ZVAL_STRING(&func, "gzuncompress", 0);
+                                       params[0] = &param;
+                                       ZVAL_STRINGL(params[0], Z_STRVAL_PP(raw_post), Z_STRLEN_PP(raw_post), 0);
+                                       INIT_PZVAL(params[0]);
+                               } else {
+                                       php_error(E_ERROR,"Request is compressed with unknown compression '%s'",Z_STRVAL_PP(encoding));
+                               }
+                               if (call_user_function(CG(function_table), (zval**)NULL, &func, &retval, 1, params TSRMLS_CC) == SUCCESS &&
+                                   Z_TYPE(retval) == IS_STRING) {
+                                       doc_request = soap_xmlParseMemory(Z_STRVAL(retval),Z_STRLEN(retval));
+                               } else {
+                                       php_error(E_ERROR,"Can't uncompress compressed request");
+                               }
+                       } else {
+                               doc_request = soap_xmlParseMemory(Z_STRVAL_PP(raw_post),Z_STRLEN_PP(raw_post));
+                       }
                } else {
                        if (!zend_ini_long("always_populate_raw_post_data", sizeof("always_populate_raw_post_data"), 0)) {
                                php_error(E_ERROR, "PHP-SOAP requires 'always_populate_raw_post_data' to be on please check your php.ini file");
@@ -1774,6 +1813,15 @@ PHP_METHOD(soapclient, soapclient)
                        add_property_bool(this_ptr, "_exceptions", 0);
                }
 #endif
+               if (zend_hash_find(ht, "compression", sizeof("compression"), (void**)&tmp) == SUCCESS &&
+                   Z_TYPE_PP(tmp) == IS_LONG &&
+             zend_hash_exists(EG(function_table), "gzinflate", sizeof("gzinflate")) &&
+             zend_hash_exists(EG(function_table), "gzdeflate", sizeof("gzdeflate")) &&
+             zend_hash_exists(EG(function_table), "gzuncompress", sizeof("gzuncompress")) &&
+             zend_hash_exists(EG(function_table), "gzcompress", sizeof("gzcompress")) &&
+             zend_hash_exists(EG(function_table), "gzencode", sizeof("gzencode"))) {
+                       add_property_long(this_ptr, "compression", Z_LVAL_PP(tmp));
+               }
        } else if (wsdl == NULL) {
                php_error(E_ERROR, "Can't create SoapClient. 'location' and 'uri' options are requred in nonWSDL mode.");
                return;