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