}
}
+ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_configure, 0, 0, 1)
+ ZEND_ARG_ARRAY_INFO(0, settings, 1)
+ZEND_END_ARG_INFO();
+static PHP_METHOD(HttpClient, configure)
+{
+ HashTable *settings = NULL;
+ php_http_client_object_t *obj;
+
+ php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|H!", &settings), invalid_arg, return);
+ obj = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ php_http_expect(SUCCESS == php_http_client_setopt(obj->client, PHP_HTTP_CLIENT_OPT_CONFIGURATION, settings), unexpected_val, return);
+
+ RETVAL_ZVAL(getThis(), 1, 0);
+}
+
ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_enablePipelining, 0, 0, 0)
ZEND_ARG_INFO(0, enable)
ZEND_END_ARG_INFO();
PHP_ME(HttpClient, wait, ai_HttpClient_wait, ZEND_ACC_PUBLIC)
PHP_ME(HttpClient, getResponse, ai_HttpClient_getResponse, ZEND_ACC_PUBLIC)
PHP_ME(HttpClient, getHistory, ai_HttpClient_getHistory, ZEND_ACC_PUBLIC)
- PHP_ME(HttpClient, enablePipelining, ai_HttpClient_enablePipelining, ZEND_ACC_PUBLIC)
- PHP_ME(HttpClient, enableEvents, ai_HttpClient_enableEvents, ZEND_ACC_PUBLIC)
+ PHP_ME(HttpClient, configure, ai_HttpClient_configure, ZEND_ACC_PUBLIC)
+ PHP_ME(HttpClient, enablePipelining, ai_HttpClient_enablePipelining, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
+ PHP_ME(HttpClient, enableEvents, ai_HttpClient_enableEvents, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
PHP_ME(HttpClient, notify, ai_HttpClient_notify, ZEND_ACC_PUBLIC)
PHP_ME(HttpClient, attach, ai_HttpClient_attach, ZEND_ACC_PUBLIC)
PHP_ME(HttpClient, detach, ai_HttpClient_detach, ZEND_ACC_PUBLIC)
/* curl options */
-static php_http_options_t php_http_curle_options;
+static php_http_options_t php_http_curle_options, php_http_curlm_options;
#define PHP_HTTP_CURLE_OPTION_CHECK_STRLEN 0x0001
#define PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR 0x0002
return rv;
}
+#if PHP_HTTP_CURL_VERSION(7,30,0)
+static STATUS php_http_curlm_option_set_pipelining_bl(php_http_option_t *opt, zval *value, void *userdata)
+{
+ php_http_client_t *client = userdata;
+ php_http_client_curl_t *curl = client->ctx;
+ CURLM *ch = curl->handle;
+ HashTable tmp_ht;
+ char **bl = NULL;
+ TSRMLS_FETCH_FROM_CTX(client->ts);
+
+ /* array of char *, ending with a NULL */
+ if (value && Z_TYPE_P(value) != IS_NULL) {
+ zval **entry;
+ HashPosition pos;
+ HashTable *ht = HASH_OF(value);
+ int c = zend_hash_num_elements(ht);
+ char **ptr = ecalloc(c + 1, sizeof(char *));
+
+ bl = ptr;
+
+ zend_hash_init(&tmp_ht, c, NULL, ZVAL_PTR_DTOR, 0);
+ array_join(ht, &tmp_ht, 0, ARRAY_JOIN_STRINGIFY);
+
+ FOREACH_HASH_VAL(pos, &tmp_ht, entry) {
+ *ptr++ = Z_STRVAL_PP(entry);
+ }
+ }
+
+ if (CURLM_OK != curl_multi_setopt(ch, opt->option, bl)) {
+ if (bl) {
+ efree(bl);
+ zend_hash_destroy(&tmp_ht);
+ }
+ return FAILURE;
+ }
+
+ if (bl) {
+ efree(bl);
+ zend_hash_destroy(&tmp_ht);
+ }
+ return SUCCESS;
+}
+#endif
+
+#if PHP_HTTP_HAVE_EVENT
+static inline STATUS php_http_curlm_use_eventloop(php_http_client_t *h, zend_bool enable)
+{
+ php_http_client_curl_t *curl = h->ctx;
+
+ if ((curl->useevents = enable)) {
+ if (!curl->evbase) {
+ curl->evbase = event_base_new();
+ }
+ if (!curl->timeout) {
+ curl->timeout = ecalloc(1, sizeof(struct event));
+ }
+ curl_multi_setopt(curl->handle, CURLMOPT_SOCKETDATA, h);
+ curl_multi_setopt(curl->handle, CURLMOPT_SOCKETFUNCTION, php_http_curlm_socket_callback);
+ curl_multi_setopt(curl->handle, CURLMOPT_TIMERDATA, h);
+ curl_multi_setopt(curl->handle, CURLMOPT_TIMERFUNCTION, php_http_curlm_timer_callback);
+ } else {
+ curl_multi_setopt(curl->handle, CURLMOPT_SOCKETDATA, NULL);
+ curl_multi_setopt(curl->handle, CURLMOPT_SOCKETFUNCTION, NULL);
+ curl_multi_setopt(curl->handle, CURLMOPT_TIMERDATA, NULL);
+ curl_multi_setopt(curl->handle, CURLMOPT_TIMERFUNCTION, NULL);
+ }
+
+ return SUCCESS;
+}
+
+static STATUS php_http_curlm_option_set_use_eventloop(php_http_option_t *opt, zval *value, void *userdata)
+{
+ php_http_client_t *client = userdata;
+
+ return php_http_curlm_use_eventloop(client, value && Z_BVAL_P(value));
+}
+#endif
+
+static void php_http_curlm_options_init(php_http_options_t *registry TSRMLS_DC)
+{
+ php_http_option_t *opt;
+
+ /* set size of connection cache */
+ if ((opt = php_http_option_register(registry, ZEND_STRL("maxconnects"), CURLMOPT_MAXCONNECTS, IS_LONG))) {
+ /* -1 == default, 0 == unlimited */
+ ZVAL_LONG(&opt->defval, -1);
+ }
+ /* set max number of connections to a single host */
+#if PHP_HTTP_CURL_VERSION(7,30,0)
+ php_http_option_register(registry, ZEND_STRL("max_host_connections"), CURLMOPT_MAX_HOST_CONNECTIONS, IS_LONG);
+#endif
+ /* maximum number of requests in a pipeline */
+#if PHP_HTTP_CURL_VERSION(7,30,0)
+ if ((opt = php_http_option_register(registry, ZEND_STRL("max_pipeline_length"), CURLMOPT_MAX_PIPELINE_LENGTH, IS_LONG))) {
+ ZVAL_LONG(&opt->defval, 5);
+ }
+#endif
+ /* max simultaneously open connections */
+#if PHP_HTTP_CURL_VERSION(7,30,0)
+ php_http_option_register(registry, ZEND_STRL("max_total_connections"), CURLMOPT_MAX_TOTAL_CONNECTIONS, IS_LONG);
+#endif
+ /* enable/disable HTTP pipelining */
+ php_http_option_register(registry, ZEND_STRL("pipelining"), CURLMOPT_PIPELINING, IS_BOOL);
+ /* chunk length threshold for pipelining */
+#if PHP_HTTP_CURL_VERSION(7,30,0)
+ php_http_option_register(registry, ZEND_STRL("chunk_lenght_penalty_size"), CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, IS_LONG);
+#endif
+ /* size threshold for pipelining penalty */
+#if PHP_HTTP_CURL_VERSION(7,30,0)
+ php_http_option_register(registry, ZEND_STRL("content_length_penalty_size"), CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE, IS_LONG);
+#endif
+ /* pipelining server blacklist */
+#if PHP_HTTP_CURL_VERSION(7,30,0)
+ if ((opt = php_http_option_register(registry, ZEND_STRL("pipelining_server_bl"), CURLMOPT_PIPELINING_SERVER_BL, IS_ARRAY))) {
+ opt->setter = php_http_curlm_option_set_pipelining_bl;
+ }
+#endif
+ /* pipelining host blacklist */
+#if PHP_HTTP_CURL_VERSION(7,30,0)
+ if ((opt = php_http_option_register(registry, ZEND_STRL("pipelining_site_bl"), CURLMOPT_PIPELINING_SITE_BL, IS_ARRAY))) {
+ opt->setter = php_http_curlm_option_set_pipelining_bl;
+ }
+#endif
+ /* events */
+#ifdef PHP_HTTP_HAVE_EVENT
+ if ((opt = php_http_option_register(registry, ZEND_STRL("use_eventloop"), 0, IS_BOOL))) {
+ opt->setter = php_http_curlm_option_set_use_eventloop;
+ }
+#endif
+}
+
+static STATUS php_http_curlm_set_option(php_http_option_t *opt, zval *val, void *userdata)
+{
+ php_http_client_t *client = userdata;
+ php_http_client_curl_t *curl = client->ctx;
+ CURLM *ch = curl->handle;
+ zval *orig = val;
+ CURLMcode rc = CURLM_UNKNOWN_OPTION;
+ STATUS rv = SUCCESS;
+ TSRMLS_FETCH_FROM_CTX(client->ts);
+
+ if (!val) {
+ val = &opt->defval;
+ } else if (Z_TYPE_P(val) != opt->type && !(Z_TYPE_P(val) == IS_NULL && opt->type == IS_ARRAY)) {
+ val = php_http_ztyp(opt->type, val);
+ }
+
+ if (opt->setter) {
+ rv = opt->setter(opt, val, client);
+ } else {
+ switch (opt->type) {
+ case IS_BOOL:
+ if (CURLM_OK != (rc = curl_multi_setopt(ch, opt->option, (long) Z_BVAL_P(val)))) {
+ rv = FAILURE;
+ }
+ break;
+ case IS_LONG:
+ if (CURLM_OK != (rc = curl_multi_setopt(ch, opt->option, Z_LVAL_P(val)))) {
+ rv = FAILURE;
+ }
+ break;
+ default:
+ rv = FAILURE;
+ break;
+ }
+ }
+
+ if (val && val != orig && val != &opt->defval) {
+ zval_ptr_dtor(&val);
+ }
+
+ if (rv != SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Could not set option %s (%s)", opt->name.s, curl_easy_strerror(rc));
+ }
+ return rv;
+}
/* client ops */
php_http_client_curl_t *curl = h->ctx;
switch (opt) {
+ case PHP_HTTP_CLIENT_OPT_CONFIGURATION:
+ return php_http_options_apply(&php_http_curlm_options, (HashTable *) arg, h);
+ break;
+
case PHP_HTTP_CLIENT_OPT_ENABLE_PIPELINING:
if (CURLM_OK != curl_multi_setopt(curl->handle, CURLMOPT_PIPELINING, (long) *((zend_bool *) arg))) {
return FAILURE;
case PHP_HTTP_CLIENT_OPT_USE_EVENTS:
#if PHP_HTTP_HAVE_EVENT
- if ((curl->useevents = *((zend_bool *) arg))) {
- if (!curl->evbase) {
- curl->evbase = event_base_new();
- }
- if (!curl->timeout) {
- curl->timeout = ecalloc(1, sizeof(struct event));
- }
- curl_multi_setopt(curl->handle, CURLMOPT_SOCKETDATA, h);
- curl_multi_setopt(curl->handle, CURLMOPT_SOCKETFUNCTION, php_http_curlm_socket_callback);
- curl_multi_setopt(curl->handle, CURLMOPT_TIMERDATA, h);
- curl_multi_setopt(curl->handle, CURLMOPT_TIMERFUNCTION, php_http_curlm_timer_callback);
- } else {
- curl_multi_setopt(curl->handle, CURLMOPT_SOCKETDATA, NULL);
- curl_multi_setopt(curl->handle, CURLMOPT_SOCKETFUNCTION, NULL);
- curl_multi_setopt(curl->handle, CURLMOPT_TIMERDATA, NULL);
- curl_multi_setopt(curl->handle, CURLMOPT_TIMERFUNCTION, NULL);
- }
+ return php_http_curlm_use_eventloop(h, *(zend_bool *) arg);
break;
#endif
};
if (SUCCESS != php_http_client_driver_add(&driver)) {
- return FAILURE;
- }
+ return FAILURE;
+ }
if (SUCCESS != php_persistent_handle_provide(ZEND_STRL("http\\Client\\Curl"), &php_http_curlm_resource_factory_ops, NULL, NULL TSRMLS_CC)) {
return FAILURE;
php_http_curle_options_init(options TSRMLS_CC);
}
+ if ((options = php_http_options_init(&php_http_curlm_options, 1))) {
+ options->getter = php_http_option_get;
+ options->setter = php_http_curlm_set_option;
+
+ php_http_curlm_options_init(options TSRMLS_CC);
+ }
/*
* HTTP Protocol Version Constants
php_persistent_handle_cleanup(ZEND_STRL("http\\Client\\Curl\\Request"), NULL, 0 TSRMLS_CC);
php_http_options_dtor(&php_http_curle_options);
+ php_http_options_dtor(&php_http_curlm_options);
return SUCCESS;
}
if ((flags & ARRAY_JOIN_PRETTIFY) && hash_key->nKeyLength) {
key = php_http_pretty_key(estrndup(hash_key->arKey, hash_key->nKeyLength - 1), hash_key->nKeyLength - 1, 1, 1);
zend_hash_find(dst, key, hash_key->nKeyLength, (void *) &data);
- } else {
+ } else if (hash_key->nKeyLength) {
zend_hash_quick_find(dst, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void *) &data);
+ } else {
+ zend_hash_index_find(dst, hash_key->h, (void *) &data);
}
if (flags & ARRAY_JOIN_STRINGIFY) {
add_next_index_zval(*data, value);
} else if (key) {
zend_symtable_update(dst, key, hash_key->nKeyLength, &value, sizeof(zval *), NULL);
- } else {
+ } else if (hash_key->nKeyLength) {
zend_hash_quick_add(dst, hash_key->arKey, hash_key->nKeyLength, hash_key->h, &value, sizeof(zval *), NULL);
+ } else {
+ zend_hash_index_update(dst, hash_key->h, (void *) &value, sizeof(zval *), NULL);
}
if (key) {
key = php_http_pretty_key(estrndup(hash_key->arKey, hash_key->nKeyLength - 1), hash_key->nKeyLength - 1, 1, 1);
zend_hash_update(dst, key, hash_key->nKeyLength, (void *) &value, sizeof(zval *), NULL);
efree(key);
- } else {
+ } else if (hash_key->nKeyLength) {
zend_hash_quick_update(dst, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void *) &value, sizeof(zval *), NULL);
+ } else {
+ zend_hash_index_update(dst, hash_key->h, (void *) &value, sizeof(zval *), NULL);
}
}