PHP_ARG_ENABLE([http], [whether to enable extended HTTP support],
[ --enable-http Enable extended HTTP support])
+PHP_ARG_ENABLE([http-persistent-handles], [whether to enable per-process persistent cURL handles],
+[ --enable-http-persistent-handles
+ HTTP: enable per-process persistent cURL handles], "no", "no")
+PHP_ARG_WITH([http-shared-deps], [whether to depend on extensions which have been built shared],
+[ --with-http-shared-deps
+ HTTP: disable to not depend on extensions like hash,
+ iconv and session (when built shared)], $PHP_HTTP, $PHP_HTTP)
PHP_ARG_WITH([http-curl-requests], [whether to enable cURL HTTP request support],
[ --with-http-curl-requests[=LIBCURLDIR]
HTTP: with cURL request support], $PHP_HTTP, $PHP_HTTP)
PHP_ARG_WITH([http-magic-mime], [whether to enable response content type guessing],
[ --with-http-magic-mime[=LIBMAGICDIR]
HTTP: with magic mime response content type guessing], "no", "no")
-PHP_ARG_WITH([http-shared-deps], [whether to depend on extensions which have been built shared],
-[ --with-http-shared-deps HTTP: disable to not depend on extensions like hash,
- iconv and session (when built shared)], $PHP_HTTP, $PHP_HTTP)
if test "$PHP_HTTP" != "no"; then
[AC_DEFINE([HAVE_CURL_MULTI_TIMEOUT], [1], [ ])], [ ],
[$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR]
)
+
+ dnl persistent cURL handles
+ AC_MSG_CHECKING([whether to enable per-process persistent cURL handles])
+ if test "$PHP_HTTP_PERSISTENT_HANDLES" != "no"; then
+ AC_DEFINE([HTTP_HAVE_PERSISTENT_HANDLES], [1], [Have per-process persistent cURL handles])
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ fi
fi
dnl ----
http_info_api.c http_request_method_api.c http_encoding_api.c \
http_filter_api.c http_request_body_api.c http_querystring_object.c \
http_deflatestream_object.c http_inflatestream_object.c http_cookie_api.c \
- http_querystring_api.c http_request_datashare_api.c http_requestdatashare_object.c"
+ http_querystring_api.c http_request_datashare_api.c http_requestdatashare_object.c \
+ http_persistent_handle_api.c"
PHP_NEW_EXTENSION([http], $PHP_HTTP_SOURCES, $ext_shared)
php_http_exception_object.h php_http_message_object.h php_http_request_object.h \
php_http_requestpool_object.h php_http_response_object.h php_http_util_object.h \
php_http_querystring_object.h php_http_deflatestream_object.h php_http_inflatestream_object.h \
- php_http_cookie_api.h php_http_querystring_api.h php_http_request_datashare_api.h php_http_requestdatashare_object.h"
+ php_http_cookie_api.h php_http_querystring_api.h php_http_request_datashare_api.h php_http_requestdatashare_object.h \
+ php_http_persistent_handle_api.h"
ifdef([PHP_INSTALL_HEADERS], [
PHP_INSTALL_HEADERS(ext/http, $PHP_HTTP_HEADERS)
], [
#ifdef HTTP_HAVE_CURL
# include "php_http_request_api.h"
# include "php_http_request_datashare_api.h"
+# ifdef HTTP_HAVE_PERSISTENT_HANDLES
+# include "php_http_persistent_handle_api.h"
+# endif
#endif
#ifdef HTTP_HAVE_ZLIB
# include "php_http_encoding_api.h"
PHP_FE(http_get_request_body_stream, NULL)
PHP_FE(http_match_request_header, NULL)
#ifdef HTTP_HAVE_CURL
+# ifdef HTTP_HAVE_PERSISTENT_HANDLES
+ PHP_FE(http_persistent_handles_count, NULL)
+ PHP_FE(http_persistent_handles_clean, NULL)
+# endif
PHP_FE(http_get, http_arg_pass_ref_3)
PHP_FE(http_head, http_arg_pass_ref_3)
PHP_FE(http_post_data, http_arg_pass_ref_4)
(SUCCESS != PHP_MINIT_CALL(http_send)) ||
(SUCCESS != PHP_MINIT_CALL(http_url)) ||
#ifdef HTTP_HAVE_CURL
+# ifdef HTTP_HAVE_PERSISTENT_HANDLES
+ (SUCCESS != PHP_MINIT_CALL(http_persistent_handle)) ||
+# endif
(SUCCESS != PHP_MINIT_CALL(http_request)) ||
# ifdef ZEND_ENGINE_2
(SUCCESS != PHP_MINIT_CALL(http_request_datashare)) ||
# ifdef ZEND_ENGINE_2
(SUCCESS != PHP_MSHUTDOWN_CALL(http_request_datashare)) ||
# endif
- (SUCCESS != PHP_MSHUTDOWN_CALL(http_request))) {
+ (SUCCESS != PHP_MSHUTDOWN_CALL(http_request))
+# ifdef HTTP_HAVE_PERSISTENT_HANDLES
+ || (SUCCESS != PHP_MSHUTDOWN_CALL(http_persistent_handle))
+# endif
+ ) {
return FAILURE;
}
#endif
#include "php_http_message_api.h"
#include "php_http_request_api.h"
#include "php_http_request_method_api.h"
+#include "php_http_persistent_handle_api.h"
#include "php_http_send_api.h"
#include "php_http_url_api.h"
/* {{{ HAVE_CURL */
#ifdef HTTP_HAVE_CURL
+#ifdef HTTP_HAVE_PERSISTENT_HANDLES
+
+/* {{{ proto object http_persistent_handles_count() */
+PHP_FUNCTION(http_persistent_handles_count)
+{
+ char **names;
+ int *counts;
+ int i, n;
+
+ NO_ARGS;
+
+ if ((n = http_persistent_handle_statall(&names, &counts))) {
+ object_init(return_value);
+ for (i = 0; i < n; ++i) {
+ add_property_long(return_value, names[i], counts[i]);
+ efree(names[i]);
+ }
+ efree(names);
+ efree(counts);
+ }
+}
+/* }}} */
+
+/* {{{ proto void http_persistent_handles_clean([string name]) */
+PHP_FUNCTION(http_persistent_handles_clean)
+{
+ char *name_str = NULL;
+ int name_len = 0;
+
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name_str, &name_len)) {
+ http_persistent_handle_cleanup_ex(name_str, name_len);
+ }
+}
+/* }}} */
+
+#endif /* HTTP_HAVE_PERSISTENT_HANDLES */
#define RETVAL_RESPONSE_OR_BODY(request) \
{ \
--- /dev/null
+/*
+ +--------------------------------------------------------------------+
+ | PECL :: http |
+ +--------------------------------------------------------------------+
+ | Redistribution and use in source and binary forms, with or without |
+ | modification, are permitted provided that the conditions mentioned |
+ | in the accompanying LICENSE file are met. |
+ +--------------------------------------------------------------------+
+ | Copyright (c) 2004-2006, Michael Wallner <mike@php.net> |
+ +--------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#include "php_http.h"
+
+#ifdef HTTP_HAVE_PERSISTENT_HANDLES
+
+#include "php_http_persistent_handle_api.h"
+
+static HashTable http_persistent_handles_hash;
+#ifdef ZTS
+# define LOCK() tsrm_mutex_lock(http_persistent_handles_lock)
+# define UNLOCK() tsrm_mutex_unlock(http_persistent_handles_lock)
+static MUTEX_T http_persistent_handles_lock;
+#else
+# define LOCK()
+# define UNLOCK()
+#endif
+
+typedef struct _http_persistent_handles_hash_entry_t {
+ HashTable list;
+ http_persistent_handle_ctor ctor;
+ http_persistent_handle_dtor dtor;
+} http_persistent_handles_hash_entry;
+
+typedef struct _http_persistent_handles_list_entry_t {
+ void *handle;
+} http_persistent_handles_list_entry;
+
+static inline void http_persistent_handles_hash_dtor_ex(http_persistent_handles_hash_entry *hentry, void (*list_dtor)(HashTable*))
+{
+ http_persistent_handles_list_entry *lentry;
+
+ for ( zend_hash_internal_pointer_reset(&hentry->list);
+ SUCCESS == zend_hash_get_current_data(&hentry->list, (void *) &lentry);
+ zend_hash_move_forward(&hentry->list)) {
+ hentry->dtor(lentry->handle);
+ }
+
+ if (list_dtor) {
+ list_dtor(&hentry->list);
+ }
+}
+
+static void http_persistent_handles_hash_dtor(void *h)
+{
+ http_persistent_handles_hash_dtor_ex(h, zend_hash_destroy);
+}
+
+PHP_MINIT_FUNCTION(http_persistent_handle)
+{
+ zend_hash_init(&http_persistent_handles_hash, 0, NULL, http_persistent_handles_hash_dtor, 1);
+#ifdef ZTS
+ http_persistent_handles_lock = tsrm_mutex_alloc();
+#endif
+ return SUCCESS;
+}
+
+PHP_MSHUTDOWN_FUNCTION(http_persistent_handle)
+{
+ zend_hash_destroy(&http_persistent_handles_hash);
+#ifdef ZTS
+ tsrm_mutex_free(http_persistent_handles_lock);
+#endif
+ return SUCCESS;
+}
+
+PHP_HTTP_API STATUS _http_persistent_handle_provide_ex(const char *name_str, size_t name_len, http_persistent_handle_ctor ctor, http_persistent_handle_dtor dtor)
+{
+ STATUS status = SUCCESS;
+ http_persistent_handles_hash_entry e;
+
+ zend_hash_init(&e.list, 0, NULL, NULL, 1);
+ e.ctor = ctor;
+ e.dtor = dtor;
+
+ LOCK();
+ if (SUCCESS != zend_hash_add(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &e, sizeof(http_persistent_handles_hash_entry), NULL)) {
+ zend_hash_destroy(&e.list);
+ status = FAILURE;
+ }
+ UNLOCK();
+
+ return status;
+}
+
+PHP_HTTP_API void _http_persistent_handle_cleanup_ex(const char *name_str, size_t name_len)
+{
+ http_persistent_handles_hash_entry *hentry;
+
+ LOCK();
+ if (name_str && name_len) {
+ if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &hentry)) {
+ http_persistent_handles_hash_dtor_ex(hentry, zend_hash_clean);
+ }
+ } else {
+ for ( zend_hash_internal_pointer_reset(&http_persistent_handles_hash);
+ SUCCESS == zend_hash_get_current_data(&http_persistent_handles_hash, (void *) &hentry);
+ zend_hash_move_forward(&http_persistent_handles_hash)) {
+ http_persistent_handles_hash_dtor_ex(hentry, zend_hash_clean);
+ }
+ }
+ UNLOCK();
+}
+
+PHP_HTTP_API int _http_persistent_handle_statall_ex(char ***names, int **counts, int persistent)
+{
+ int i, n;
+ char *key;
+ http_persistent_handles_hash_entry *hentry;
+
+ LOCK();
+ if ((n = zend_hash_num_elements(&http_persistent_handles_hash))) {
+ *names = safe_pemalloc(n, sizeof(char **), 0, persistent);
+ *counts = safe_pemalloc(n, sizeof(int), 0, persistent);
+
+ for ( i = 0, zend_hash_internal_pointer_reset(&http_persistent_handles_hash);
+ HASH_KEY_NON_EXISTANT != zend_hash_get_current_key(&http_persistent_handles_hash, &key, NULL, 0) &&
+ SUCCESS == zend_hash_get_current_data(&http_persistent_handles_hash, (void *) &hentry);
+ ++i, zend_hash_move_forward(&http_persistent_handles_hash)) {
+ (*names)[i] = pestrdup(key, persistent);
+ (*counts)[i] = zend_hash_num_elements(&hentry->list);
+ }
+ }
+ UNLOCK();
+
+ return n;
+}
+
+PHP_HTTP_API STATUS _http_persistent_handle_acquire_ex(const char *name_str, size_t name_len, void **handle)
+{
+ STATUS status = FAILURE;
+ ulong index;
+ http_persistent_handles_hash_entry *hentry;
+ http_persistent_handles_list_entry *lentry;
+
+ LOCK();
+ if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &hentry)) {
+ zend_hash_internal_pointer_reset(&hentry->list);
+ if ( HASH_KEY_NON_EXISTANT != zend_hash_get_current_key(&hentry->list, NULL, &index, 0) &&
+ SUCCESS == zend_hash_get_current_data(&hentry->list, (void *) &lentry)) {
+ *handle = lentry->handle;
+ zend_hash_index_del(&hentry->list, index);
+ status = SUCCESS;
+ } else if ((*handle = hentry->ctor())) {
+ status = SUCCESS;
+ }
+ }
+ UNLOCK();
+
+ return status;
+}
+
+PHP_HTTP_API STATUS _http_persistent_handle_release_ex(const char *name_str, size_t name_len, void **handle)
+{
+ STATUS status = FAILURE;
+ http_persistent_handles_hash_entry *hentry;
+ http_persistent_handles_list_entry lentry;
+
+ LOCK();
+ if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &hentry)) {
+ lentry.handle = *handle;
+ if (SUCCESS == zend_hash_next_index_insert(&hentry->list, (void *) &lentry, sizeof(http_persistent_handles_list_entry), NULL)) {
+ status = SUCCESS;
+ }
+ }
+ UNLOCK();
+
+ return status;
+}
+
+#endif /* HTTP_HAVE_PERSISTENT_HANDLES */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
+
#include "php_http_api.h"
#include "php_http_request_api.h"
#include "php_http_url_api.h"
+#ifdef HTTP_HAVE_PERSISTENT_HANDLES
+# include "php_http_persistent_handle_api.h"
+#endif
#ifdef ZEND_ENGINE_2
# include "php_http_request_object.h"
return FAILURE;
}
+#ifdef HTTP_HAVE_PERSISTENT_HANDLES
+ if (SUCCESS != http_persistent_handle_provide("http_request", curl_easy_init, curl_easy_cleanup)) {
+ return FAILURE;
+ }
+#endif
+
HTTP_LONG_CONSTANT("HTTP_AUTH_BASIC", CURLAUTH_BASIC);
HTTP_LONG_CONSTANT("HTTP_AUTH_DIGEST", CURLAUTH_DIGEST);
HTTP_LONG_CONSTANT("HTTP_AUTH_NTLM", CURLAUTH_NTLM);
static curlioerr http_curl_ioctl_callback(CURL *, curliocmd, void *);
/* }}} */
+#ifdef HTTP_HAVE_PERSISTENT_HANDLES
+# define HTTP_CURL_HANDLE_CTOR(ch) (SUCCESS == http_persistent_handle_acquire("http_request", &(ch)))
+# define HTTP_CURL_HANDLE_DTOR(chp) http_persistent_handle_release("http_request", (chp))
+#else
+# define HTTP_CURL_HANDLE_CTOR(ch) ((ch) = curl_easy_init())
+# define HTTP_CURL_HANDLE_DTOR(chp) curl_easy_cleanup(*(chp)); *(chp) = NULL
+#endif
+
/* {{{ CURL *http_curl_init(http_request *) */
PHP_HTTP_API CURL * _http_curl_init_ex(CURL *ch, http_request *request)
{
- if (ch || (ch = curl_easy_init())) {
+ if (ch || HTTP_CURL_HANDLE_CTOR(ch)) {
#if defined(ZTS)
curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1L);
#endif
PHP_HTTP_API void _http_curl_free(CURL **ch)
{
if (*ch) {
- /* avoid nasty segfaults with already cleaned up callbacks */
curl_easy_setopt(*ch, CURLOPT_NOPROGRESS, 1L);
curl_easy_setopt(*ch, CURLOPT_PROGRESSFUNCTION, NULL);
curl_easy_setopt(*ch, CURLOPT_VERBOSE, 0L);
curl_easy_setopt(*ch, CURLOPT_DEBUGFUNCTION, NULL);
- curl_easy_cleanup(*ch);
- *ch = NULL;
+
+ HTTP_CURL_HANDLE_DTOR(ch);
}
}
/* }}} */
<date>2007-01-23</date>
<version>
<release>1.5.0dev</release>
- <api>1.4.0</api>
+ <api>1.5.0</api>
</version>
<stability>
<release>beta</release>
</stability>
<license>BSD, revised</license>
<notes><![CDATA[
-+ Add HttpMessage::fromEnv(int type[, string class_name = "HttpMessage"]) (Clay Loveless)
++ Added HttpMessage::fromEnv(int type[, string class_name = "HttpMessage"]) (Clay Loveless)
++ Added --enable-http-persistent-handles (Clay Loveless)
]]></notes>
<contents>
<dir name="/">
<file role="src" name="php_http_headers_api.h"/>
<file role="src" name="php_http_info_api.h"/>
<file role="src" name="php_http_message_api.h"/>
+ <file role="src" name="php_http_persistent_handles_api.h"/>
<file role="src" name="php_http_querystring_api.h"/>
<file role="src" name="php_http_request_api.h"/>
<file role="src" name="php_http_request_int.h"/>
<file role="src" name="http_headers_api.c"/>
<file role="src" name="http_info_api.c"/>
<file role="src" name="http_message_api.c"/>
+ <file role="src" name="http_persistent_handles_api.c"/>
<file role="src" name="http_querystring_api.c"/>
<file role="src" name="http_request_api.c"/>
<file role="src" name="http_request_info.c"/>
prompt="whether to depend on extensions which have been built shared"
default="yes"
/>
+ <configureoption
+ name="enable-http-persistent-handles"
+ prompt="whether to enable per-process persistent cURL handles"
+ default="no"
+ />
<filelist>
<install as="http.ini" name="docs/http.ini"/>
<install as="examples/tutorial.txt" name="docs/examples/tutorial.txt"/>
PHP_FUNCTION(http_get_request_body_stream);
PHP_FUNCTION(http_match_request_header);
#ifdef HTTP_HAVE_CURL
+# ifdef HTTP_HAVE_PERSISTENT_HANDLES
+PHP_FUNCTION(http_persistent_handles_count);
+PHP_FUNCTION(http_persistent_handles_clean);
+# endif
PHP_FUNCTION(http_get);
PHP_FUNCTION(http_head);
PHP_FUNCTION(http_post_data);
--- /dev/null
+/*
+ +--------------------------------------------------------------------+
+ | PECL :: http |
+ +--------------------------------------------------------------------+
+ | Redistribution and use in source and binary forms, with or without |
+ | modification, are permitted provided that the conditions mentioned |
+ | in the accompanying LICENSE file are met. |
+ +--------------------------------------------------------------------+
+ | Copyright (c) 2004-2006, Michael Wallner <mike@php.net> |
+ +--------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifndef HTTP_PERSISTENT_HANDLE_H
+#define HTTP_PERSISTENT_HANDLE_H
+
+#ifdef HTTP_HAVE_PERSISTENT_HANDLES
+typedef void *(*http_persistent_handle_ctor)(void);
+typedef void (*http_persistent_handle_dtor)(void *handle);
+
+PHP_MINIT_FUNCTION(http_persistent_handle);
+PHP_MSHUTDOWN_FUNCTION(http_persistent_handle);
+
+#define http_persistent_handle_provide(n, c, d) _http_persistent_handle_provide_ex((n), strlen(n), (c), (d))
+#define http_persistent_handle_provide_ex(n, l, c, d) _http_persistent_handle_provide_ex((n), (l), (c), (d))
+PHP_HTTP_API STATUS _http_persistent_handle_provide_ex(const char *name_str, size_t name_len, http_persistent_handle_ctor ctor, http_persistent_handle_dtor dtor);
+
+#define http_persistent_handle_cleanup(n) _http_persistent_handle_cleanup_ex((n), strlen(n))
+#define http_persistent_handle_cleanup_ex(n, l) _http_persistent_handle_cleanup_ex((n), (l))
+PHP_HTTP_API void _http_persistent_handle_cleanup_ex(const char *name_str, size_t name_len);
+
+#define http_persistent_handle_statall(n, c) _http_persistent_handle_statall_ex((n), (c), 0)
+#define http_persistent_handle_statall_ex(n, c, p) _http_persistent_handle_statall_ex((n), (c), (p))
+PHP_HTTP_API int _http_persistent_handle_statall_ex(char ***names, int **counts, int persistent);
+
+#define http_persistent_handle_acquire(n, h) _http_persistent_handle_acquire_ex((n), strlen(n), (h))
+#define http_persistent_handle_acquire_ex(n, l, h) _http_persistent_handle_acquire_ex((n), (l), (h))
+PHP_HTTP_API STATUS _http_persistent_handle_acquire_ex(const char *name_str, size_t name_len, void **handle);
+
+#define http_persistent_handle_release(n, h) _http_persistent_handle_release_ex((n), strlen(n), (h))
+#define http_persistent_handle_release_ex(n, l, h) _http_persistent_handle_release_ex((n), (l), (h))
+PHP_HTTP_API STATUS _http_persistent_handle_release_ex(const char *name_str, size_t name_len, void **handle);
+
+#endif /* HTTP_HAVE_PERSISTENT_HANDLES */
+#endif /* HTTP_PERSISTENT_HANDLE_H */