/*
- * Copyright (C) 2005-2008 Atsushi Konno All rights reserved.
+ * Copyright (C) 2005-2009 Atsushi Konno All rights reserved.
* Copyright (C) 2005 QSDN,Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
apr_status_t rv;
const char *reason;
+ int response_code;
char *response;
apr_size_t response_len;
char *default_chxj_serf_get(request_rec *r, apr_pool_t *ppool, const char *url_path, int set_headers_flag, apr_size_t *response_len);
char *(*chxj_serf_get)(request_rec *r, apr_pool_t *ppool, const char *url_path, int set_headers_flag, apr_size_t *response_len) = default_chxj_serf_get;
-char *default_chxj_serf_post(request_rec *r, apr_pool_t *ppool, const char *url_path, char *post_data, apr_size_t post_data_len, int set_headers_flag, apr_size_t *response_len);
-char *(*chxj_serf_post)(request_rec *r, apr_pool_t *ppool, const char *url_path, char *post_data, apr_size_t post_data_len, int set_headers_flag, apr_size_t *response_len) = default_chxj_serf_post;
+char *default_chxj_serf_post(request_rec *r, apr_pool_t *ppool, const char *url_path, char *post_data, apr_size_t post_data_len, int set_headers_flag, apr_size_t *response_len, int *response_code);
+char *(*chxj_serf_post)(request_rec *r, apr_pool_t *ppool, const char *url_path, char *post_data, apr_size_t post_data_len, int set_headers_flag, apr_size_t *response_len, int *response_code) = default_chxj_serf_post;
+apr_table_t *default_chxj_serf_head(request_rec *r, apr_pool_t *ppool, const char *url_path, int *response_code);
+apr_table_t *(*chxj_serf_head)(request_rec *r, apr_pool_t *ppool, const char *url_path, int *response_code) = default_chxj_serf_head;
void
}
-void
-s_term(apr_pool_t *pool)
-{
- apr_pool_destroy(pool);
-}
-
static serf_bucket_t *
s_connection_setup(apr_socket_t *skt, void *setup_ctx, apr_pool_t *UNUSED(pool))
c = serf_bucket_ssl_decrypt_create(c, ctx->ssl_ctx, ctx->bkt_alloc);
if (!ctx->ssl_ctx) {
ctx->ssl_ctx = serf_bucket_ssl_decrypt_context_get(c);
+ serf_ssl_use_default_certificates(ctx->ssl_ctx);
+ serf_ssl_server_cert_callback_set(ctx->ssl_ctx, NULL, NULL);
}
return c;
}
static apr_status_t
-s_handle_response(serf_request_t *UNUSED(request), serf_bucket_t *response, void *handler_ctx, apr_pool_t *pool)
+s_handle_response(serf_request_t *UNUSED(request), serf_bucket_t *response, void *handler_ctx, apr_pool_t *UNUSED(pool))
{
const char *data;
apr_size_t len;
return rv;
}
ctx->reason = sl.reason;
+ ctx->response_code = sl.code;
while (1) {
rv = serf_bucket_read(response, 2048, &data, &len);
if (SERF_BUCKET_READ_ERROR(rv)) {
ctx->rv = rv;
apr_atomic_dec32(&ctx->requests_outstanding);
+ DBG(ctx->r, "REQ[%X] end of s_handle_response() (ERROR)", (unsigned int)(apr_size_t)ctx->r);
return rv;
}
-
- if (! ctx->response) {
- ctx->response = apr_palloc(pool, len);
- ctx->response[0] = 0;
- ctx->response_len = 0;
+ if (APR_STATUS_IS_EAGAIN(rv)) {
+ /* 0 byte return if EAGAIN returned. */
+ DBG(ctx->r, "REQ[%X] end of s_handle_response() (EAGAIN) len:[%d]", (unsigned int)(apr_size_t)ctx->r, (int)len);
+ return rv;
}
- else {
- char *tmp = apr_palloc(pool, ctx->response_len);
- memcpy(tmp, ctx->response, ctx->response_len);
- ctx->response = apr_palloc(pool, ctx->response_len + len);
- memcpy(ctx->response, tmp, ctx->response_len);
+
+ if (len > 0) {
+ if (! ctx->response) {
+ ctx->response = apr_palloc(ctx->pool, len);
+ ctx->response[0] = 0;
+ ctx->response_len = 0;
+ }
+ else {
+ char *tmp = apr_palloc(ctx->pool, ctx->response_len);
+ memcpy(tmp, ctx->response, ctx->response_len);
+ ctx->response = apr_palloc(ctx->pool, ctx->response_len + len);
+ memcpy(ctx->response, tmp, ctx->response_len);
+ }
+ memcpy(&ctx->response[ctx->response_len], data, len);
+ ctx->response_len += len;
+ ctx->response[ctx->response_len] = 0;
}
- memcpy(&ctx->response[ctx->response_len], data, len);
- ctx->response_len += len;
if (APR_STATUS_IS_EOF(rv)) {
serf_bucket_t *hdrs;
char *tmp_headers = "";
rv = serf_bucket_read(hdrs, 2048, &data, &len);
if (SERF_BUCKET_READ_ERROR(rv))
return rv;
- tmp_headers = apr_pstrcat(ctx->pool, tmp_headers, apr_psprintf(ctx->pool , "%.*s", len, data), NULL);
+ tmp_headers = apr_pstrcat(ctx->pool, tmp_headers, apr_psprintf(ctx->pool , "%.*s", (unsigned int)len, data), NULL);
if (APR_STATUS_IS_EOF(rv)) {
break;
}
}
ctx->rv = APR_SUCCESS;
apr_atomic_dec32(&ctx->requests_outstanding);
- DBG(ctx->r, "end of s_handle_response()(NORMAL)");
+ DBG(ctx->r, "REQ[%X] end of s_handle_response()(NORMAL)", (unsigned int)(apr_size_t)ctx->r);
return APR_EOF;
}
if (APR_STATUS_IS_EAGAIN(rv)) {
- DBG(ctx->r, "end of s_handle_response() (EAGAIN)");
+ DBG(ctx->r, "REQ[%X] end of s_handle_response() (EAGAIN)", (unsigned int)(apr_size_t)ctx->r);
return rv;
}
}
apr_table_entry_t *hentryp = (apr_table_entry_t*)headers->elts;
for (ii=headers->nelts-1; ii>=0; ii--) {
serf_bucket_headers_setc(hdrs_bkt, hentryp[ii].key, hentryp[ii].val);
- DBG(ctx->r, "key:[%s], val:[%s]", hentryp[ii].key, hentryp[ii].val);
+ DBG(ctx->r, "REQ[%X] REQUEST key:[%s], val:[%s]", (unsigned int)(apr_size_t)ctx->r, hentryp[ii].key, hentryp[ii].val);
}
if (ctx->post_data) {
serf_bucket_headers_setc(hdrs_bkt, "X-Chxj-Forward", "Done");
- serf_bucket_headers_setc(hdrs_bkt, "X-Chxj-Content-Length", apr_psprintf(r->pool, "%d", ctx->post_data_len));
+ serf_bucket_headers_setc(hdrs_bkt, "X-Chxj-Content-Length", apr_psprintf(r->pool, "%" APR_SIZE_T_FMT , ctx->post_data_len));
+ DBG(ctx->r, "REQ[%X] REQUEST key:[%s], val:[%s]", (unsigned int)(apr_size_t)ctx->r, "X-Chxj-Forward", "Done");
+ DBG(ctx->r, "REQ[%X] REQUEST key:[%s], val:[%s]", (unsigned int)(apr_size_t)ctx->r, "X-Chxj-Content-Length", apr_psprintf(r->pool, "%" APR_SIZE_T_FMT, ctx->post_data_len));
+
}
- DBG(ctx->r, "Content-Length:[%s]", serf_bucket_headers_get(hdrs_bkt, "Content-Length"));
+ DBG(ctx->r, "REQ[%X] REQUEST Content-Length:[%s]", (unsigned int)(apr_size_t)r, serf_bucket_headers_get(hdrs_bkt, "Content-Length"));
apr_atomic_inc32(&(ctx->requests_outstanding));
if (ctx->acceptor_ctx->ssl_flag) {
if (!url.hostname) {
url.hostname = "localhost";
}
+ if (url.query) {
+ url.path = apr_psprintf(pool, "%s?%s", url.path, url.query);
+ }
rv = apr_sockaddr_info_get(&address, url.hostname, APR_UNSPEC, url.port, 0, pool);
if (rv != APR_SUCCESS) {
char buf[256];
- ERR(r, "apr_sockaddr_info_get() failed: rv:[%d|%s]", rv, apr_strerror(rv, buf, 256));
- s_term(pool);
+ ERR(r, "REQ[%X] %s:%d apr_sockaddr_info_get() failed: rv:[%d|%s] - Please check DNS settings.",
+ (unsigned int)(apr_size_t)r, __FILE__,__LINE__, rv, apr_strerror(rv, buf, 256));
return NULL;
}
memset(&app_ctx, 0, sizeof(app_ctx_t));
handler_ctx.host = url.hostinfo;
handler_ctx.method = "GET";
handler_ctx.path = url.path;
- handler_ctx.user_agent = (char *)apr_table_get(r->headers_in, "User-Agent");
+ handler_ctx.user_agent = (char *)apr_table_get(r->headers_in, CHXJ_HTTP_USER_AGENT);
+ if (!handler_ctx.user_agent) {
+ handler_ctx.user_agent = (char *)apr_table_get(r->headers_in, HTTP_USER_AGENT);
+ }
handler_ctx.post_data = NULL;
handler_ctx.post_data_len = 0;
serf_connection_close(connection);
ret = apr_pstrdup(ppool, handler_ctx.response);
if (set_headers_flag) {
- r->headers_out = apr_table_copy(r->pool, handler_ctx.headers_out);
+ r->headers_out = apr_table_copy(pool, handler_ctx.headers_out);
*response_len = handler_ctx.response_len;
char *contentType = (char *)apr_table_get(handler_ctx.headers_out, "Content-Type");
if (contentType) {
chxj_set_content_type(r, contentType);
}
}
- s_term(pool);
return ret;
}
char *
-default_chxj_serf_post(request_rec *r, apr_pool_t *ppool, const char *url_path, char *post_data, apr_size_t post_data_len, int set_headers_flag, apr_size_t *response_len)
+default_chxj_serf_post(request_rec *r, apr_pool_t *ppool, const char *url_path, char *post_data, apr_size_t post_data_len, int set_headers_flag, apr_size_t *response_len, int *response_code)
{
apr_pool_t *pool;
apr_uri_t url;
handler_ctx_t handler_ctx;
char *ret;
- DBG(r, "start chxj_serf_post()");
+ DBG(r, "REQ:[%X] start chxj_serf_post()", (unsigned int)(apr_size_t)r);
s_init(ppool, &pool);
if (!url.hostname) {
url.hostname = "localhost";
}
+ if (url.query) {
+ url.path = apr_psprintf(pool, "%s?%s", url.path, url.query);
+ }
rv = apr_sockaddr_info_get(&address, url.hostname, APR_UNSPEC, url.port, 0, pool);
if (rv != APR_SUCCESS) {
char buf[256];
ERR(r, "apr_sockaddr_info_get() failed: rv:[%d|%s]", rv, apr_strerror(rv, buf, 256));
- s_term(pool);
return NULL;
}
memset(&app_ctx, 0, sizeof(app_ctx_t));
handler_ctx.host = url.hostinfo;
handler_ctx.method = "POST";
handler_ctx.path = url.path;
- handler_ctx.user_agent = (char *)apr_table_get(r->headers_in, "User-Agent");
+ handler_ctx.user_agent = (char *)apr_table_get(r->headers_in, CHXJ_HTTP_USER_AGENT);
+ if (! handler_ctx.user_agent) {
+ handler_ctx.user_agent = (char *)apr_table_get(r->headers_in, HTTP_USER_AGENT);
+ }
handler_ctx.post_data = post_data;
handler_ctx.post_data_len = post_data_len;
}
DBG(r, "end of serf request");
- DBG(r, "response:[%s][%d]", handler_ctx.response, handler_ctx.response_len);
+ DBG(r, "response_code:[%d]", handler_ctx.response_code);
+ DBG(r, "response:[%s][%" APR_SIZE_T_FMT "]", handler_ctx.response, handler_ctx.response_len);
serf_connection_close(connection);
- ret = apr_pstrdup(ppool, handler_ctx.response);
- if (set_headers_flag) {
- r->headers_out = apr_table_copy(r->pool, handler_ctx.headers_out);
+ if (handler_ctx.response) {
+ ret = apr_pstrdup(ppool, handler_ctx.response);
+ }
+ else {
+ ret = apr_pstrdup(ppool, "");
+ }
+ if (set_headers_flag && !rv) {
+ r->headers_out = apr_table_copy(pool, handler_ctx.headers_out);
*response_len = handler_ctx.response_len;
char *contentType = (char *)apr_table_get(handler_ctx.headers_out, "Content-Type");
if (contentType) {
chxj_set_content_type(r, apr_pstrdup(r->pool, contentType));
}
}
- s_term(pool);
- DBG(r, "end chxj_serf_post()");
+ if (rv) {
+ *response_len = 0;
+ }
+ *response_code = handler_ctx.response_code;
+ DBG(r, "REQ:[%X] end chxj_serf_post()", (unsigned int)(apr_size_t)r);
return ret;
}
+
+
+apr_table_t *
+default_chxj_serf_head(request_rec *r, apr_pool_t *ppool, const char *url_path, int *response_code)
+{
+ apr_pool_t *pool;
+ apr_uri_t url;
+ apr_status_t rv;
+ apr_sockaddr_t *address = NULL;
+
+ serf_context_t *context;
+ serf_connection_t *connection;
+
+ app_ctx_t app_ctx;
+ handler_ctx_t handler_ctx;
+ char *ret;
+
+ DBG(r, "REQ:[%X] start chxj_serf_head()", (unsigned int)(apr_size_t)r);
+
+
+ s_init(ppool, &pool);
+
+ apr_uri_parse(pool, url_path, &url);
+ if (!url.port) {
+ url.port = apr_uri_port_of_scheme(url.scheme);
+ }
+ if (!url.port) {
+ url.port = 80;
+ }
+ if (!url.path) {
+ url.path = "/";
+ }
+ if (!url.hostname) {
+ url.hostname = "localhost";
+ }
+ if (url.query) {
+ url.path = apr_psprintf(pool, "%s?%s", url.path, url.query);
+ }
+
+ rv = apr_sockaddr_info_get(&address, url.hostname, APR_UNSPEC, url.port, 0, pool);
+ if (rv != APR_SUCCESS) {
+ char buf[256];
+ ERR(r, "apr_sockaddr_info_get() failed: rv:[%d|%s]", rv, apr_strerror(rv, buf, 256));
+ return NULL;
+ }
+ memset(&app_ctx, 0, sizeof(app_ctx_t));
+
+ app_ctx.bkt_alloc = serf_bucket_allocator_create(pool, NULL, NULL);
+ if (strcasecmp(url.scheme, "https") == 0) {
+ app_ctx.ssl_flag = 1;
+ }
+
+ context = serf_context_create(pool);
+ connection = serf_connection_create(context, address, s_connection_setup, &app_ctx, s_connection_closed, &app_ctx, pool);
+
+ memset(&handler_ctx, 0, sizeof(handler_ctx_t));
+ handler_ctx.requests_outstanding = 0;
+ handler_ctx.host = url.hostinfo;
+ /*========================================================================================================*/
+ /* XXX Maybe, libserf doesn't support the HEAD request. Because the part body is waited for with polling. */
+ /*========================================================================================================*/
+ handler_ctx.method = "GET";
+ handler_ctx.path = url.path;
+ handler_ctx.user_agent = (char *)apr_table_get(r->headers_in, CHXJ_HTTP_USER_AGENT);
+ if (! handler_ctx.user_agent) {
+ handler_ctx.user_agent = (char *)apr_table_get(r->headers_in, HTTP_USER_AGENT);
+ }
+ handler_ctx.post_data = NULL;
+ handler_ctx.post_data_len = 0;
+
+ handler_ctx.acceptor = s_accept_response;
+ handler_ctx.acceptor_ctx = &app_ctx;
+ handler_ctx.handler = s_handle_response;
+ handler_ctx.pool = pool;
+ handler_ctx.r = r;
+ handler_ctx.response_len = 0;
+ handler_ctx.response = NULL;
+
+ serf_connection_request_create(connection, s_setup_request, &handler_ctx);
+
+ while (1) {
+ rv = serf_context_run(context, SERF_DURATION_FOREVER, pool);
+ if (APR_STATUS_IS_TIMEUP(rv))
+ continue;
+ if (rv) {
+ char buf[200];
+ ERR(r, "Error running context: (%d) %s\n", rv, apr_strerror(rv, buf, sizeof(buf)));
+ break;
+ }
+ if (!apr_atomic_read32(&handler_ctx.requests_outstanding)) {
+ if (handler_ctx.rv != APR_SUCCESS) {
+ char buf[200];
+ ERR(r, "Error running context: (%d) %s\n", handler_ctx.rv, apr_strerror(handler_ctx.rv, buf, sizeof(buf)));
+ }
+ break;
+ }
+ }
+
+ DBG(r, "end of serf request");
+ DBG(r, "response_code:[%d]", handler_ctx.response_code);
+ DBG(r, "response:[%s][%" APR_SIZE_T_FMT "]", handler_ctx.response, handler_ctx.response_len);
+ serf_connection_close(connection);
+ if (handler_ctx.response) {
+ ret = apr_pstrdup(ppool, handler_ctx.response);
+ }
+ else {
+ ret = apr_pstrdup(ppool, "");
+ }
+ *response_code = handler_ctx.response_code;
+ DBG(r, "REQ:[%X] end chxj_serf_post()", (unsigned int)(apr_size_t)r);
+ return handler_ctx.headers_out;
+}
/*
* vim:ts=2 et
*/