[mod-lisp-devel] Chunked encoding
Hugh Winkler
hughw at hughw.net
Wed Dec 20 21:24:58 UTC 2006
Hi all,
I see this topic was raised a couple of months ago :
http://common-lisp.net/pipermail/mod-lisp-devel/2006-October/thread.html#99.
I've made changes to mod_lisp2.c to support chunked encoding. Sorry,
I only have a 2.0.55 to run against atm, so I have not backported to
1.3.
Notes:
Apache 2 has eliminated REQUEST_CHUNKED_DECHUNK, meaning there's no
way to receive chunked data — Apache will always dechunkify it.
I considered signaling the end of the stream by sending MSG_OOB. Well,
apr does not support that. So the only option left was to re-chunk the
data. I opted to re-chunk according to RFC 2616 so that on the Lisp
side we can use Dr. Weitz' Chunga[1] to de-chunk.
The new behavior is compatible with existing code on the Lisp side
e.g. Kevin Rosenberg's modlisp. The mod_lisp2 code only chunks if the
Content-length header is omitted; formerly, Lisp side code could not
work properly if Content-length was omitted anyway.
There is one maybe extraneous change in this patch: I eliminated some
gcc compiler warnings issuing from local_lisp_cfg(). Here is my gcc
version string: (GCC) 4.1.2 20060928 (prerelease) (Ubuntu
4.1.1-13ubuntu5). This change is not essential but it's nice to build
with no warnings.
Thanks Mark for mod_lisp... sorry I'm no help on the 1.3 backport.
Hugh
[1] http://weitz.de/chunga/
--- ../libapache2-mod-lisp2-1.3.1-orig/mod_lisp2.c 2006-12-20
13:23:46.000000000 -0600
+++ mod_lisp2.c 2006-12-20 14:01:47.000000000 -0600
@@ -58,6 +58,11 @@
/*
Change log:
+ If request contains chunked data, send chunks (length word plus data)
+ to backend lisp. Also eliminated a gcc warning.
+ -- Hugh Winkler
+ 2006-12-05
+
Fixed the APR 1.2.2 detection.
-- sent by several people
2006-1203
@@ -231,7 +236,7 @@
static header_map_t map_header_to_lisp_header;
static int write_client_data
(request_rec * r, const char * data, unsigned int n_bytes);
-
+
/* Configuration data */
static lisp_cfg_t *
@@ -284,19 +289,19 @@
static lisp_cfg_t *
local_lisp_cfg (lisp_cfg_t *cfg)
{
- lisp_cfg_t *local_cfg = NULL;
-
- apr_threadkey_private_get((void**)&local_cfg, cfg_key);
+ void *local_cfg = NULL;
+
+ apr_threadkey_private_get(&local_cfg, cfg_key);
if (local_cfg == NULL)
{
local_cfg = copy_lisp_cfg (socket_pool, cfg);
- apr_threadkey_private_set((void*)local_cfg, cfg_key);
+ apr_threadkey_private_set(local_cfg, cfg_key);
return local_cfg;
}
check_cfg_for_reuse(local_cfg, cfg);
- return local_cfg;
+ return (lisp_cfg_t*) local_cfg;
}
#else
lisp_cfg_t *local_cfg;
@@ -433,6 +438,26 @@
}
static apr_status_t
+write_lisp_data_chunk (apr_socket_t * socket,
+ const char * data, unsigned int n_bytes)
+{
+ char crlf[2] = {0xd, 0xa};
+ char length[16];
+ snprintf(length, 16, "%x", n_bytes);
+
+ apr_status_t status = write_lisp_data (socket, length, strlen(length));
+ if ( status == APR_SUCCESS)
+ {
+ status = write_lisp_data (socket, crlf, 2);
+ if ( status == APR_SUCCESS && n_bytes)
+ status = write_lisp_data (socket, data, n_bytes);
+ if ( status == APR_SUCCESS)
+ status = write_lisp_data (socket, crlf, 2);
+ }
+ return status;
+}
+
+static apr_status_t
write_lisp_line (apr_socket_t * socket, const char * data)
{
RELAY_ERROR (write_lisp_data (socket, data, (strlen (data))));
@@ -555,6 +580,7 @@
int content_length = (-1);
int keep_socket_p = 0;
apr_socket_t * socket;
+ const char * request_content_length = 0;
cfg = local_lisp_cfg(cfg);
@@ -600,6 +626,8 @@
((copy_headers ((r->headers_in), map_header_to_lisp_header, socket)),
"writing to Lisp");
+ request_content_length = apr_table_get(r->headers_in, "Content-Length");
+
/* Send the end-of-headers marker. */
ML_LOG_DEBUG (r, "write end-of-headers");
CVT_ERROR ((write_lisp_line (socket, "end")), "writing to Lisp");
@@ -619,21 +647,31 @@
close_lisp_socket (cfg);
return (HTTP_INTERNAL_SERVER_ERROR);
}
- if (n_read == 0)
- break;
+ /* for chunked case, when nread == 0, we will write
+ * a terminating 0.*/
+
{
- apr_status_t status = (write_lisp_data (socket, buffer, n_read));
+ apr_status_t status = APR_SUCCESS;
+
+ /* if there's no Content-Type header, the data must be chunked */
+ if (request_content_length == NULL)
+ status = write_lisp_data_chunk (socket, buffer, n_read);
+ else if (n_read != 0)
+ status = write_lisp_data (socket, buffer, n_read);
+
if (APR_SUCCESS != status)
{
- while ((ap_get_client_block (r, buffer, (sizeof (buffer))))
- > 0)
+ while ((ap_get_client_block (r, buffer, sizeof(buffer)))
+ > 0)
;
ML_LOG_ERROR (status, r, "writing to Lisp");
close_lisp_socket (cfg);
return (HTTP_INTERNAL_SERVER_ERROR);
}
}
+ if( n_read == 0)
+ break;
}
}
More information about the mod-lisp-devel
mailing list