Using PUT without a content-length

Julien Reichel Julien.Reichel at spinetix.com
Fri Jul 25 05:34:09 EDT 2008


Hi,

So looking more deeply at the code and at the HTTP specification, it
looks like closing the connection is not a good idea :-)

So here is a patch for supporting variable length request body using the
Transfer-Encoding : chunk mode

I was not so sure for the correct handling of the status.

Let me know if you think this patch is appropriate.

Julien
 
PS: patch also copied inline in case the mailing list cuts attachments:

Index: ne_request.c
===================================================================
--- ne_request.c	(reference)
+++ ne_request.c	(patch)
@@ -340,12 +340,18 @@
 {
     ne_session *const sess = req->session;
     char buffer[NE_BUFSIZ];
+    char chunk_buffer[128];
+    int chunk_idx=0;
+    int ret = 0;
     ssize_t bytes;
 
     NE_DEBUG(NE_DBG_HTTP, "Sending request body:\n");
 
     req->session->status.sr.progress = 0;
-    req->session->status.sr.total = req->body_length;
+    if ( req->body_length > 0 )
+        req->session->status.sr.total = req->body_length;
+    else
+        req->session->status.sr.total = 0;
     notify_status(sess, ne_status_sending);
     
     /* tell the source to start again from the beginning. */
@@ -355,7 +361,17 @@
     }
     
     while ((bytes = req->body_cb(req->body_ud, buffer, sizeof buffer))
> 0) {
-	int ret = ne_sock_fullwrite(sess->socket, buffer, bytes);
+        if ( req->body_length < 0 ) {
+            // Chunked mode
+            if ( chunk_idx==0 )
+                snprintf(chunk_buffer, 128, "%x\r\n", (unsigned)bytes);
+            else
+                snprintf(chunk_buffer, 128, "\r\n%x\r\n",
(unsigned)bytes);
+            ret = ne_sock_fullwrite(sess->socket, chunk_buffer,
strlen(chunk_buffer));
+            chunk_idx++;
+        }
+        if (ret >= 0)
+	        ret = ne_sock_fullwrite(sess->socket, buffer, bytes);
         if (ret < 0) {
             int aret = aborted(req, _("Could not send request body"),
ret);
             return RETRY_RET(retry, ret, aret);
@@ -369,6 +385,15 @@
         req->session->status.sr.progress += bytes;
         notify_status(sess, ne_status_sending);
     }
+    if ( req->body_length < 0 ) {
+        // Chunked mode
+        snprintf(chunk_buffer, 128, "\r\n0\r\n\r\n");
+        ret = ne_sock_fullwrite(sess->socket, chunk_buffer,
strlen(chunk_buffer));
+        if (ret < 0) {
+            int aret = aborted(req, _("Could not send last-chunk
info"), ret);
+            return RETRY_RET(retry, ret, aret);
+        }
+    }
 
     if (bytes == 0) {
         return NE_OK;
@@ -466,7 +491,10 @@
 static void set_body_length(ne_request *req, ne_off_t length)
 {
     req->body_length = length;
-    ne_print_request_header(req, "Content-Length", "%" FMT_NE_OFF_T,
length);
+    if ( length > 0 )
+        ne_print_request_header(req, "Content-Length", "%"
FMT_NE_OFF_T, length);
+    else if ( length < 0 )
+        ne_print_request_header(req, "Transfer-Encoding", "chunked");
 }
 
 void ne_set_request_body_buffer(ne_request *req, const char *buffer,
@@ -937,7 +965,7 @@
 	return RETRY_RET(retry, sret, aret);
     }
     
-    if (!req->flags[NE_REQFLAG_EXPECT100] && req->body_length > 0) {
+    if (!req->flags[NE_REQFLAG_EXPECT100] && req->body_length != 0) {
 	/* Send request body, if not using 100-continue. */
 	ret = send_request_body(req, retry);
 	if (ret) {
@@ -957,7 +985,7 @@
 	if ((ret = discard_headers(req)) != NE_OK) break;
 
 	if (req->flags[NE_REQFLAG_EXPECT100] && (status->code == 100)
-            && req->body_length > 0 && !sentbody) {
+            && req->body_length != 0 && !sentbody) {
 	    /* Send the body after receiving the first 100 Continue */
 	    if ((ret = send_request_body(req, 0)) != NE_OK) break;

 	    sentbody = 1;


> -----Original Message-----
> From: neon-bounces at lists.manyfish.co.uk 
> [mailto:neon-bounces at lists.manyfish.co.uk] On Behalf Of Julien Reichel
> Sent: 25 July 2008 09:54
> To: neon at lists.manyfish.co.uk
> Subject: Using PUT without a content-length
> 
> Hi,
> 
> Is there a way to do a PUT command in neon with an unknown 
> content length ?
> 
> I need to use the PUT command to put a variable length file 
> where the length is unknown in advance.
> 
> The function ne_set_request_body_provider() will not use the 
> put call-back is a size equal to 0 is set as argument.
> 
> Is there a chunked mode transfer for the request body ?
> 
> Is it possible to close the TCP connection at the end of the 
> request body of the PUT command ? (is that supported by 
> HTTP/WebDAV servers ?)
> 
> Thanks for the help
> 
> Julien
> 
> --------------------------------------------------------------
> ----------
> --
> 
> Julien Reichel, PhD
> Technology Architect, SpinetiX S.A.
> PSE-C, CH-1015, Lausanne, Switzerland
> 
> Tel:     +41 (0) 21 693 89 81
> Mail:   julien.reichel at spinetix.com
> Get Information : http://www.spinetix.com
> 
> --------------------------------------------------------------
> ----------
> --
> 
> _______________________________________________
> neon mailing list
> neon at lists.manyfish.co.uk
> http://lists.manyfish.co.uk/mailman/listinfo/neon
> 


More information about the neon mailing list