attempt to fix that HTTP/2 nonsense
authorMichael Wallner <mike@php.net>
Wed, 7 Sep 2016 12:55:24 +0000 (14:55 +0200)
committerMichael Wallner <mike@php.net>
Wed, 7 Sep 2016 12:55:24 +0000 (14:55 +0200)
src/php_http_info.c
src/php_http_info.h
src/php_http_message.c
src/php_http_version.c
tests/client022.phpt
tests/client029.phpt

index 13bf1246a5d7b615d4c7acb4f7ca2876f0577feb..81bf727b1e4d135bf931af3b084984743f41dc0a 100644 (file)
@@ -49,6 +49,46 @@ void php_http_info_free(php_http_info_t **i)
        }
 }
 
+void php_http_info_to_string(php_http_info_t *info, char **str, size_t *len, const char *eol TSRMLS_DC)
+{
+       char *tmp = NULL;
+
+       if (info->http.version.major == 2) {
+               if (info->type == PHP_HTTP_REQUEST) {
+                       *len = spprintf(str, 0, "%s %s HTTP/2%s",
+                                       info->http.info.request.method?info->http.info.request.method:"UNKNOWN",
+                                       info->http.info.request.method&&!strcasecmp(info->http.info.request.method,"CONNECT")?(
+                                       info->http.info.request.url?php_http_url_authority_to_string(info->http.info.request.url, &(tmp), NULL):"0"):(
+                                       info->http.info.request.url?php_http_url_to_string(info->http.info.request.url, &(tmp), NULL, 0):"/"),
+                                       eol);
+               } else if (info->type == PHP_HTTP_RESPONSE) {
+                       *len = spprintf(str, 0, "HTTP/2 %d%s%s%s",
+                                       info->http.info.response.code?info->http.info.response.code:200,
+                                       info->http.info.response.status&&*info->http.info.response.status ? " ":"",
+                                       STR_PTR(info->http.info.response.status),
+                                       eol);
+               }
+       } else if (info->type == PHP_HTTP_REQUEST) {
+               *len = spprintf(str, 0, "%s %s HTTP/%u.%u%s",
+                               info->http.info.request.method?info->http.info.request.method:"UNKNOWN",
+                               info->http.info.request.method&&!strcasecmp(info->http.info.request.method,"CONNECT")?(
+                               info->http.info.request.url?php_http_url_authority_to_string(info->http.info.request.url, &(tmp), NULL):"0"):(
+                               info->http.info.request.url?php_http_url_to_string(info->http.info.request.url, &(tmp), NULL, 0):"/"),
+                               info->http.version.major||info->http.version.major?info->http.version.major:1,
+                               info->http.version.major||info->http.version.minor?info->http.version.minor:1,
+                               eol);
+       } else if (info->type == PHP_HTTP_RESPONSE){
+               *len = spprintf(str, 0, "HTTP/%u.%u %d%s%s%s", info->http.version.major||info->http.version.major?info->http.version.major:1,
+                               info->http.version.major||info->http.version.minor?info->http.version.minor:1,
+                               info->http.info.response.code?info->http.info.response.code:200,
+                               info->http.info.response.status&&*info->http.info.response.status ? " ":"",
+                               STR_PTR(info->http.info.response.status),
+                               eol);
+       }
+
+       STR_FREE(tmp);
+}
+
 php_http_info_t *php_http_info_parse(php_http_info_t *info, const char *pre_header TSRMLS_DC)
 {
        const char *end, *http, *off;
@@ -80,7 +120,7 @@ php_http_info_t *php_http_info_parse(php_http_info_t *info, const char *pre_head
 
        /* clumsy fix for changed libcurl behaviour in 7.49.1, see https://github.com/curl/curl/issues/888 */
        off = &http[lenof("HTTP/X")];
-       if (info->http.version.major < 2) {
+       if (info->http.version.major < 2 || (info->http.version.major == 2 && *off == '.')) {
                off += 2;
        }
 
index 4f02908446b6c0c430eb6bb39269f45967500b00..e1cce6fc6766a876591ee308af41f4e1ebad7515 100644 (file)
 #include "php_http_version.h"
 #include "php_http_url.h"
 
-#define PHP_HTTP_INFO_REQUEST_FMT_ARGS(_http_ptr, tmp, eol) "%s %s HTTP/%u.%u" eol, \
-                               (_http_ptr)->info.request.method?(_http_ptr)->info.request.method:"UNKNOWN", \
-                               (_http_ptr)->info.request.method&&!strcasecmp((_http_ptr)->info.request.method,"CONNECT")?( \
-                               (_http_ptr)->info.request.url?php_http_url_authority_to_string((_http_ptr)->info.request.url, &(tmp), NULL):"0"):( \
-                               (_http_ptr)->info.request.url?php_http_url_to_string((_http_ptr)->info.request.url, &(tmp), NULL, 0):"/"), \
-                               (_http_ptr)->version.major||(_http_ptr)->version.major?(_http_ptr)->version.major:1, \
-                               (_http_ptr)->version.major||(_http_ptr)->version.minor?(_http_ptr)->version.minor:1
-
-#define PHP_HTTP_INFO_RESPONSE_FMT_ARGS(_http_ptr, tmp, eol) "HTTP/%u.%u %d%s%s" eol, \
-                               (_http_ptr)->version.major||(_http_ptr)->version.major?(_http_ptr)->version.major:1, \
-                               (_http_ptr)->version.major||(_http_ptr)->version.minor?(_http_ptr)->version.minor:1, \
-                               (_http_ptr)->info.response.code?(_http_ptr)->info.response.code:200, \
-                               (_http_ptr)->info.response.status&&*(_http_ptr)->info.response.status ? " ":"", \
-                               STR_PTR((_http_ptr)->info.response.status)
-
 typedef struct php_http_info_data {
        union {
                /* GET /foo/bar */
@@ -60,6 +45,7 @@ typedef zend_bool (*php_http_info_callback_t)(void **callback_data, HashTable **
 
 PHP_HTTP_API php_http_info_t *php_http_info_init(php_http_info_t *info TSRMLS_DC);
 PHP_HTTP_API php_http_info_t *php_http_info_parse(php_http_info_t *info, const char *pre_header TSRMLS_DC);
+PHP_HTTP_API void php_http_info_to_string(php_http_info_t *info, char **str, size_t *len, const char *eol TSRMLS_DC);
 PHP_HTTP_API void php_http_info_dtor(php_http_info_t *info);
 PHP_HTTP_API void php_http_info_free(php_http_info_t **info);
 
index 0701af00c562d1241ca3106c3f17f844f323ebfc..60569b8be62f336f2199ba72196c6fe1f8178e03 100644 (file)
@@ -358,25 +358,15 @@ void php_http_message_update_headers(php_http_message_t *msg)
 static void message_headers(php_http_message_t *msg, php_http_buffer_t *str)
 {
        char *tmp = NULL;
+       size_t len = 0;
        TSRMLS_FETCH_FROM_CTX(msg->ts);
 
-       switch (msg->type) {
-               case PHP_HTTP_REQUEST:
-                       php_http_buffer_appendf(str, PHP_HTTP_INFO_REQUEST_FMT_ARGS(&msg->http, tmp, PHP_HTTP_CRLF));
-                       PTR_FREE(tmp);
-                       break;
-
-               case PHP_HTTP_RESPONSE:
-                       php_http_buffer_appendf(str, PHP_HTTP_INFO_RESPONSE_FMT_ARGS(&msg->http, tmp, PHP_HTTP_CRLF));
-                       PTR_FREE(tmp);
-                       break;
-
-               default:
-                       break;
-       }
-
+       php_http_info_to_string((php_http_info_t *) msg, &tmp, &len, PHP_HTTP_CRLF TSRMLS_CC);
        php_http_message_update_headers(msg);
+
+       php_http_buffer_append(str, tmp, len);
        php_http_header_to_string(str, &msg->hdrs TSRMLS_CC);
+       STR_FREE(tmp);
 }
 
 void php_http_message_to_callback(php_http_message_t *msg, php_http_pass_callback_t cb, void *cb_arg)
@@ -1391,24 +1381,13 @@ ZEND_END_ARG_INFO();
 static PHP_METHOD(HttpMessage, getInfo)
 {
        if (SUCCESS == zend_parse_parameters_none()) {
-               char *tmp = NULL;
+               size_t len = 0;
                php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 
                PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
 
-               switch (obj->message->type) {
-                       case PHP_HTTP_REQUEST:
-                               Z_STRLEN_P(return_value) = spprintf(&Z_STRVAL_P(return_value), 0, PHP_HTTP_INFO_REQUEST_FMT_ARGS(&obj->message->http, tmp, ""));
-                               PTR_FREE(tmp);
-                               break;
-                       case PHP_HTTP_RESPONSE:
-                               Z_STRLEN_P(return_value) = spprintf(&Z_STRVAL_P(return_value), 0, PHP_HTTP_INFO_RESPONSE_FMT_ARGS(&obj->message->http, tmp, ""));
-                               PTR_FREE(tmp);
-                               break;
-                       default:
-                               RETURN_NULL();
-                               break;
-               }
+               php_http_info_to_string((php_http_info_t *) obj->message, &Z_STRVAL_P(return_value), &len, "" TSRMLS_CC);
+               Z_STRLEN_P(return_value) = len;
                Z_TYPE_P(return_value) = IS_STRING;
                return;
        }
index c861a6470a2ba084a5502e3066193547e43967c8..2cba01e3615ae773eecdec6ca42fe44d1b4d6b72 100644 (file)
@@ -73,7 +73,12 @@ php_http_version_t *php_http_version_parse(php_http_version_t *v, const char *st
 
 void php_http_version_to_string(php_http_version_t *v, char **str, size_t *len, const char *pre, const char *post TSRMLS_DC)
 {
-       *len = spprintf(str, 0, "%s%u.%u%s", pre ? pre : "", v->major, v->minor, post ? post : "");
+       /* different semantics for different versions */
+       if (v->major == 2) {
+               *len = spprintf(str, 0, "%s2%s", STR_PTR(pre), STR_PTR(post));
+       } else  {
+               *len = spprintf(str, 0, "%s%u.%u%s", STR_PTR(pre), v->major, v->minor, STR_PTR(post));
+       }
 }
 
 void php_http_version_dtor(php_http_version_t *v)
index a59971ccbcaccb7b99bdac8e83ece4c51ede3cbd..e813cdc0c953c018a044569526857e11cdb10d40 100644 (file)
@@ -31,7 +31,7 @@ nghttpd(function($port) {
 ===DONE===
 --EXPECTF--
 Test
-HTTP/2.0 200
+HTTP/2 200
 %a
 
 <!doctype html>
index 2ed6d7934c36773a9fdbcd2d635bb4ab84970289..fc4250048f287a863c6db240646ed76f519bbee3 100644 (file)
@@ -23,7 +23,7 @@ class UserHandler implements http\Client\Curl\User
                $this->client = $client;
        }
        
-       function init(callable $run) {
+       function init($run) {
                $this->run = $run;
        }