- implement accessors to messages response status text
authorMichael Wallner <mike@php.net>
Sun, 5 Feb 2006 21:18:14 +0000 (21:18 +0000)
committerMichael Wallner <mike@php.net>
Sun, 5 Feb 2006 21:18:14 +0000 (21:18 +0000)
- implement FR #6698 etag support (like 'lastmodified')
- add test

http_message_object.c
http_request_api.c
http_request_object.c
php_http_message_object.h
php_http_request_object.h
tests/HttpMessage_001.phpt
tests/request_etag.phpt [new file with mode: 0644]

index 00a8007db26ed08a03041bb8c7a0585c554bce3c..b02deadeec5cda526a1b6cb2ccfa76ee8bec7684 100644 (file)
@@ -76,6 +76,11 @@ HTTP_BEGIN_ARGS(setResponseCode, 0, 1)
        HTTP_ARG_VAL(response_code, 0)
 HTTP_END_ARGS;
 
+HTTP_EMPTY_ARGS(getResponseStatus, 0);
+HTTP_BEGIN_ARGS(setResponseStatus, 0, 1)
+       HTTP_ARG_VAL(response_status, 0)
+HTTP_END_ARGS;
+
 HTTP_EMPTY_ARGS(getRequestMethod, 0);
 HTTP_BEGIN_ARGS(setRequestMethod, 0, 1)
        HTTP_ARG_VAL(request_method, 0)
@@ -138,6 +143,8 @@ zend_function_entry http_message_object_fe[] = {
        HTTP_MESSAGE_ME(setType, ZEND_ACC_PUBLIC)
        HTTP_MESSAGE_ME(getResponseCode, ZEND_ACC_PUBLIC)
        HTTP_MESSAGE_ME(setResponseCode, ZEND_ACC_PUBLIC)
+       HTTP_MESSAGE_ME(getResponseStatus, ZEND_ACC_PUBLIC)
+       HTTP_MESSAGE_ME(setResponseStatus, ZEND_ACC_PUBLIC)
        HTTP_MESSAGE_ME(getRequestMethod, ZEND_ACC_PUBLIC)
        HTTP_MESSAGE_ME(setRequestMethod, ZEND_ACC_PUBLIC)
        HTTP_MESSAGE_ME(getRequestUrl, ZEND_ACC_PUBLIC)
@@ -253,6 +260,7 @@ static inline void _http_message_object_declare_default_properties(TSRMLS_D)
        DCL_PROP(PROTECTED, string, body, "");
        DCL_PROP(PROTECTED, string, requestMethod, "");
        DCL_PROP(PROTECTED, string, requestUrl, "");
+       DCL_PROP(PROTECTED, string, responseStatus, "");
        DCL_PROP(PROTECTED, long, responseCode, 0);
        DCL_PROP_N(PROTECTED, httpVersion);
        DCL_PROP_N(PROTECTED, headers);
@@ -832,6 +840,50 @@ PHP_METHOD(HttpMessage, setResponseCode)
 }
 /* }}} */
 
+/* {{{ proto string HttpMessage::getResponseStatus()
+ *
+ * Get the Response Status of the message (i.e. the string following the response code).
+ *
+ * Returns the HTTP response status string if the message is of type 
+ * HttpMessage::TYPE_RESPONSE, else FALSE.
+ */
+PHP_METHOD(HttpMessage, getResponseStatus)
+{
+       NO_ARGS;
+       
+       IF_RETVAL_USED {
+               getObject(http_message_object, obj);
+               HTTP_CHECK_MESSAGE_TYPE_RESPONSE(obj->message, RETURN_FALSE);
+               RETURN_STRING(obj->message->http.info.response.status, 1);
+       }
+}
+/* }}} */
+
+/* {{{ proto bool HttpMessage::setResponseStatus(string status)
+ *
+ * Set the Response Status of the HTTP message (i.e. the string following the response code).
+ *
+ * Expects a string parameter containing the response status text.
+ *
+ * Returns TRUE on success or FALSE if the message is not of type
+ * HttpMessage::TYPE_RESPONSE.
+ */
+PHP_METHOD(HttpMessage, setResponseStatus)
+{
+       char *status;
+       int status_len;
+       getObject(http_message_object, obj);
+       
+       HTTP_CHECK_MESSAGE_TYPE_RESPONSE(obj->message, RETURN_FALSE);
+       
+       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &status, &status_len)) {
+               RETURN_FALSE;
+       }
+       STR_SET(obj->message->http.info.response.status, estrdup(status));
+       RETURN_TRUE;
+}
+/* }}} */
+
 /* {{{ proto string HttpMessage::getRequestMethod()
  *
  * Get the Request Method of the Message.
index 0432582a638564f9f9f2195afca7c62095bd729b..c80b80b21eefe5c9b26f7feefd6bc997129c4642 100644 (file)
@@ -569,6 +569,12 @@ PHP_HTTP_API STATUS _http_request_prepare(http_request *request, HashTable *opti
                }
        }
 
+       /* resume */
+       if ((zoption = http_request_option(request, options, "resume", IS_LONG)) && (Z_LVAL_P(zoption) != 0)) {
+               range_req = 1;
+               HTTP_CURL_OPT(CURLOPT_RESUME_FROM, Z_LVAL_P(zoption));
+       }
+
        /* additional headers, array('name' => 'value') */
        if (request->_cache.headers) {
                curl_slist_free_all(request->_cache.headers);
@@ -587,7 +593,10 @@ PHP_HTTP_API STATUS _http_request_prepare(http_request *request, HashTable *opti
                                        
                                        ZVAL_ADDREF(*header_val);
                                        convert_to_string_ex(header_val);
-                                       snprintf(header, 1023, "%s: %s", header_key, Z_STRVAL_PP(header_val));
+                                       if (!strcasecmp(header_key, "range")) {
+                                               range_req = 1;
+                                       }
+                                       snprintf(header, lenof(header), "%s: %s", header_key, Z_STRVAL_PP(header_val));
                                        request->_cache.headers = curl_slist_append(request->_cache.headers, header);
                                        zval_ptr_dtor(header_val);
                                }
@@ -597,11 +606,37 @@ PHP_HTTP_API STATUS _http_request_prepare(http_request *request, HashTable *opti
                        }
                }
        }
+       /* etag */
+       if ((zoption = http_request_option(request, options, "etag", IS_STRING)) && Z_STRLEN_P(zoption)) {
+               char match_header[1024] = {0}, *quoted_etag = NULL;
+               
+               if ((Z_STRVAL_P(zoption)[0] != '"') || (Z_STRVAL_P(zoption)[Z_STRLEN_P(zoption)-1] != '"')) {
+                       spprintf(&quoted_etag, 0, "\"%s\"", Z_STRVAL_P(zoption));
+               }
+               snprintf(match_header, lenof(match_header), "%s: %s", range_req?"If-Match":"If-None-Match", quoted_etag?quoted_etag:Z_STRVAL_P(zoption));
+               request->_cache.headers = curl_slist_append(request->_cache.headers, match_header);
+               STR_FREE(quoted_etag);
+       }
+       /* compression */
        if ((zoption = http_request_option(request, options, "compress", IS_BOOL)) && Z_LVAL_P(zoption)) {
                request->_cache.headers = curl_slist_append(request->_cache.headers, "Accept-Encoding: gzip;q=1.0,deflate;q=0.5");
        }
        HTTP_CURL_OPT(CURLOPT_HTTPHEADER, request->_cache.headers);
 
+       /* lastmodified */
+       if ((zoption = http_request_option(request, options, "lastmodified", IS_LONG))) {
+               if (Z_LVAL_P(zoption)) {
+                       if (Z_LVAL_P(zoption) > 0) {
+                               HTTP_CURL_OPT(CURLOPT_TIMEVALUE, Z_LVAL_P(zoption));
+                       } else {
+                               HTTP_CURL_OPT(CURLOPT_TIMEVALUE, HTTP_GET_REQUEST_TIME() + Z_LVAL_P(zoption));
+                       }
+                       HTTP_CURL_OPT(CURLOPT_TIMECONDITION, range_req ? CURL_TIMECOND_IFUNMODSINCE : CURL_TIMECOND_IFMODSINCE);
+               } else {
+                       HTTP_CURL_OPT(CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE);
+               }
+       }
+
        /* cookies, array('name' => 'value') */
        if ((zoption = http_request_option(request, options, "cookies", IS_ARRAY))) {
                phpstr_dtor(&request->_cache.cookies);
@@ -638,12 +673,6 @@ PHP_HTTP_API STATUS _http_request_prepare(http_request *request, HashTable *opti
                HTTP_CURL_OPT(CURLOPT_COOKIEJAR, Z_STRVAL_P(zoption));
        }
 
-       /* resume */
-       if ((zoption = http_request_option(request, options, "resume", IS_LONG)) && (Z_LVAL_P(zoption) != 0)) {
-               range_req = 1;
-               HTTP_CURL_OPT(CURLOPT_RESUME_FROM, Z_LVAL_P(zoption));
-       }
-
        /* maxfilesize */
        if ((zoption = http_request_option(request, options, "maxfilesize", IS_LONG))) {
                HTTP_CURL_OPT(CURLOPT_MAXFILESIZE, Z_LVAL_P(zoption));
@@ -654,20 +683,6 @@ PHP_HTTP_API STATUS _http_request_prepare(http_request *request, HashTable *opti
                HTTP_CURL_OPT(CURLOPT_HTTP_VERSION, Z_LVAL_P(zoption));
        }
 
-       /* lastmodified */
-       if ((zoption = http_request_option(request, options, "lastmodified", IS_LONG))) {
-               if (Z_LVAL_P(zoption)) {
-                       if (Z_LVAL_P(zoption) > 0) {
-                               HTTP_CURL_OPT(CURLOPT_TIMEVALUE, Z_LVAL_P(zoption));
-                       } else {
-                               HTTP_CURL_OPT(CURLOPT_TIMEVALUE, HTTP_GET_REQUEST_TIME() + Z_LVAL_P(zoption));
-                       }
-                       HTTP_CURL_OPT(CURLOPT_TIMECONDITION, range_req ? CURL_TIMECOND_IFUNMODSINCE : CURL_TIMECOND_IFMODSINCE);
-               } else {
-                       HTTP_CURL_OPT(CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE);
-               }
-       }
-
        /* timeout, defaults to 0 */
        if ((zoption = http_request_option(request, options, "timeout", IS_LONG))) {
                HTTP_CURL_OPT(CURLOPT_TIMEOUT, Z_LVAL_P(zoption));
index 6f5b0345f0ca4e20299abc6d972d6713daefdc48..cd77474c319d99053a0d69efeb1d4dc5a9016375 100644 (file)
@@ -140,6 +140,7 @@ HTTP_END_ARGS;
 
 HTTP_EMPTY_ARGS(getResponseBody, 0);
 HTTP_EMPTY_ARGS(getResponseCode, 0);
+HTTP_EMPTY_ARGS(getResponseStatus, 0);
 HTTP_BEGIN_ARGS(getResponseInfo, 0, 0)
        HTTP_ARG_VAL(name, 0)
 HTTP_END_ARGS;
@@ -264,6 +265,7 @@ zend_function_entry http_request_object_fe[] = {
        HTTP_REQUEST_ME(getResponseHeader, ZEND_ACC_PUBLIC)
        HTTP_REQUEST_ME(getResponseCookie, ZEND_ACC_PUBLIC)
        HTTP_REQUEST_ME(getResponseCode, ZEND_ACC_PUBLIC)
+       HTTP_REQUEST_ME(getResponseStatus, ZEND_ACC_PUBLIC)
        HTTP_REQUEST_ME(getResponseBody, ZEND_ACC_PUBLIC)
        HTTP_REQUEST_ME(getResponseInfo, ZEND_ACC_PUBLIC)
        HTTP_REQUEST_ME(getResponseMessage, ZEND_ACC_PUBLIC)
@@ -357,6 +359,7 @@ static inline void _http_request_object_declare_default_properties(TSRMLS_D)
        DCL_PROP_N(PRIVATE, responseData);
        DCL_PROP_N(PRIVATE, responseMessage);
        DCL_PROP(PRIVATE, long, responseCode, 0);
+       DCL_PROP(PRIVATE, string, responseStatus, "");
        DCL_PROP(PRIVATE, long, method, HTTP_GET);
        DCL_PROP(PRIVATE, string, url, "");
        DCL_PROP(PRIVATE, string, contentType, "");
@@ -590,6 +593,7 @@ STATUS _http_request_object_responsehandler(http_request_object *obj, zval *this
                }
 
                UPD_PROP(long, responseCode, msg->http.info.response.code);
+               UPD_PROP(string, responseStatus, msg->http.info.response.status);
 
                MAKE_STD_ZVAL(resp);
                array_init(resp);
@@ -1641,6 +1645,22 @@ PHP_METHOD(HttpRequest, getResponseCode)
 }
 /* }}} */
 
+/* {{{ proto string HttpRequest::getResponseStatus()
+ *
+ * Get the response status (i.e. the string after the response code) after the message has been sent.
+ *
+ * Returns a string containing the response status text.
+ */
+PHP_METHOD(HttpRequest, getResponseStatus)
+{
+       NO_ARGS;
+       
+       IF_RETVAL_USED {
+               RETURN_PROP(responseStatus);
+       }
+}
+/* }}} */
+
 /* {{{ proto mixed HttpRequest::getResponseInfo([string name])
  *
  * Get response info after the request has been sent.
index 97f8214a4cee6f310fc45cf745d84f2241d987cc..62760f70111817cd9f81b6671d89e968d191dd50 100644 (file)
@@ -80,6 +80,8 @@ PHP_METHOD(HttpMessage, getType);
 PHP_METHOD(HttpMessage, setType);
 PHP_METHOD(HttpMessage, getResponseCode);
 PHP_METHOD(HttpMessage, setResponseCode);
+PHP_METHOD(HttpMessage, getResponseStatus);
+PHP_METHOD(HttpMessage, setResponseStatus);
 PHP_METHOD(HttpMessage, getRequestMethod);
 PHP_METHOD(HttpMessage, setRequestMethod);
 PHP_METHOD(HttpMessage, getRequestUrl);
index bbb4e966f87ec7df197132dae6ee44e8e67d39c6..7713e289ba9dc367dd6adf8bec4b8c96e8ed9776 100644 (file)
@@ -82,6 +82,7 @@ PHP_METHOD(HttpRequest, getResponseData);
 PHP_METHOD(HttpRequest, getResponseHeader);
 PHP_METHOD(HttpRequest, getResponseCookie);
 PHP_METHOD(HttpRequest, getResponseCode);
+PHP_METHOD(HttpRequest, getResponseStatus);
 PHP_METHOD(HttpRequest, getResponseBody);
 PHP_METHOD(HttpRequest, getResponseInfo);
 PHP_METHOD(HttpRequest, getResponseMessage);
index 25adb8f1fee832df529998ce46796007cd033b23..c2fe79a33e6cb64c0cdbec2daeabb26d91ddf955 100644 (file)
@@ -13,7 +13,7 @@ $m = new HttpMessage(
        "Location: /anywhere\r\n".
        "HTTP/1.1 302\r\n".
        "Location: /somewhere\r\n".
-       "HTTP/1.1 206\r\n".
+       "HTTP/1.1 206 Partial content\r\n".
        "Content-Range: bytes=2-3\r\n".
        "Transfer-Encoding: chunked\r\n".
        "\r\n".
@@ -22,6 +22,8 @@ $m = new HttpMessage(
        "00"
 );
 
+var_dump($m->getResponseStatus());
+
 $x = $m->getParentMessage();
 $x = $m->getParentMessage();
 $x = $m->getParentMessage();
@@ -36,19 +38,20 @@ echo "Done\n";
 ?>
 --EXPECTF--
 %sTEST
+string(15) "Partial content"
 string(1) "X"
-string(174) "HTTP/1.1 301
+string(190) "HTTP/1.1 301
 Location: /anywhere
 HTTP/1.1 302
 Location: /somewhere
-HTTP/1.1 206
+HTTP/1.1 206 Partial content
 Content-Range: bytes=2-3
 X-Original-Transfer-Encoding: chunked
 Content-Length: 1
 
 X
 "
-string(103) "HTTP/1.1 206
+string(119) "HTTP/1.1 206 Partial content
 Content-Range: bytes=2-3
 X-Original-Transfer-Encoding: chunked
 Content-Length: 1
diff --git a/tests/request_etag.phpt b/tests/request_etag.phpt
new file mode 100644 (file)
index 0000000..69b26d2
--- /dev/null
@@ -0,0 +1,21 @@
+--TEST--
+request etag
+--SKIPIF--
+<?php
+include 'skip.inc';
+skipif(!http_support(HTTP_SUPPORT_REQUESTS), "need request support");
+?>
+--FILE--
+<?php
+echo "-TEST\n";
+var_dump(http_get("http://dev.iworks.at/ext-http/etag", array("etag" => '"26ad3a-5-95eb19c0"')));
+echo "Done\n";
+?>
+--EXPECTF--
+%sTEST
+string(%d) "HTTP/1.1 304 Not Modified
+Date: %s
+Server: %s
+ETag: "26ad3a-5-95eb19c0"
+"
+Done
\ No newline at end of file