X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-http;a=blobdiff_plain;f=php_http_client_curl.c;h=566e523b9154b67803abb8a11d67d58818820d91;hp=48bd0deb02789810778ef25840fc73aa1d6dcd8f;hb=91894f441698c7d430d9c1233700227dbee94f0d;hpb=4dde50dd5e77937157350e3aba617261e074bf92 diff --git a/php_http_client_curl.c b/php_http_client_curl.c index 48bd0de..566e523 100644 --- a/php_http_client_curl.c +++ b/php_http_client_curl.c @@ -60,19 +60,11 @@ typedef struct php_http_client_curl_handler { php_resource_factory_t *rf; php_http_client_t *client; php_http_client_progress_state_t progress; - php_http_client_enqueue_t queue; struct { - php_http_message_parser_t *parser; - php_http_message_t *message; - php_http_buffer_t *buffer; - } request; - - struct { - php_http_message_parser_t *parser; - php_http_message_t *message; - php_http_buffer_t *buffer; + php_http_buffer_t headers; + php_http_message_body_t *body; } response; struct { @@ -247,7 +239,6 @@ static curlioerr php_http_curle_ioctl_callback(CURL *ch, curliocmd cmd, void *ct static int php_http_curle_raw_callback(CURL *ch, curl_infotype type, char *data, size_t length, void *ctx) { php_http_client_curl_handler_t *h = ctx; - unsigned flags = 0; /* catch progress */ switch (type) { @@ -304,32 +295,6 @@ static int php_http_curle_raw_callback(CURL *ch, curl_infotype type, char *data, default: break; } - /* process data */ - switch (type) { - case CURLINFO_HEADER_IN: - case CURLINFO_DATA_IN: - php_http_buffer_append(h->response.buffer, data, length); - - if (h->options.redirects) { - flags |= PHP_HTTP_MESSAGE_PARSER_EMPTY_REDIRECTS; - } - - if (PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE == php_http_message_parser_parse(h->response.parser, h->response.buffer, flags, &h->response.message)) { - return -1; - } - break; - - case CURLINFO_HEADER_OUT: - case CURLINFO_DATA_OUT: - php_http_buffer_append(h->request.buffer, data, length); - - if (PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE == php_http_message_parser_parse(h->request.parser, h->request.buffer, flags, &h->request.message)) { - return -1; - } - break; - default: - break; - } #if 0 /* debug */ @@ -339,9 +304,18 @@ static int php_http_curle_raw_callback(CURL *ch, curl_infotype type, char *data, return 0; } -static int php_http_curle_dummy_callback(char *data, size_t n, size_t l, void *s) +static int php_http_curle_header_callback(char *data, size_t n, size_t l, void *arg) { - return n*l; + php_http_client_curl_handler_t *h = arg; + + return php_http_buffer_append(&h->response.headers, data, n * l); +} + +static int php_http_curle_body_callback(char *data, size_t n, size_t l, void *arg) +{ + php_http_client_curl_handler_t *h = arg; + + return php_http_message_body_append(h->response.body, data, n*l); } static STATUS php_http_curle_get_info(CURL *ch, HashTable *info) @@ -617,6 +591,50 @@ static int compare_queue(php_http_client_enqueue_t *e, void *handle) return handle == ((php_http_client_curl_handler_t *) e->opaque)->handle; } +static php_http_message_t *php_http_curlm_responseparser(php_http_client_curl_handler_t *h TSRMLS_DC) +{ + php_http_message_t *response; + php_http_header_parser_t parser; + zval *zh; + + response = php_http_message_init(NULL, 0, h->response.body TSRMLS_CC); + php_http_header_parser_init(&parser TSRMLS_CC); + php_http_header_parser_parse(&parser, &h->response.headers, PHP_HTTP_HEADER_PARSER_CLEANUP, &response->hdrs, (php_http_info_callback_t) php_http_message_info_callback, (void *) &response); + php_http_header_parser_dtor(&parser); + + /* move body to right message */ + if (response->body != h->response.body) { + php_http_message_t *ptr = response; + + while (ptr->parent) { + ptr = ptr->parent; + } + response->body = ptr->body; + ptr->body = NULL; + } + php_http_message_body_addref(h->response.body); + + /* let's update the response headers */ + if ((zh = php_http_message_header(response, ZEND_STRL("Content-Length"), 1))) { + zend_hash_update(&response->hdrs, "X-Original-Content-Length", sizeof("X-Original-Content-Length"), &zh, sizeof(zval *), NULL); + } + if ((zh = php_http_message_header(response, ZEND_STRL("Transfer-Encoding"), 0))) { + zend_hash_update(&response->hdrs, "X-Original-Transfer-Encoding", sizeof("X-Original-Transfer-Encoding"), (void *) &zh, sizeof(zval *), NULL); + zend_hash_del(&response->hdrs, "Transfer-Encoding", sizeof("Transfer-Encoding")); + } + if ((zh = php_http_message_header(response, ZEND_STRL("Content-Range"), 0))) { + zend_hash_update(&response->hdrs, "X-Original-Content-Range", sizeof("X-Original-Content-Range"), &zh, sizeof(zval *), NULL); + zend_hash_del(&response->hdrs, "Content-Range", sizeof("Content-Range")); + } + if ((zh = php_http_message_header(response, ZEND_STRL("Content-Encoding"), 0))) { + zend_hash_update(&response->hdrs, "X-Original-Content-Encoding", sizeof("X-Original-Content-Encoding"), &zh, sizeof(zval *), NULL); + zend_hash_del(&response->hdrs, "Content-Encoding", sizeof("Content-Encoding")); + } + php_http_message_update_headers(response); + + return response; +} + static void php_http_curlm_responsehandler(php_http_client_t *context) { int remaining = 0; @@ -635,8 +653,12 @@ static void php_http_curlm_responsehandler(php_http_client_t *context) if ((enqueue = php_http_client_enqueued(context, msg->easy_handle, compare_queue))) { php_http_client_curl_handler_t *handler = enqueue->opaque; + php_http_message_t *response = php_http_curlm_responseparser(handler TSRMLS_CC); - context->callback.response.func(context->callback.response.arg, context, &handler->queue, &handler->request.message, &handler->response.message); + if (response) { + context->callback.response.func(context->callback.response.arg, context, &handler->queue, &response); + php_http_message_free(&response); + } } } } while (remaining); @@ -1544,12 +1566,8 @@ static php_http_client_curl_handler_t *php_http_client_curl_handler_init(php_htt handler->rf = rf; handler->client = h; handler->handle = handle; - handler->request.buffer = php_http_buffer_init(NULL); - handler->request.parser = php_http_message_parser_init(NULL TSRMLS_CC); - handler->request.message = php_http_message_init(NULL, 0, NULL TSRMLS_CC); - handler->response.buffer = php_http_buffer_init(NULL); - handler->response.parser = php_http_message_parser_init(NULL TSRMLS_CC); - handler->response.message = php_http_message_init(NULL, 0, NULL TSRMLS_CC); + handler->response.body = php_http_message_body_init(NULL, NULL TSRMLS_CC); + php_http_buffer_init(&handler->response.headers); php_http_buffer_init(&handler->options.cookies); php_http_buffer_init(&handler->options.ranges); zend_hash_init(&handler->options.cache, 0, NULL, ZVAL_PTR_DTOR, 0); @@ -1562,8 +1580,8 @@ static php_http_client_curl_handler_t *php_http_client_curl_handler_init(php_htt curl_easy_setopt(handle, CURLOPT_AUTOREFERER, 1L); curl_easy_setopt(handle, CURLOPT_VERBOSE, 1L); curl_easy_setopt(handle, CURLOPT_NOPROGRESS, 0L); - curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, NULL); - curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, php_http_curle_dummy_callback); + curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, php_http_curle_header_callback); + curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, php_http_curle_body_callback); curl_easy_setopt(handle, CURLOPT_DEBUGFUNCTION, php_http_curle_raw_callback); curl_easy_setopt(handle, CURLOPT_READFUNCTION, php_http_curle_read_callback); curl_easy_setopt(handle, CURLOPT_IOCTLFUNCTION, php_http_curle_ioctl_callback); @@ -1575,6 +1593,8 @@ static php_http_client_curl_handler_t *php_http_client_curl_handler_init(php_htt curl_easy_setopt(handle, CURLOPT_PROGRESSDATA, handler); #endif curl_easy_setopt(handle, CURLOPT_DEBUGDATA, handler); + curl_easy_setopt(handle, CURLOPT_WRITEDATA, handler); + curl_easy_setopt(handle, CURLOPT_HEADERDATA, handler); php_http_client_curl_handler_reset(handler); @@ -1598,7 +1618,7 @@ static STATUS php_http_client_curl_handler_prepare(php_http_client_curl_handler_ if (storage->url) { pefree(storage->url, 1); } - storage->url = pestrdup(PHP_HTTP_INFO(msg).request.url, 1); + php_http_url_to_string(PHP_HTTP_INFO(msg).request.url, &storage->url, NULL, 1); curl_easy_setopt(curl->handle, CURLOPT_URL, storage->url); /* request method */ @@ -1711,12 +1731,8 @@ static void php_http_client_curl_handler_dtor(php_http_client_curl_handler_t *ha php_resource_factory_handle_dtor(handler->rf, handler->handle TSRMLS_CC); php_resource_factory_free(&handler->rf); - php_http_message_parser_free(&handler->request.parser); - php_http_message_free(&handler->request.message); - php_http_buffer_free(&handler->request.buffer); - php_http_message_parser_free(&handler->response.parser); - php_http_message_free(&handler->response.message); - php_http_buffer_free(&handler->response.buffer); + php_http_message_body_free(&handler->response.body); + php_http_buffer_dtor(&handler->response.headers); php_http_buffer_dtor(&handler->options.ranges); php_http_buffer_dtor(&handler->options.cookies); zend_hash_destroy(&handler->options.cache); @@ -1784,38 +1800,29 @@ static void queue_dtor(php_http_client_enqueue_t *e) php_http_client_curl_handler_dtor(handler); } -static php_resource_factory_t *create_rf(const char *url TSRMLS_DC) +static php_resource_factory_t *create_rf(php_http_url_t *url TSRMLS_DC) { - php_url *purl; + php_persistent_handle_factory_t *pf; php_resource_factory_t *rf = NULL; + char *id_str = NULL; + size_t id_len; - if (!url || !*url) { + if (!url || (!url->host && !url->path)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot request empty URL"); return NULL; } - purl = php_url_parse(url); + id_len = spprintf(&id_str, 0, "%s:%d", STR_PTR(url->host), url->port ? url->port : 80); - if (!purl) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not parse URL '%s'", url); - return NULL; + pf = php_persistent_handle_concede(NULL, ZEND_STRL("http\\Client\\Curl\\Request"), id_str, id_len, NULL, NULL TSRMLS_CC); + if (pf) { + rf = php_resource_factory_init(NULL, php_persistent_handle_get_resource_factory_ops(), pf, (void (*)(void*)) php_persistent_handle_abandon); } else { - char *id_str = NULL; - size_t id_len = spprintf(&id_str, 0, "%s:%d", STR_PTR(purl->host), purl->port ? purl->port : 80); - php_persistent_handle_factory_t *pf = php_persistent_handle_concede(NULL, ZEND_STRL("http\\Client\\Curl\\Request"), id_str, id_len, NULL, NULL TSRMLS_CC); - - if (pf) { - rf = php_resource_factory_init(NULL, php_persistent_handle_get_resource_factory_ops(), pf, (void (*)(void*)) php_persistent_handle_abandon); - } - - php_url_free(purl); - efree(id_str); - } - - if (!rf) { rf = php_resource_factory_init(NULL, &php_http_curle_resource_factory_ops, NULL, NULL); } + efree(id_str); + return rf; } @@ -2132,6 +2139,9 @@ PHP_MINIT_FUNCTION(http_client_curl) */ REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "HTTP_VERSION_1_0", CURL_HTTP_VERSION_1_0, CONST_CS|CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "HTTP_VERSION_1_1", CURL_HTTP_VERSION_1_1, CONST_CS|CONST_PERSISTENT); +#if PHP_HTTP_CURL_VERSION(7,33,0) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "HTTP_VERSION_2_0", CURL_HTTP_VERSION_2_0, CONST_CS|CONST_PERSISTENT); +#endif REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "HTTP_VERSION_ANY", CURL_HTTP_VERSION_NONE, CONST_CS|CONST_PERSISTENT); /*