From a91d9c18e9846c3c4dc80b8bcbece92774ee4a2e Mon Sep 17 00:00:00 2001 From: matyhtf Date: Thu, 1 Feb 2018 18:20:11 +0800 Subject: [PATCH] fixed http2 cookie bugs --- swoole_http_v2_client.c | 61 +++++++++++++++++++++++++++--------- swoole_http_v2_client.h | 9 ++++-- swoole_http_v2_client_coro.c | 27 +++++----------- 3 files changed, 62 insertions(+), 35 deletions(-) diff --git a/swoole_http_v2_client.c b/swoole_http_v2_client.c index 2d4c0a2fc29..fde9d971423 100644 --- a/swoole_http_v2_client.c +++ b/swoole_http_v2_client.c @@ -26,6 +26,8 @@ static zend_class_entry *swoole_http2_client_class_entry_ptr; static zend_class_entry swoole_http2_response_ce; zend_class_entry *swoole_http2_response_class_entry_ptr; +swString *cookie_buffer = NULL; + enum { HTTP2_CLIENT_PROPERTY_INDEX = 3, @@ -98,9 +100,15 @@ void swoole_http2_client_init(int module_number TSRMLS_DC) swoole_http2_response_class_entry_ptr = zend_register_internal_class(&swoole_http2_response_ce TSRMLS_CC); SWOOLE_CLASS_ALIAS(swoole_http2_response, "Swoole\\Http2\\Response"); + zend_declare_property_long(swoole_http2_response_class_entry_ptr, SW_STRL("errCode")-1, 0, ZEND_ACC_PUBLIC TSRMLS_CC); zend_declare_property_long(swoole_http2_response_class_entry_ptr, SW_STRL("statusCode")-1, 0, ZEND_ACC_PUBLIC TSRMLS_CC); zend_declare_property_null(swoole_http2_response_class_entry_ptr, SW_STRL("body")-1, ZEND_ACC_PUBLIC TSRMLS_CC); zend_declare_property_null(swoole_http2_response_class_entry_ptr, SW_STRL("streamId")-1, ZEND_ACC_PUBLIC TSRMLS_CC); + + if (cookie_buffer == NULL) + { + cookie_buffer = swString_new(8192); + } } static PHP_METHOD(swoole_http2_client, __construct) @@ -226,7 +234,7 @@ static int http2_client_build_header(zval *zobject, http2_client_request *req, c } if (strncasecmp("Host", key, keylen) == 0) { - http2_add_header(&nv[3], ZEND_STRL(":authority"), Z_STRVAL_P(value), Z_STRLEN_P(value)); + http2_add_header(&nv[HTTP2_CLIENT_HOST_HEADER_INDEX], ZEND_STRL(":authority"), Z_STRVAL_P(value), Z_STRLEN_P(value)); find_host = 1; } else @@ -239,25 +247,14 @@ static int http2_client_build_header(zval *zobject, http2_client_request *req, c } if (!find_host) { - http2_add_header(&nv[3], ZEND_STRL(":authority"), hcc->host, hcc->host_len); + http2_add_header(&nv[HTTP2_CLIENT_HOST_HEADER_INDEX], ZEND_STRL(":authority"), hcc->host, hcc->host_len); } zval *zcookie = sw_zend_read_property(swoole_http2_client_class_entry_ptr, zobject, ZEND_STRL("cookies"), 1 TSRMLS_CC); //http cookies if (zcookie && !ZVAL_IS_NULL(zcookie)) { - zend_size_t len; - smart_str formstr_s = { 0 }; - char *formstr = sw_http_build_query(zcookie, &len, &formstr_s TSRMLS_CC); - if (formstr == NULL) - { - swoole_php_error(E_WARNING, "http_build_query failed."); - } - else - { - http2_add_header(&nv[3], ZEND_STRL("cookie"), formstr, len); - smart_str_free(&formstr_s); - } + http2_add_cookie(&nv, &index, zcookie TSRMLS_CC); } ssize_t rv; @@ -308,6 +305,42 @@ static int http2_client_build_header(zval *zobject, http2_client_request *req, c return rv; } +void http2_add_cookie(nghttp2_nv *nv, int *index, zval *cookies TSRMLS_DC) +{ + char *key; + uint32_t keylen; + int keytype; + zval *value = NULL; + char *encoded_value; + uint32_t offest = 0; + swString_clear(cookie_buffer); + + SW_HASHTABLE_FOREACH_START2(Z_ARRVAL_P(cookies), key, keylen, keytype, value) + if (HASH_KEY_IS_STRING != keytype) + { + continue; + } + convert_to_string(value); + if (Z_STRLEN_P(value) == 0) + { + continue; + } + + swString_append_ptr(cookie_buffer, key, keylen); + swString_append_ptr(cookie_buffer, "=", 1); + + int encoded_value_len; + encoded_value = sw_php_url_encode(Z_STRVAL_P(value), Z_STRLEN_P(value), &encoded_value_len); + if (encoded_value) + { + swString_append_ptr(cookie_buffer, encoded_value, encoded_value_len); + efree(encoded_value); + http2_add_header(&nv[(*index)++], ZEND_STRL("cookie"), cookie_buffer->str + offest, keylen + 1 + encoded_value_len); + offest += keylen + 1 + encoded_value_len; + } + SW_HASHTABLE_FOREACH_END(); +} + int http2_client_parse_header(http2_client_property *hcc, http2_client_stream *stream , int flags, char *in, size_t inlen) { #if PHP_MAJOR_VERSION < 7 diff --git a/swoole_http_v2_client.h b/swoole_http_v2_client.h index 0ac61ab9fb4..ff21581fe32 100644 --- a/swoole_http_v2_client.h +++ b/swoole_http_v2_client.h @@ -23,6 +23,8 @@ #include "http.h" #include "http2.h" +#define HTTP2_CLIENT_HOST_HEADER_INDEX 3 + #ifdef SW_HAVE_ZLIB #include extern voidpf php_zlib_alloc(voidpf opaque, uInt items, uInt size); @@ -98,8 +100,6 @@ static sw_inline void http2_client_init_gzip_stream(http2_client_stream *stream) int http2_client_parse_header(http2_client_property *hcc, http2_client_stream *stream , int flags, char *in, size_t inlen); -extern zend_class_entry *swoole_client_class_entry_ptr; - static sw_inline void http2_client_send_setting(swClient *cli) { uint16_t id = 0; @@ -152,4 +152,9 @@ static sw_inline void http2_add_header(nghttp2_nv *headers, char *k, int kl, cha swTrace("k=%s, len=%d, v=%s, len=%d", k, kl, v, vl); } +void http2_add_cookie(nghttp2_nv *nv, int *index, zval *cookies TSRMLS_DC); + +extern swString *cookie_buffer; +extern zend_class_entry *swoole_client_class_entry_ptr; + #endif diff --git a/swoole_http_v2_client_coro.c b/swoole_http_v2_client_coro.c index d1b0cafd205..4e390fa53ed 100644 --- a/swoole_http_v2_client_coro.c +++ b/swoole_http_v2_client_coro.c @@ -216,7 +216,7 @@ static int http2_client_build_header(zval *zobject, zval *req, char *buffer, int } if (strncasecmp("Host", key, keylen) == 0) { - http2_add_header(&nv[3], ZEND_STRL(":authority"), Z_STRVAL_P(value), Z_STRLEN_P(value)); + http2_add_header(&nv[HTTP2_CLIENT_HOST_HEADER_INDEX], ZEND_STRL(":authority"), Z_STRVAL_P(value), Z_STRLEN_P(value)); find_host = 1; } else @@ -229,24 +229,13 @@ static int http2_client_build_header(zval *zobject, zval *req, char *buffer, int } if (!find_host) { - http2_add_header(&nv[3], ZEND_STRL(":authority"), hcc->host, hcc->host_len); + http2_add_header(&nv[HTTP2_CLIENT_HOST_HEADER_INDEX], ZEND_STRL(":authority"), hcc->host, hcc->host_len); } //http cookies if (cookies && !ZVAL_IS_NULL(cookies)) { - zend_size_t len; - smart_str formstr_s = { 0 }; - char *formstr = sw_http_build_query(cookies, &len, &formstr_s TSRMLS_CC); - if (formstr == NULL) - { - swoole_php_error(E_WARNING, "http_build_query failed."); - } - else - { - http2_add_header(&nv[3], ZEND_STRL("cookie"), formstr, len); - smart_str_free(&formstr_s); - } + http2_add_cookie(&nv, &index, cookies TSRMLS_CC); } ssize_t rv; @@ -301,6 +290,7 @@ static void http2_client_onReceive(swClient *cli, char *buf, uint32_t _length) { int type = buf[3]; int flags = buf[4]; + int error_code; int stream_id = ntohl((*(int *) (buf + 5))) & 0x7fffffff; uint32_t length = swHttp2_get_length(buf); buf += SW_HTTP2_FRAME_HEADER_SIZE; @@ -375,7 +365,7 @@ static void http2_client_onReceive(swClient *cli, char *buf, uint32_t _length) { int last_stream_id = htonl(*(int *) (buf)); buf += 4; - int error_code = htonl(*(int *) (buf)); + error_code = htonl(*(int *) (buf)); swWarn("["SW_ECHO_RED"] last_stream_id=%d, error_code=%d.", "GOAWAY", last_stream_id, error_code); zval* retval; @@ -391,10 +381,8 @@ static void http2_client_onReceive(swClient *cli, char *buf, uint32_t _length) } else if (type == SW_HTTP2_TYPE_RST_STREAM) { - int last_stream_id = htonl(*(int *) (buf)); - buf += 4; - int error_code = htonl(*(int *) (buf)); - swWarn("["SW_ECHO_RED"] last_stream_id=%d, error_code=%d.", "RST_STREAM", last_stream_id, error_code); + error_code = htonl(*(int *) (buf)); + swWarn("["SW_ECHO_RED"] stream_id=%d, error_code=%d.", "RST_STREAM", stream_id, error_code); if (hcc->iowait == 0) { @@ -444,6 +432,7 @@ static void http2_client_onReceive(swClient *cli, char *buf, uint32_t _length) if (type == SW_HTTP2_TYPE_RST_STREAM) { zend_update_property_long(swoole_http2_response_class_entry_ptr, zresponse, ZEND_STRL("statusCode"), -3 TSRMLS_CC); + zend_update_property_long(swoole_http2_response_class_entry_ptr, zresponse, ZEND_STRL("errCode"), error_code TSRMLS_CC); } if (stream->buffer)