From 318d3b3a3ff2074bf80caf2a54b014eddac3eb1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Hukkam=C3=A4ki?= Date: Thu, 28 Jul 2016 19:17:20 +0000 Subject: [PATCH] Implement request #27814 Construct HTTP request headers into smart_str and send whole request in one go. --- NEWS | 2 ++ ext/standard/http_fopen_wrapper.c | 39 +++++++++++++++++-------------- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/NEWS b/NEWS index c20b29910dd..beed108cc73 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,8 @@ PHP NEWS - Stream: . Fixed bug #72743 (Out-of-bound read in php_stream_filter_create). (Loianhtuan) + . Implemented FR #27814 (Multiple small packets send for HTTP request). + (vhuk) 04 Aug 2016, PHP 7.1.0beta2 diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c index ec57cab2b68..5dbedb6c75f 100644 --- a/ext/standard/http_fopen_wrapper.c +++ b/ext/standard/http_fopen_wrapper.c @@ -145,6 +145,7 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, php_stream_filter *transfer_encoding = NULL; int response_code; zend_array *symbol_table; + smart_str req_buf = {0}; ZVAL_UNDEF(&response_header); tmp_line[0] = '\0'; @@ -423,8 +424,7 @@ finish: strlcat(scratch, " HTTP/1.0\r\n", scratch_len); } - /* send it */ - php_stream_write(stream, scratch, strlen(scratch)); + smart_str_appends(&req_buf, scratch); if (context && (tmpzval = php_stream_context_get_option(context, "http", "header")) != NULL) { tmp = NULL; @@ -554,7 +554,7 @@ finish: stmp = php_base64_encode((unsigned char*)scratch, strlen(scratch)); if (snprintf(scratch, scratch_len, "Authorization: Basic %s\r\n", ZSTR_VAL(stmp)) > 0) { - php_stream_write(stream, scratch, strlen(scratch)); + smart_str_appends(&req_buf, scratch); php_stream_notify_info(context, PHP_STREAM_NOTIFY_AUTH_REQUIRED, NULL, 0); } @@ -564,7 +564,7 @@ finish: /* if the user has configured who they are, send a From: line */ if (((have_header & HTTP_HEADER_FROM) == 0) && FG(from_address)) { if (snprintf(scratch, scratch_len, "From: %s\r\n", FG(from_address)) > 0) - php_stream_write(stream, scratch, strlen(scratch)); + smart_str_appends(&req_buf, scratch); } /* Send Host: header so name-based virtual hosts work */ @@ -572,10 +572,10 @@ finish: if ((use_ssl && resource->port != 443 && resource->port != 0) || (!use_ssl && resource->port != 80 && resource->port != 0)) { if (snprintf(scratch, scratch_len, "Host: %s:%i\r\n", resource->host, resource->port) > 0) - php_stream_write(stream, scratch, strlen(scratch)); + smart_str_appends(&req_buf, scratch); } else { if (snprintf(scratch, scratch_len, "Host: %s\r\n", resource->host) > 0) { - php_stream_write(stream, scratch, strlen(scratch)); + smart_str_appends(&req_buf, scratch); } } } @@ -587,7 +587,7 @@ finish: * HTTP/1.0 to avoid issues when the server respond with a HTTP/1.1 * keep-alive response, which is the preferred response type. */ if ((have_header & HTTP_HEADER_CONNECTION) == 0) { - php_stream_write_string(stream, "Connection: close\r\n"); + smart_str_appends(&req_buf,"Connection: close\r\n"); } if (context && @@ -610,7 +610,7 @@ finish: ua = emalloc(ua_len + 1); if ((ua_len = slprintf(ua, ua_len, _UA_HEADER, ua_str)) > 0) { ua[ua_len] = 0; - php_stream_write(stream, ua, ua_len); + smart_str_appendl(&req_buf, ua, ua_len); } else { php_error_docref(NULL, E_WARNING, "Cannot construct User-agent header"); } @@ -630,12 +630,12 @@ finish: Z_TYPE_P(tmpzval) == IS_STRING && Z_STRLEN_P(tmpzval) > 0 ) { scratch_len = slprintf(scratch, scratch_len, "Content-Length: %zd\r\n", Z_STRLEN_P(tmpzval)); - php_stream_write(stream, scratch, scratch_len); + smart_str_appendl(&req_buf, scratch, scratch_len); have_header |= HTTP_HEADER_CONTENT_LENGTH; } - php_stream_write(stream, user_headers, strlen(user_headers)); - php_stream_write(stream, "\r\n", sizeof("\r\n")-1); + smart_str_appends(&req_buf, user_headers); + smart_str_appends(&req_buf, "\r\n"); efree(user_headers); } @@ -645,19 +645,21 @@ finish: Z_TYPE_P(tmpzval) == IS_STRING && Z_STRLEN_P(tmpzval) > 0) { if (!(have_header & HTTP_HEADER_CONTENT_LENGTH)) { scratch_len = slprintf(scratch, scratch_len, "Content-Length: %zd\r\n", Z_STRLEN_P(tmpzval)); - php_stream_write(stream, scratch, scratch_len); + smart_str_appendl(&req_buf, scratch, scratch_len); } if (!(have_header & HTTP_HEADER_TYPE)) { - php_stream_write(stream, "Content-Type: application/x-www-form-urlencoded\r\n", - sizeof("Content-Type: application/x-www-form-urlencoded\r\n") - 1); + smart_str_appends(&req_buf, "Content-Type: application/x-www-form-urlencoded\r\n"); php_error_docref(NULL, E_NOTICE, "Content-type not specified assuming application/x-www-form-urlencoded"); } - php_stream_write(stream, "\r\n", sizeof("\r\n")-1); - php_stream_write(stream, Z_STRVAL_P(tmpzval), Z_STRLEN_P(tmpzval)); + smart_str_appends(&req_buf, "\r\n"); + smart_str_appendl(&req_buf, Z_STRVAL_P(tmpzval), Z_STRLEN_P(tmpzval)); } else { - php_stream_write(stream, "\r\n", sizeof("\r\n")-1); + smart_str_appends(&req_buf, "\r\n"); } + /* send it */ + php_stream_write(stream, ZSTR_VAL(req_buf.s), ZSTR_LEN(req_buf.s)); + location[0] = '\0'; symbol_table = zend_rebuild_symbol_table(); @@ -893,6 +895,9 @@ finish: } } out: + + smart_str_free(&req_buf); + if (protocol_version) { efree(protocol_version); }