2.0.0beta2
[m6w6/ext-http] / php_http_curl_client.c
index a285397fb124613cee728fea306b8343dcb8c790..bf04651d00ccec16dbe0530ce724e46f433de357 100644 (file)
@@ -175,15 +175,22 @@ static int php_http_curl_client_raw_callback(CURL *ch, curl_infotype type, char
        switch (type) {
                case CURLINFO_HEADER_IN:
                case CURLINFO_DATA_IN:
-               case CURLINFO_HEADER_OUT:
-               case CURLINFO_DATA_OUT:
-                       php_http_buffer_append(h->buffer, data, length);
+                       php_http_buffer_append(h->response.buffer, data, length);
 
                        if (curl->options.redirects) {
                                flags |= PHP_HTTP_MESSAGE_PARSER_EMPTY_REDIRECTS;
                        }
 
-                       if (PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE == php_http_message_parser_parse(h->parser, h->buffer, flags, &h->message)) {
+                       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;
@@ -510,11 +517,13 @@ static STATUS set_options(php_http_client_t *h, HashTable *options)
                                zval **cookie_val;
 
                                FOREACH_KEYVAL(pos, zoption, cookie_key, cookie_val) {
-                                       if (cookie_key.type == HASH_KEY_IS_STRING) {
-                                               zval *val = php_http_ztyp(IS_STRING, *cookie_val);
-                                               php_http_buffer_appendf(&curl->options.cookies, "%s=%s; ", cookie_key.str, Z_STRVAL_P(val));
-                                               zval_ptr_dtor(&val);
-                                       }
+                                       zval *val = php_http_ztyp(IS_STRING, *cookie_val);
+
+                                       php_http_array_hashkey_stringify(&cookie_key);
+                                       php_http_buffer_appendf(&curl->options.cookies, "%s=%s; ", cookie_key.str, Z_STRVAL_P(val));
+                                       php_http_array_hashkey_stringfree(&cookie_key);
+
+                                       zval_ptr_dtor(&val);
                                }
 
                                php_http_buffer_fix(&curl->options.cookies);
@@ -565,6 +574,19 @@ static STATUS set_options(php_http_client_t *h, HashTable *options)
        if ((zoption = get_option(&curl->options.cache, options, ZEND_STRS("connecttimeout"), IS_DOUBLE))) {
                curl_easy_setopt(ch, CURLOPT_CONNECTTIMEOUT_MS, (long)(Z_DVAL_P(zoption)*1000));
        }
+       
+#if PHP_HTTP_CURL_VERSION(7,25,0)
+       /* tcp */
+       if ((zoption = get_option(&curl->options.cache, options, ZEND_STRS("tcp_keepalive"), IS_BOOL))) {
+               curl_easy_setopt(ch, CURLOPT_TCP_KEEPALIVE, (long)Z_BVAL_P(zoption));
+       }
+       if ((zoption = get_option(&curl->options.cache, options, ZEND_STRS("tcp_keepidle"), IS_LONG))) {
+               curl_easy_setopt(ch, CURLOPT_TCP_KEEPIDLE, Z_LVAL_P(zoption));
+       }
+       if ((zoption = get_option(&curl->options.cache, options, ZEND_STRS("tcp_keepintvl"), IS_LONG))) {
+               curl_easy_setopt(ch, CURLOPT_TCP_KEEPINTVL, Z_LVAL_P(zoption));
+       }
+#endif
 
        /* ssl */
        if ((zoption = get_option(&curl->options.cache, options, ZEND_STRS("ssl"), IS_ARRAY))) {
@@ -962,7 +984,12 @@ static STATUS php_http_curl_client_reset(php_http_client_t *h)
        curl_easy_setopt(ch, CURLOPT_TIMECONDITION, 0L);
        curl_easy_setopt(ch, CURLOPT_TIMEVALUE, 0L);
        curl_easy_setopt(ch, CURLOPT_TIMEOUT, 0L);
-       curl_easy_setopt(ch, CURLOPT_CONNECTTIMEOUT, 3);
+       curl_easy_setopt(ch, CURLOPT_CONNECTTIMEOUT, 3L);
+#if PHP_HTTP_CURL_VERSION(7,25,0)
+       curl_easy_setopt(ch, CURLOPT_TCP_KEEPALIVE, 0L);
+       curl_easy_setopt(ch, CURLOPT_TCP_KEEPIDLE, 60L);
+       curl_easy_setopt(ch, CURLOPT_TCP_KEEPINTVL, 60L);
+#endif
        curl_easy_setopt(ch, CURLOPT_SSLCERT, NULL);
        curl_easy_setopt(ch, CURLOPT_SSLCERTTYPE, NULL);
        curl_easy_setopt(ch, CURLOPT_SSLCERTPASSWD, NULL);
@@ -1024,8 +1051,9 @@ static STATUS php_http_curl_client_reset(php_http_client_t *h)
        return SUCCESS;
 }
 
-STATUS php_http_curl_client_prepare(php_http_client_t *h, php_http_message_t *msg)
+PHP_HTTP_API STATUS php_http_curl_client_prepare(php_http_client_t *h, php_http_message_t *msg)
 {
+       size_t body_size;
        php_http_curl_client_t *curl = h->ctx;
        php_http_curl_client_storage_t *storage = get_storage(curl->handle);
        TSRMLS_FETCH_FROM_CTX(h->ts);
@@ -1072,6 +1100,7 @@ STATUS php_http_curl_client_prepare(php_http_client_t *h, php_http_message_t *ms
        }
 
        /* request headers */
+       php_http_message_update_headers(msg);
        if (zend_hash_num_elements(&msg->hdrs)) {
                php_http_array_hashkey_t header_key = php_http_array_hashkey_init(0);
                zval **header_val;
@@ -1096,15 +1125,14 @@ STATUS php_http_curl_client_prepare(php_http_client_t *h, php_http_message_t *ms
        }
 
        /* attach request body */
-       {
+       if ((body_size = php_http_message_body_size(&msg->body))) {
                /* RFC2616, section 4.3 (para. 4) states that »a message-body MUST NOT be included in a request if the
                 * specification of the request method (section 5.1.1) does not allow sending an entity-body in request.«
                 * Following the clause in section 5.1.1 (para. 2) that request methods »MUST be implemented with the
                 * same semantics as those specified in section 9« reveal that not any single defined HTTP/1.1 method
                 * does not allow a request body.
                 */
-               size_t body_size = php_http_message_body_size(&msg->body);
-
+               php_stream_rewind(php_http_message_body_stream(&msg->body));
                curl_easy_setopt(curl->handle, CURLOPT_IOCTLDATA, &msg->body);
                curl_easy_setopt(curl->handle, CURLOPT_READDATA, &msg->body);
                curl_easy_setopt(curl->handle, CURLOPT_INFILESIZE, body_size);
@@ -1245,11 +1273,6 @@ static php_http_resource_factory_ops_t php_http_curl_client_resource_factory_ops
        php_http_curl_dtor
 };
 
-static zend_class_entry *get_class_entry(void)
-{
-       return php_http_curl_client_class_entry;
-}
-
 static php_http_client_ops_t php_http_curl_client_ops = {
        &php_http_curl_client_resource_factory_ops,
        php_http_curl_client_init,
@@ -1260,7 +1283,7 @@ static php_http_client_ops_t php_http_curl_client_ops = {
        php_http_curl_client_setopt,
        php_http_curl_client_getopt,
        (php_http_new_t) php_http_curl_client_object_new_ex,
-       get_class_entry
+       php_http_curl_client_get_class_entry
 };
 
 PHP_HTTP_API php_http_client_ops_t *php_http_curl_client_get_ops(void)
@@ -1274,12 +1297,18 @@ PHP_HTTP_API php_http_client_ops_t *php_http_curl_client_get_ops(void)
 #define PHP_HTTP_CURL_CLIENT_ME(method, visibility)    PHP_ME(HttpClientCURL, method, PHP_HTTP_ARGS(HttpClientCURL, method), visibility)
 #define PHP_HTTP_CURL_CLIENT_CLIENT_MALIAS(me, vis)    ZEND_FENTRY(me, ZEND_MN(HttpClient_##me), PHP_HTTP_ARGS(HttpClientCURL, me), vis)
 
-PHP_HTTP_BEGIN_ARGS(send, 1)
+PHP_HTTP_BEGIN_ARGS(send, 0)
        PHP_HTTP_ARG_VAL(request, 0)
 PHP_HTTP_END_ARGS;
 
-zend_class_entry *php_http_curl_client_class_entry;
-zend_function_entry php_http_curl_client_method_entry[] = {
+static zend_class_entry *php_http_curl_client_class_entry;
+
+zend_class_entry *php_http_curl_client_get_class_entry(void)
+{
+       return php_http_curl_client_class_entry;
+}
+
+static zend_function_entry php_http_curl_client_method_entry[] = {
        PHP_HTTP_CURL_CLIENT_CLIENT_MALIAS(send, ZEND_ACC_PUBLIC)
        EMPTY_FUNCTION_ENTRY
 };