This patch switches mod_dav to use brigades for input when
handling PUT.
My one caveat with this is what to do when the filters return
an error (spec. AP_FILTER_ERROR which means that they already
took care of it). In this case, the handler should NOT generate
an error of its own and just return the AP_FILTER_ERROR value
back. mod_dav has its own error handling, so its not as
straightforward as the other modules.
Greg? Anyone else? -- justin
Index: modules/dav/main/mod_dav.c
===================================================================
RCS file: /home/cvs/httpd-2.0/modules/dav/main/mod_dav.c,v
retrieving revision 1.79
diff -u -r1.79 mod_dav.c
--- modules/dav/main/mod_dav.c 17 May 2002 11:33:08 -0000 1.79
+++ modules/dav/main/mod_dav.c 2 Jun 2002 23:12:53 -0000
@@ -868,10 +868,6 @@
apr_off_t range_start;
apr_off_t range_end;
- if ((result = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK)) != OK) {
- return result;
- }
-
/* Ask repository module to resolve the resource */
err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
&resource);
@@ -946,40 +942,73 @@
}
if (err == NULL) {
- if (ap_should_client_block(r)) {
- char *buffer = apr_palloc(r->pool, DAV_READ_BLOCKSIZE);
- long len;
+ apr_bucket_brigade *brigade;
+ apr_bucket *bucket;
+ apr_status_t rv;
+ int seen_eos;
+
+ brigade = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+ seen_eos = 0;
+
+ /*
+ * ### what happens if we read more/less than the amount
+ * ### specified in the Content-Range? eek...
+ */
+ do {
+ rv = ap_get_brigade(r->input_filters, brigade, AP_MODE_READBYTES,
+ APR_BLOCK_READ, DAV_READ_BLOCKSIZE);
/*
- * Once we start reading the request, then we must read the
- * whole darn thing. ap_discard_request_body() won't do anything
- * for a partially-read request.
+ * Error reading request body. This has precedence over
+ * prior errors.
*/
-
- while ((len = ap_get_client_block(r, buffer,
- DAV_READ_BLOCKSIZE)) > 0) {
- if (err == NULL) {
- /* write whatever we read, until we see an error */
- err = (*resource->hooks->write_stream)(stream,
- buffer, len);
- }
+ if (rv != APR_SUCCESS) {
+ /* If the filter didn't handle this error. */
+ if (rv != AP_FILTER_ERROR) {
+ rv = HTTP_BAD_REQUEST;
+ }
+
+ err = dav_new_error(r->pool, rv, 0,
+ "An error occurred while reading the "
+ "request body.");
+ break;
}
- /*
- * ### what happens if we read more/less than the amount
- * ### specified in the Content-Range? eek...
- */
-
- if (len == -1) {
- /*
- * Error reading request body. This has precedence over
- * prior errors.
- */
- err = dav_new_error(r->pool, HTTP_BAD_REQUEST, 0,
- "An error occurred while reading the "
- "request body.");
+ APR_BRIGADE_FOREACH(bucket, brigade) {
+ const char *data;
+ apr_size_t len;
+
+ if (APR_BUCKET_IS_EOS(bucket)) {
+ seen_eos = 1;
+ break;
+ }
+
+ /* Ahem, what to do? */
+ if (APR_BUCKET_IS_METADATA(bucket)) {
+ continue;
+ }
+
+ rv = apr_bucket_read(bucket, &data, &len, APR_BLOCK_READ);
+ if (rv != APR_SUCCESS) {
+ err = dav_new_error(r->pool, HTTP_BAD_REQUEST, 0,
+ "An error occurred while reading the "
+ "request body.");
+ /* This is a error which preempts us from reading to
+ * EOS. */
+ seen_eos = 1;
+ break;
+ }
+
+ if (err == NULL) {
+ /* write whatever we read, until we see an error */
+ err = (*resource->hooks->write_stream)(stream,
+ data, len);
+ }
}
+
+ apr_brigade_cleanup(brigade);
}
+ while (!seen_eos);
err2 = (*resource->hooks->close_stream)(stream,
err == NULL /* commit */);