Implement request #27814

Construct HTTP request headers into smart_str and send whole
request in one go.
This commit is contained in:
Ville Hukkamäki 2016-07-28 19:17:20 +00:00 committed by Nikita Popov
parent 3800e1cf97
commit 318d3b3a3f
2 changed files with 24 additions and 17 deletions

2
NEWS
View File

@ -8,6 +8,8 @@ PHP NEWS
- Stream: - Stream:
. Fixed bug #72743 (Out-of-bound read in php_stream_filter_create). . Fixed bug #72743 (Out-of-bound read in php_stream_filter_create).
(Loianhtuan) (Loianhtuan)
. Implemented FR #27814 (Multiple small packets send for HTTP request).
(vhuk)
04 Aug 2016, PHP 7.1.0beta2 04 Aug 2016, PHP 7.1.0beta2

View File

@ -145,6 +145,7 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
php_stream_filter *transfer_encoding = NULL; php_stream_filter *transfer_encoding = NULL;
int response_code; int response_code;
zend_array *symbol_table; zend_array *symbol_table;
smart_str req_buf = {0};
ZVAL_UNDEF(&response_header); ZVAL_UNDEF(&response_header);
tmp_line[0] = '\0'; tmp_line[0] = '\0';
@ -423,8 +424,7 @@ finish:
strlcat(scratch, " HTTP/1.0\r\n", scratch_len); strlcat(scratch, " HTTP/1.0\r\n", scratch_len);
} }
/* send it */ smart_str_appends(&req_buf, scratch);
php_stream_write(stream, scratch, strlen(scratch));
if (context && (tmpzval = php_stream_context_get_option(context, "http", "header")) != NULL) { if (context && (tmpzval = php_stream_context_get_option(context, "http", "header")) != NULL) {
tmp = NULL; tmp = NULL;
@ -554,7 +554,7 @@ finish:
stmp = php_base64_encode((unsigned char*)scratch, strlen(scratch)); stmp = php_base64_encode((unsigned char*)scratch, strlen(scratch));
if (snprintf(scratch, scratch_len, "Authorization: Basic %s\r\n", ZSTR_VAL(stmp)) > 0) { 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); 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 the user has configured who they are, send a From: line */
if (((have_header & HTTP_HEADER_FROM) == 0) && FG(from_address)) { if (((have_header & HTTP_HEADER_FROM) == 0) && FG(from_address)) {
if (snprintf(scratch, scratch_len, "From: %s\r\n", FG(from_address)) > 0) 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 */ /* Send Host: header so name-based virtual hosts work */
@ -572,10 +572,10 @@ finish:
if ((use_ssl && resource->port != 443 && resource->port != 0) || if ((use_ssl && resource->port != 443 && resource->port != 0) ||
(!use_ssl && resource->port != 80 && 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) 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 { } else {
if (snprintf(scratch, scratch_len, "Host: %s\r\n", resource->host) > 0) { 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 * HTTP/1.0 to avoid issues when the server respond with a HTTP/1.1
* keep-alive response, which is the preferred response type. */ * keep-alive response, which is the preferred response type. */
if ((have_header & HTTP_HEADER_CONNECTION) == 0) { 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 && if (context &&
@ -610,7 +610,7 @@ finish:
ua = emalloc(ua_len + 1); ua = emalloc(ua_len + 1);
if ((ua_len = slprintf(ua, ua_len, _UA_HEADER, ua_str)) > 0) { if ((ua_len = slprintf(ua, ua_len, _UA_HEADER, ua_str)) > 0) {
ua[ua_len] = 0; ua[ua_len] = 0;
php_stream_write(stream, ua, ua_len); smart_str_appendl(&req_buf, ua, ua_len);
} else { } else {
php_error_docref(NULL, E_WARNING, "Cannot construct User-agent header"); 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 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)); 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; have_header |= HTTP_HEADER_CONTENT_LENGTH;
} }
php_stream_write(stream, user_headers, strlen(user_headers)); smart_str_appends(&req_buf, user_headers);
php_stream_write(stream, "\r\n", sizeof("\r\n")-1); smart_str_appends(&req_buf, "\r\n");
efree(user_headers); efree(user_headers);
} }
@ -645,19 +645,21 @@ finish:
Z_TYPE_P(tmpzval) == IS_STRING && Z_STRLEN_P(tmpzval) > 0) { Z_TYPE_P(tmpzval) == IS_STRING && Z_STRLEN_P(tmpzval) > 0) {
if (!(have_header & HTTP_HEADER_CONTENT_LENGTH)) { if (!(have_header & HTTP_HEADER_CONTENT_LENGTH)) {
scratch_len = slprintf(scratch, scratch_len, "Content-Length: %zd\r\n", Z_STRLEN_P(tmpzval)); 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)) { if (!(have_header & HTTP_HEADER_TYPE)) {
php_stream_write(stream, "Content-Type: application/x-www-form-urlencoded\r\n", smart_str_appends(&req_buf, "Content-Type: application/x-www-form-urlencoded\r\n");
sizeof("Content-Type: application/x-www-form-urlencoded\r\n") - 1);
php_error_docref(NULL, E_NOTICE, "Content-type not specified assuming application/x-www-form-urlencoded"); 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); smart_str_appends(&req_buf, "\r\n");
php_stream_write(stream, Z_STRVAL_P(tmpzval), Z_STRLEN_P(tmpzval)); smart_str_appendl(&req_buf, Z_STRVAL_P(tmpzval), Z_STRLEN_P(tmpzval));
} else { } 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'; location[0] = '\0';
symbol_table = zend_rebuild_symbol_table(); symbol_table = zend_rebuild_symbol_table();
@ -893,6 +895,9 @@ finish:
} }
} }
out: out:
smart_str_free(&req_buf);
if (protocol_version) { if (protocol_version) {
efree(protocol_version); efree(protocol_version);
} }