X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-http;a=blobdiff_plain;f=http_methods.c;h=c2b13ef091daac92aaf4833e7cafd9439646f132;hp=e10923b2b473a2e30d09c6cd9b1e0829c4eb37cb;hb=73ca84f4751d2197ee39b92c3b924b8e64b0ff0d;hpb=2269e8e11a6837fc165ae85406ea6db84c1995cc diff --git a/http_methods.c b/http_methods.c index e10923b..c2b13ef 100644 --- a/http_methods.c +++ b/http_methods.c @@ -18,8 +18,10 @@ #ifdef HAVE_CONFIG_H # include "config.h" #endif - #include "php.h" + +#ifdef ZEND_ENGINE_2 + #include "php_streams.h" #include "php_http.h" @@ -27,6 +29,7 @@ #include "php_http_api.h" #include "php_http_cache_api.h" #include "php_http_request_api.h" +#include "php_http_request_pool_api.h" #include "php_http_date_api.h" #include "php_http_headers_api.h" #include "php_http_message_api.h" @@ -39,11 +42,9 @@ #include "php_http_requestpool_object.h" #include "php_http_exception_object.h" -#ifdef ZEND_ENGINE_2 - #include "missing.h" -ZEND_EXTERN_MODULE_GLOBALS(http) +ZEND_EXTERN_MODULE_GLOBALS(http); /* {{{ HttpResponse */ @@ -52,8 +53,6 @@ ZEND_EXTERN_MODULE_GLOBALS(http) * Instantiates a new HttpResponse object, which can be used to send * any data/resource/file to an HTTP client with caching and multiple * ranges/resuming support. - * - * NOTE: GZIPping is not implemented yet. */ PHP_METHOD(HttpResponse, __construct) { @@ -69,6 +68,37 @@ PHP_METHOD(HttpResponse, __construct) } /* }}} */ +/* {{{ proto void HttpResponse::__destruct() + * + * - + */ +PHP_METHOD(HttpResponse, __destruct) +{ + getObject(http_response_object, obj); + zval *catch_ob = GET_PROP(obj, catch_ob), *sent = GET_PROP(obj, sent); + fprintf(stderr, "DTOR!\n"); fflush(stderr); + if (!Z_LVAL_P(sent) && Z_LVAL_P(catch_ob)) { + zval ob_data; + + /* fetch catched output buffer */ + if (SUCCESS == php_ob_get_buffer(&ob_data TSRMLS_CC)) { + zval *lmod = GET_PROP(obj, lastModified); + + SET_PROP(obj, data, &ob_data); + UPD_PROP(obj, long, send_mode, SEND_DATA); + + if (!Z_LVAL_P(lmod)) { + UPD_PROP(obj, long, lastModified, http_last_modified(&ob_data, SEND_DATA)); + } + zval_dtor(&ob_data); + + http_response_object_sendhandler(getThis(), obj, 1, return_value); + RETVAL_NULL(); + } + } +} +/* }}} */ + /* {{{ proto bool HttpResponse::setCache(bool cache) * * Whether it sould be attempted to cache the entitity. @@ -526,15 +556,40 @@ PHP_METHOD(HttpResponse, getFile) PHP_METHOD(HttpResponse, send) { zend_bool clean_ob = 1; - zval *do_cache, *do_gzip; + + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &clean_ob)) { + RETURN_FALSE; + } + + http_response_object_sendhandler(getThis(), NULL, clean_ob, return_value); +} +/* }}} */ + +/* {{{ proto bool HttpResponse::catchOutput([bool clean_ob = false]) + * + * Use this method instead of HttpResponse::set*() and HttpResponse::send() + * to let HttpResponse catch and handle the scripts output (i.e. echo/print). + * + * Example: + *
+ * setContentType('text/html; charset=utf-8');
+ * $r->catchOutput(true);
+ * // script follows
+ * ?>
+ * 
+ */ +PHP_METHOD(HttpResponse, catchOutput) +{ + zend_bool clean_ob = 0; getObject(http_response_object, obj); if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &clean_ob)) { RETURN_FALSE; } - do_cache = GET_PROP(obj, cache); - do_gzip = GET_PROP(obj, gzip); + UPD_PROP(obj, long, catch_ob, 1); if (clean_ob) { /* interrupt on-the-fly etag generation */ @@ -543,93 +598,13 @@ PHP_METHOD(HttpResponse, send) php_end_ob_buffers(0 TSRMLS_CC); } - /* gzip */ - if (Z_LVAL_P(do_gzip)) { - php_start_ob_buffer_named("ob_gzhandler", 0, 1 TSRMLS_CC); - } - - /* caching */ - if (Z_LVAL_P(do_cache)) { - char *cc_hdr; - int cc_len; - zval *cctrl, *etag, *lmod, *ccraw; - - etag = GET_PROP(obj, eTag); - lmod = GET_PROP(obj, lastModified); - cctrl = GET_PROP(obj, cacheControl); - ccraw = GET_PROP(obj, raw_cache_header); - - if (Z_LVAL_P(ccraw)) { - cc_hdr = Z_STRVAL_P(cctrl); - cc_len = Z_STRLEN_P(cctrl); - } else { - char cc_header[42] = {0}; - sprintf(cc_header, "%s, must-revalidate, max-age=0", Z_STRVAL_P(cctrl)); - cc_hdr = cc_header; - cc_len = Z_STRLEN_P(cctrl) + lenof(", must-revalidate, max-age=0"); - } - - http_cache_etag(Z_STRVAL_P(etag), Z_STRLEN_P(etag), cc_hdr, cc_len); - http_cache_last_modified(Z_LVAL_P(lmod), Z_LVAL_P(lmod) ? Z_LVAL_P(lmod) : time(NULL), cc_hdr, cc_len); - } - - /* content type */ - { - zval *ctype = GET_PROP(obj, contentType); - if (Z_STRLEN_P(ctype)) { - http_send_content_type(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype)); - } else { - http_send_content_type("application/x-octetstream", lenof("application/x-octetstream")); - } - } - - /* content disposition */ - { - zval *dispo_file = GET_PROP(obj, dispoFile); - if (Z_STRLEN_P(dispo_file)) { - zval *dispo_inline = GET_PROP(obj, dispoInline); - http_send_content_disposition(Z_STRVAL_P(dispo_file), Z_STRLEN_P(dispo_file), (zend_bool) Z_LVAL_P(dispo_inline)); - } - } - - /* throttling */ - { - zval *send_buffersize, *throttle_delay; - send_buffersize = GET_PROP(obj, sendBuffersize); - throttle_delay = GET_PROP(obj, throttleDelay); - HTTP_G(send).buffer_size = Z_LVAL_P(send_buffersize); - HTTP_G(send).throttle_delay = Z_DVAL_P(throttle_delay); - } - - /* send */ - { - zval *send_mode = GET_PROP(obj, send_mode); - switch (Z_LVAL_P(send_mode)) - { - case SEND_DATA: - { - zval *zdata = GET_PROP(obj, data); - RETURN_SUCCESS(http_send_data(Z_STRVAL_P(zdata), Z_STRLEN_P(zdata))); - } - - case SEND_RSRC: - { - php_stream *the_real_stream; - zval *the_stream = GET_PROP(obj, stream); - php_stream_from_zval(the_real_stream, &the_stream); - RETURN_SUCCESS(http_send_stream(the_real_stream)); - } - - default: - { - zval *zfile = GET_PROP(obj, file); - RETURN_SUCCESS(http_send_file(Z_STRVAL_P(zfile))); - } - } + if (SUCCESS != php_start_ob_buffer(NULL, 0, 1 TSRMLS_CC)) { + RETURN_FALSE; } + + RETURN_TRUE; } /* }}} */ -/* }}} */ /* {{{ HttpMessage */ @@ -1132,7 +1107,7 @@ PHP_METHOD(HttpRequest, __destruct) PHP_METHOD(HttpRequest, setOptions) { char *key = NULL; - long idx = 0; + ulong idx = 0; zval *opts, *old_opts, **opt; getObject(http_request_object, obj); @@ -1398,11 +1373,11 @@ PHP_METHOD(HttpRequest, unsetCookies) } /* }}} */ -/* {{{ proto bool HttpRequest::setURL(string url) +/* {{{ proto bool HttpRequest::setUrl(string url) * * Set the request URL. */ -PHP_METHOD(HttpRequest, setURL) +PHP_METHOD(HttpRequest, setUrl) { char *URL = NULL; int URL_len; @@ -1421,7 +1396,7 @@ PHP_METHOD(HttpRequest, setURL) * * Get the previously set request URL. */ -PHP_METHOD(HttpRequest, getURL) +PHP_METHOD(HttpRequest, getUrl) { NO_ARGS; @@ -1727,7 +1702,7 @@ PHP_METHOD(HttpRequest, addPostFile) } /* }}} */ -/* {{{ proto bool HttpRequest::setPostFiles() +/* {{{ proto bool HttpRequest::setPostFiles(array post_files) * * Set files to post. * Overwrites previously set post files. @@ -2068,12 +2043,14 @@ PHP_METHOD(HttpRequest, getResponseMessage) getObject(http_request_object, obj); message = GET_PROP(obj, responseMessage); - Z_TYPE_P(return_value) = IS_OBJECT; - return_value->is_ref = 1; - return_value->value.obj = message->value.obj; - zval_add_ref(&return_value); + if (Z_TYPE_P(message) == IS_OBJECT) { + RETVAL_OBJECT(message); + } else { + RETURN_NULL(); + } } } +/* }}} */ /* {{{ proto bool HttpRequest::send() * @@ -2120,20 +2097,19 @@ PHP_METHOD(HttpRequest, send) SET_EH_THROW_HTTP(); if (obj->pool) { - http_error(E_WARNING, HTTP_E_CURL, "You cannot call HttpRequest::send() while attached to an HttpRequestPool"); + http_error(E_WARNING, HTTP_E_CURL, "Cannot perform HttpRequest::send() while attached to an HttpRequestPool"); + SET_EH_NORMAL(); RETURN_FALSE; } if (SUCCESS == (status = http_request_object_requesthandler(obj, getThis(), &body))) { - zval *info = GET_PROP(obj, responseInfo); - status = http_request_exec(obj->ch, Z_ARRVAL_P(info)); - SET_PROP(obj, responseInfo, info); + status = http_request_exec(obj->ch, NULL); } http_request_body_dtor(&body); /* final data handling */ if (SUCCESS == status) { - status = http_request_object_responsehandler(obj, getThis(), NULL); + status = http_request_object_responsehandler(obj, getThis()); } SET_EH_NORMAL(); @@ -2143,13 +2119,46 @@ PHP_METHOD(HttpRequest, send) /* {{{ HttpRequestPool */ -/* {{{ proto void HttpRequestPool::__construct() +/* {{{ proto void HttpRequestPool::__construct([HttpRequest request[, ...]]) * - * Instantiate a new HttpRequestPool object. + * Instantiate a new HttpRequestPool object. An HttpRequestPool is + * able to send several HttpRequests in parallel. + * + * Example: + *
+ * attach($req[$url]);
+ *     }
+ *     $pool->send();
+ *     foreach ($urls as $url) {
+ *         printf("%s (%s) is %s\n",
+ *             $url, $req[$url]->getResponseInfo('effective_url'),
+ *             $r->getResponseCode() == 200 ? 'alive' : 'not alive'
+ *         );
+ *     }
+ * ?>
+ * 
*/ PHP_METHOD(HttpRequestPool, __construct) { - NO_ARGS; + int argc = ZEND_NUM_ARGS(); + zval ***argv = safe_emalloc(argc, sizeof(zval *), 0); + getObject(http_requestpool_object, obj); + + if (SUCCESS == zend_get_parameters_array_ex(argc, argv)) { + int i; + + for (i = 0; i < argc; ++i) { + if (Z_TYPE_PP(argv[i]) == IS_OBJECT && instanceof_function(Z_OBJCE_PP(argv[i]), http_request_object_ce TSRMLS_CC)) { + http_request_pool_attach(&obj->pool, *(argv[i])); + } + } + } + efree(argv); } /* }}} */ @@ -2224,12 +2233,70 @@ PHP_METHOD(HttpRequestPool, detach) * Send all attached HttpRequest objects in parallel. */ PHP_METHOD(HttpRequestPool, send) +{ + STATUS status; + getObject(http_requestpool_object, obj); + + NO_ARGS; + + SET_EH_THROW_HTTP(); + status = http_request_pool_send(&obj->pool); + SET_EH_NORMAL(); + + RETURN_SUCCESS(status); +} +/* }}} */ + +/* {{{ proto protected bool HttpRequestPool::socketSend() + * + * Usage: + *
+ * socketSend()) {
+ *         do_something_else();
+ *         if (!$pool->socketSelect()) {
+ *             die('Socket error');
+ *         }
+ *     }
+ *     $pool->socketRead();
+ * ?>
+ * 
+ */ +PHP_METHOD(HttpRequestPool, socketSend) { getObject(http_requestpool_object, obj); NO_ARGS; - RETURN_SUCCESS(http_request_pool_send(&obj->pool)); + RETURN_BOOL(0 < http_request_pool_perform(&obj->pool)); +} +/* }}} */ + +/* {{{ proto protected bool HttpRequestPool::socketSelect() + * + * See HttpRequestPool::socketSend(). + */ +PHP_METHOD(HttpRequestPool, socketSelect) +{ + getObject(http_requestpool_object, obj); + + NO_ARGS; + + RETURN_SUCCESS(http_request_pool_select(&obj->pool)); +} +/* }}} */ + +/* {{{ proto protected void HttpRequestPool::socketRead() + * + * See HttpRequestPool::socketSend(). + */ +PHP_METHOD(HttpRequestPool, socketRead) +{ + getObject(http_requestpool_object, obj); + + NO_ARGS; + + zend_llist_apply(&obj->pool.handles, (llist_apply_func_t) http_request_pool_responsehandler TSRMLS_CC); } /* }}} */ @@ -2248,3 +2315,4 @@ PHP_METHOD(HttpRequestPool, send) * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ +