* - timeout: int, seconds the request may take
* - connecttimeout: int, seconds the connect may take
* - onprogress: mixed, progress callback
- * - ondebug: mixed, debug callback
* </pre>
*
* The optional third parameter will be filled with some additional information
}
}
-#define http_message_header(m, h) _http_message_header_ex((m), (h), sizeof(h))
-#define http_message_header_ex _http_message_header_ex
-static inline zval *_http_message_header_ex(http_message *msg, char *key_str, size_t key_len)
-{
- zval **header;
- if (SUCCESS == zend_hash_find(&msg->hdrs, key_str, key_len, (void **) &header)) {
- return *header;
- }
- return NULL;
-}
-
PHP_HTTP_API http_message *_http_message_init_ex(http_message *message, http_message_type type)
{
if (!message) {
continue; \
}
+typedef struct _http_curl_conv {
+ phpstr *response;
+ phpstr *request;
+ curl_infotype last_info;
+} http_curl_conv;
static const char *const http_request_methods[HTTP_MAX_REQUEST_METHOD + 1];
#define http_curl_getopt(o, k, t) _http_curl_getopt_ex((o), (k), sizeof(k), (t) TSRMLS_CC)
#define http_curl_getopt_ex(o, k, l, t) _http_curl_getopt_ex((o), (k), (l), (t) TSRMLS_CC)
static inline zval *_http_curl_getopt_ex(HashTable *options, char *key, size_t keylen, int type TSRMLS_DC);
-static size_t http_curl_write_callback(char *, size_t, size_t, void *);
static size_t http_curl_read_callback(void *, size_t, size_t, void *);
static int http_curl_progress_callback(void *, double, double, double, double);
-static int http_curl_debug_callback(CURL *, curl_infotype, char *, size_t, void *);
+static int http_curl_raw_callback(CURL *, curl_infotype, char *, size_t, void *);
+static int http_curl_dummy_callback(char *data, size_t n, size_t l, void *s) { return n*l; }
#define HTTP_CURL_CALLBACK_DATA(from, type, var) \
http_curl_callback_ctx *__CTX = (http_curl_callback_ctx *) (from); \
}
/* }}} */
-/* {{{ STATUS http_request_init(CURL *, http_request_method, char *, http_request_body *, HashTable *, phpstr *) */
-PHP_HTTP_API STATUS _http_request_init(CURL *ch, http_request_method meth, char *url, http_request_body *body, HashTable *options, phpstr *response TSRMLS_DC)
+/* {{{ STATUS http_request_init(CURL *, http_request_method, char *, http_request_body *, HashTable *) */
+PHP_HTTP_API STATUS _http_request_init(CURL *ch, http_request_method meth, char *url, http_request_body *body, HashTable *options TSRMLS_DC)
{
zval *zoption;
zend_bool range_req = 0;
HTTP_CURL_OPT(URL, http_request_data_copy(COPY_STRING, url));
}
- if (response) {
- http_curl_callback_ctx *response_ctx = http_curl_callback_data(response);
- HTTP_CURL_OPT(WRITEDATA, response_ctx);
- HTTP_CURL_OPT(WRITEHEADER, response_ctx);
- }
-
HTTP_CURL_OPT(HEADER, 0);
HTTP_CURL_OPT(FILETIME, 1);
HTTP_CURL_OPT(AUTOREFERER, 1);
HTTP_CURL_OPT(READFUNCTION, http_curl_read_callback);
- HTTP_CURL_OPT(WRITEFUNCTION, http_curl_write_callback);
- HTTP_CURL_OPT(HEADERFUNCTION, http_curl_write_callback);
+ /* we'll get all data through the debug function */
+ HTTP_CURL_OPT(WRITEFUNCTION, http_curl_dummy_callback);
+ HTTP_CURL_OPT(HEADERFUNCTION, NULL);
+
+ HTTP_CURL_OPT(VERBOSE, 1);
+ HTTP_CURL_OPT(DEBUGFUNCTION, http_curl_raw_callback);
#if defined(ZTS) && (LIBCURL_VERSION_NUM >= 0x070a00)
HTTP_CURL_OPT(NOSIGNAL, 1);
HTTP_CURL_OPT(NOPROGRESS, 1);
}
- /* debug callback */
- if (zoption = http_curl_getopt(options, "ondebug", 0)) {
- HTTP_CURL_OPT(VERBOSE, 1);
- HTTP_CURL_OPT(DEBUGFUNCTION, http_curl_debug_callback);
- HTTP_CURL_OPT(DEBUGDATA, http_curl_callback_data(zoption));
- } else {
- HTTP_CURL_OPT(VERBOSE, 0);
- }
-
/* proxy */
if (zoption = http_curl_getopt(options, "proxyhost", IS_STRING)) {
HTTP_CURL_OPT(PROXY, http_request_data_copy(COPY_STRING, Z_STRVAL_P(zoption)));
/* }}} */
/* {{{ STATUS http_request_exec(CURL *, HashTable *) */
-PHP_HTTP_API STATUS _http_request_exec(CURL *ch, HashTable *info TSRMLS_DC)
+PHP_HTTP_API STATUS _http_request_exec(CURL *ch, HashTable *info, phpstr *response, phpstr *request TSRMLS_DC)
{
CURLcode result;
+ http_curl_conv conv = {response, request, -1};
+
+ HTTP_CURL_OPT(DEBUGDATA, http_curl_callback_data(&conv));
/* perform request */
if (CURLE_OK != (result = curl_easy_perform(ch))) {
}
}
- status = ((SUCCESS == http_request_init(ch, meth, url, body, options, response)) &&
- (SUCCESS == http_request_exec(ch, info))) ? SUCCESS : FAILURE;
+ status = ((SUCCESS == http_request_init(ch, meth, url, body, options)) &&
+ (SUCCESS == http_request_exec(ch, info, response, NULL))) ? SUCCESS : FAILURE;
if (clean_curl) {
curl_easy_cleanup(ch);
};
/* }}} */
-/* {{{ static size_t http_curl_write_callback(char *, size_t, size_t, void *) */
-static size_t http_curl_write_callback(char *buf, size_t len, size_t n, void *s)
-{
- HTTP_CURL_CALLBACK_DATA(s, phpstr *, str);
- return str ? phpstr_append(PHPSTR(str), buf, len * n) : len * n;
-}
-/* }}} */
-
/* {{{ static size_t http_curl_read_callback(void *, size_t, size_t, void *) */
static size_t http_curl_read_callback(void *data, size_t len, size_t n, void *s)
{
}
/* }}} */
-/* {{{ static int http_curl_debug_callback(CURL *, curl_infotype, char *, size_t, void *) */
-static int http_curl_debug_callback(CURL *ch, curl_infotype type, char *string, size_t length, void *data)
+/* {{{ static int http_curl_raw_callback(CURL *, curl_infotype, char *, size_t, void *) */
+static int http_curl_raw_callback(CURL *ch, curl_infotype type, char *data, size_t length, void *ctx)
{
- zval *params_pass[2], params_local[2], retval;
- HTTP_CURL_CALLBACK_DATA(data, zval *, func);
-
- params_pass[0] = ¶ms_local[0];
- params_pass[1] = ¶ms_local[1];
+ HTTP_CURL_CALLBACK_DATA(ctx, http_curl_conv *, conv);
- INIT_PZVAL(&retval);
- INIT_PZVAL(params_pass[0]);
- INIT_PZVAL(params_pass[1]);
- ZVAL_LONG(params_pass[0], type);
- ZVAL_STRINGL(params_pass[1], string, length, 0);
-
-#ifdef ZEND_ENGINE_2
- /* ensure we can call private HttpRequest::debugWrapper() */
+ switch (type)
{
- void *sc = EG(scope);
- EG(scope) = http_request_object_ce;
-#endif
- call_user_function(EG(function_table), NULL, func, &retval, 2, params_pass TSRMLS_CC);
-#ifdef ZEND_ENGINE_2
- EG(scope) = sc;
+ case CURLINFO_DATA_IN:
+ if (conv->response && conv->last_info == CURLINFO_HEADER_IN) {
+ phpstr_appends(conv->response, HTTP_CRLF);
+ }
+ case CURLINFO_HEADER_IN:
+ if (conv->response) {
+ phpstr_append(conv->response, data, length);
+ }
+ break;
+ case CURLINFO_DATA_OUT:
+ if (conv->request && conv->last_info == CURLINFO_HEADER_OUT) {
+ phpstr_appends(conv->request, HTTP_CRLF);
+ }
+ case CURLINFO_HEADER_OUT:
+ if (conv->request) {
+ phpstr_append(conv->request, data, length);
+ }
+ break;
}
-#endif
+ if (type) {
+ conv->last_info = type;
+ }
return 0;
}
/* }}} */
HTTP_ARG_VAL(method, 0)
HTTP_END_ARGS;
-HTTP_BEGIN_ARGS(debugWrapper, 0, 2)
- HTTP_ARG_VAL(info_type, 0)
- HTTP_ARG_VAL(info_message, 0)
-HTTP_END_ARGS;
-
#define http_request_object_declare_default_properties() _http_request_object_declare_default_properties(TSRMLS_C)
static inline void _http_request_object_declare_default_properties(TSRMLS_D);
HTTP_REQUEST_ALIAS(methodName, http_request_method_name)
HTTP_REQUEST_ALIAS(methodExists, http_request_method_exists)
- HTTP_REQUEST_ME(debugWrapper, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
-
{NULL, NULL, NULL}
};
static zend_object_handlers http_request_object_handlers;
DCL_PROP(PROTECTED, string, queryData, "");
DCL_PROP(PROTECTED, string, putFile, "");
- DCL_PROP_N(PRIVATE, dbg_user_cb);
DCL_PROP(PUBLIC, bool, recordHistory, 1);
}
strncat(request_uri, Z_STRVAL_P(qdata), HTTP_URI_MAXLEN - strlen(request_uri));
}
- /* ensure we have HttpRequest::debugWrapper as dbg callback */
- {
- zval *dbg_cb;
- MAKE_STD_ZVAL(dbg_cb);
- array_init(dbg_cb);
- zval_add_ref(&getThis());
- add_next_index_zval(dbg_cb, getThis());
- add_next_index_stringl(dbg_cb, "debugWrapper", lenof("debugWrapper"), 1);
- add_assoc_zval(opts, "ondebug", dbg_cb);
- }
- /* */
-
switch (Z_LVAL_P(meth))
{
case HTTP_GET:
case HTTP_HEAD:
body->type = -1;
- status = http_request_init(obj->ch, Z_LVAL_P(meth), request_uri, NULL, Z_ARRVAL_P(opts), &obj->response);
+ status = http_request_init(obj->ch, Z_LVAL_P(meth), request_uri, NULL, Z_ARRVAL_P(opts));
break;
case HTTP_PUT:
body->data = stream;
body->size = ssb.sb.st_size;
- status = http_request_init(obj->ch, HTTP_PUT, request_uri, body, Z_ARRVAL_P(opts), &obj->response);
+ status = http_request_init(obj->ch, HTTP_PUT, request_uri, body, Z_ARRVAL_P(opts));
} else {
status = FAILURE;
}
zval *fields = GET_PROP(obj, postFields), *files = GET_PROP(obj, postFiles);
if (SUCCESS == (status = http_request_body_fill(body, Z_ARRVAL_P(fields), Z_ARRVAL_P(files)))) {
- status = http_request_init(obj->ch, HTTP_POST, request_uri, body, Z_ARRVAL_P(opts), &obj->response);
+ status = http_request_init(obj->ch, HTTP_POST, request_uri, body, Z_ARRVAL_P(opts));
}
}
break;
body->data = Z_STRVAL_P(post);
body->size = Z_STRLEN_P(post);
- status = http_request_init(obj->ch, Z_LVAL_P(meth), request_uri, body, Z_ARRVAL_P(opts), &obj->response);
+ status = http_request_init(obj->ch, Z_LVAL_P(meth), request_uri, body, Z_ARRVAL_P(opts));
}
break;
}
*info = GET_PROP(obj, responseInfo),
*hist = GET_PROP(obj, recordHistory);
+ /* should we record history? */
if (Z_TYPE_P(hist) != IS_BOOL) {
convert_to_boolean_ex(&hist);
}
}
UPD_PROP(obj, long, method, Z_LVAL_PP(opt));
continue;
- } else if (!strcmp(key, "ondebug")) {
- SET_PROP(obj, dbg_user_cb, *opt);
}
zval_add_ref(opt);
FREE_PARR(obj, options);
INIT_PARR(obj, options);
- zend_update_property_null(http_request_object_ce, getThis(), "dbg_user_cb", lenof("dbg_user_cb") TSRMLS_CC);
}
/* }}} */
}
if (SUCCESS == (status = http_request_object_requesthandler(obj, getThis(), &body))) {
- status = http_request_exec(obj->ch, NULL);
+ status = http_request_exec(obj->ch, NULL, &obj->response, &obj->request);
}
http_request_body_dtor(&body);
}
/* }}} */
-/* {{{ proto private HttpRequest::debugWrapper(long type, string message)
- */
-PHP_METHOD(HttpRequest, debugWrapper)
-{
- static int curl_ignores_body = 0;
- getObject(http_request_object, obj);
- zval *type, *message, *dbg_user_cb = GET_PROP(obj, dbg_user_cb);
-
- if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &type, &message)) {
- RETURN_NULL();
- }
-
- if (Z_TYPE_P(type) != IS_LONG) {
- convert_to_long_ex(&type);
- }
- if (Z_TYPE_P(message) != IS_STRING) {
- convert_to_string_ex(&message);
- }
-
- switch (Z_LVAL_P(type))
- {
- case CURLINFO_DATA_IN:
- /* fetch ignored body */
- if (curl_ignores_body && Z_LVAL_P(type) == CURLINFO_DATA_IN) {
- phpstr_append(&obj->response, Z_STRVAL_P(message), Z_STRLEN_P(message));
- }
- break;
-
- case CURLINFO_TEXT:
- /* check if following incoming data would be ignored */
- curl_ignores_body = !strcmp(Z_STRVAL_P(message), "Ignoring the response-body\n");
- break;
-
- case CURLINFO_HEADER_OUT:
- case CURLINFO_DATA_OUT:
- /* fetch outgoing request message */
- phpstr_append(&obj->request, Z_STRVAL_P(message), Z_STRLEN_P(message));
- break;
- }
-
- /* call user debug callback */
- if (Z_TYPE_P(dbg_user_cb) != IS_NULL) {
- zval *args[2], cb_ret;
-
- args[0] = type;
- args[1] = message;
- call_user_function(EG(function_table), NULL, dbg_user_cb, &cb_ret, 2, args TSRMLS_CC);
- }
-
- RETURN_NULL();
-}
-/* }}} */
-
#endif /* ZEND_ENGINE_2 && HTTP_HAVE_CURL */
/*
#define http_message_set_type(m, t) _http_message_set_type((m), (t))
PHP_HTTP_API void _http_message_set_type(http_message *m, http_message_type t);
+#define http_message_header(m, h) _http_message_header_ex((m), (h), sizeof(h))
+#define http_message_header_ex _http_message_header_ex
+static inline zval *_http_message_header_ex(http_message *msg, char *key_str, size_t key_len)
+{
+ zval **header;
+ if (SUCCESS == zend_hash_find(&msg->hdrs, key_str, key_len, (void **) &header)) {
+ return *header;
+ }
+ return NULL;
+}
+
#define http_message_parse(m, l) http_message_parse_ex(NULL, (m), (l))
#define http_message_parse_ex(h, m, l) _http_message_parse_ex((h), (m), (l) TSRMLS_CC)
PHP_HTTP_API http_message *_http_message_parse_ex(http_message *msg, const char *message, size_t length TSRMLS_DC);
#define http_request_body_free(b) _http_request_body_free((b) TSRMLS_CC)
PHP_HTTP_API void _http_request_body_free(http_request_body *body TSRMLS_DC);
-#define http_request_init(ch, meth, url, body, options, response) _http_request_init((ch), (meth), (url), (body), (options), (response) TSRMLS_CC)
-PHP_HTTP_API STATUS _http_request_init(CURL *ch, http_request_method meth, char *url, http_request_body *body, HashTable *options, phpstr *response TSRMLS_DC);
+#define http_request_init(ch, meth, url, body, options) _http_request_init((ch), (meth), (url), (body), (options) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_request_init(CURL *ch, http_request_method meth, char *url, http_request_body *body, HashTable *options TSRMLS_DC);
-#define http_request_exec(ch, i) _http_request_exec((ch), (i) TSRMLS_CC)
-PHP_HTTP_API STATUS _http_request_exec(CURL *ch, HashTable *info TSRMLS_DC);
+#define http_request_exec(ch, i, response, request) _http_request_exec((ch), (i), (response), (request) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_request_exec(CURL *ch, HashTable *info, phpstr *response, phpstr *request TSRMLS_DC);
#define http_request_info(ch, i) _http_request_info((ch), (i) TSRMLS_CC)
PHP_HTTP_API void _http_request_info(CURL *ch, HashTable *info TSRMLS_DC);