Skip to content

Commit

Permalink
Preliminary support for Continue expectation in evhttp.
Browse files Browse the repository at this point in the history
  • Loading branch information
chris-davis committed Nov 30, 2010
1 parent a12839b commit fa9305f
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 1 deletion.
55 changes: 55 additions & 0 deletions http.c
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,29 @@ evhttp_write_buffer(struct evhttp_connection *evcon,
evcon);
}

static void
evhttp_send_continue_done(struct evhttp_connection *evcon, void *arg)
{
bufferevent_disable(evcon->bufev, EV_WRITE);
}

static void
evhttp_send_continue(struct evhttp_connection *evcon,
struct evhttp_request *req)
{
bufferevent_enable(evcon->bufev, EV_WRITE);
evbuffer_add_printf(bufferevent_get_output(evcon->bufev),
"HTTP/%d.%d 100 Continue\r\n\r\n",
req->major, req->minor);
evcon->cb = evhttp_send_continue_done;
evcon->cb_arg = NULL;
bufferevent_setcb(evcon->bufev,
evhttp_read_cb,
evhttp_write_cb,
evhttp_error_cb,
evcon);
}

/** Helper: returns true iff evconn is in any connected state. */
static int
evhttp_connected(struct evhttp_connection *evcon)
Expand Down Expand Up @@ -574,6 +597,9 @@ evhttp_make_header(struct evhttp_connection *evcon, struct evhttp_request *req)
* For a request, we add the POST data, for a reply, this
* is the regular data.
*/
/* XXX We might want to support waiting (a limited amount of
time) for a continue status line from the server before
sending POST/PUT message bodies. */
evbuffer_add_buffer(output, req->output_buffer);
}
}
Expand Down Expand Up @@ -1804,6 +1830,30 @@ evhttp_get_body(struct evhttp_connection *evcon, struct evhttp_request *req)
return;
}
}

/* Should we send a 100 Continue status line? */
if (req->kind == EVHTTP_REQUEST && REQ_VERSION_ATLEAST(req, 1, 1)) {
const char *expect;

expect = evhttp_find_header(req->input_headers, "Expect");
if (expect) {
if (!evutil_ascii_strcasecmp(expect, "100-continue")) {
/* XXX It would be nice to do some sanity
checking here. Does the resource exist?
Should the resource accept post requests? If
no, we should respond with an error. For
now, just optimistically tell the client to
send their message body. */
if (!evbuffer_get_length(bufferevent_get_input(evcon->bufev)))
evhttp_send_continue(evcon, req);
} else {
evhttp_send_error(req, HTTP_EXPECTATIONFAILED,
NULL);
return;
}
}
}

evhttp_read_body(evcon, req);
/* note the request may have been freed in evhttp_read_body */
}
Expand Down Expand Up @@ -1861,6 +1911,11 @@ evhttp_read_header(struct evhttp_connection *evcon,
break;

case EVHTTP_RESPONSE:
/* Start over if we got a 100 Continue response. */
if (req->response_code == 100) {
evhttp_start_read(evcon);
return;
}
if (!evhttp_response_needs_body(req)) {
event_debug(("%s: skipping body for code %d\n",
__func__, req->response_code));
Expand Down
1 change: 1 addition & 0 deletions include/event2/http.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ struct event_base;
#define HTTP_BADREQUEST 400 /**< invalid http request was made */
#define HTTP_NOTFOUND 404 /**< could not find content for uri */
#define HTTP_BADMETHOD 405 /**< method not allowed for this uri */
#define HTTP_EXPECTATIONFAILED 417 /**< we can't handle this expectation */
#define HTTP_INTERNAL 500 /**< internal error */
#define HTTP_NOTIMPLEMENTED 501 /**< not implemented */
#define HTTP_SERVUNAVAIL 503 /**< the server is not available */
Expand Down
23 changes: 22 additions & 1 deletion test/regress_http.c
Original file line number Diff line number Diff line change
Expand Up @@ -1503,10 +1503,31 @@ http_post_test(void *arg)

event_base_dispatch(data->base);

tt_int_op(test_ok, ==, 1);

test_ok = 0;

req = evhttp_request_new(http_postrequest_done, data->base);
tt_assert(req);

/* Now try with 100-continue. */

/* Add the information that we care about */
evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
evhttp_add_header(evhttp_request_get_output_headers(req), "Expect", "100-continue");
evbuffer_add_printf(evhttp_request_get_output_buffer(req), POST_DATA);

if (evhttp_make_request(evcon, req, EVHTTP_REQ_POST, "/postit") == -1) {
tt_abort_msg("Couldn't make request");
}

event_base_dispatch(data->base);

tt_int_op(test_ok, ==, 1);

evhttp_connection_free(evcon);
evhttp_free(http);

tt_int_op(test_ok, ==, 1);
end:
;
}
Expand Down

0 comments on commit fa9305f

Please sign in to comment.