struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
TAILQ_REMOVE(&evcon->requests, req, next);
+ if (req->on_complete_cb != NULL) {
+ req->on_complete_cb(req, req->on_complete_cb_arg);
+ }
+
need_close =
(REQ_VERSION_BEFORE(req, 1, 1) &&
!evhttp_is_connection_keepalive(req->input_headers))||
req->error_cb = cb;
}
+void
+evhttp_request_set_on_complete_cb(struct evhttp_request *req,
+ void (*cb)(struct evhttp_request *, void *), void *arg)
+{
+ req->on_complete_cb = cb;
+ req->on_complete_cb_arg = arg;
+}
+
/*
* Allows for inspection of the request URI
*/
void evhttp_request_set_error_cb(struct evhttp_request *,
void (*)(enum evhttp_request_error, void *));
+/**
+ * Set a on request complete callback.
+ *
+ * Receive a callback on request completion. This callback is triggered once
+ * the request is complete and all resources associated with the request will
+ * be released.
+ */
+void evhttp_request_set_on_complete_cb(struct evhttp_request *,
+ void (*)(struct evhttp_request *, void *), void *);
+
/** Frees the request object and removes associated events. */
void evhttp_request_free(struct evhttp_request *req);
static void http_large_delay_cb(struct evhttp_request *req, void *arg);
static void http_badreq_cb(struct evhttp_request *req, void *arg);
static void http_dispatcher_cb(struct evhttp_request *req, void *arg);
+static void http_on_complete_cb(struct evhttp_request *req, void *arg);
static int
http_bind(struct evhttp *myhttp, ev_uint16_t *pport, int ipv6)
evhttp_set_cb(myhttp, "/delay", http_delay_cb, base);
evhttp_set_cb(myhttp, "/largedelay", http_large_delay_cb, base);
evhttp_set_cb(myhttp, "/badrequest", http_badreq_cb, base);
+ evhttp_set_cb(myhttp, "/oncomplete", http_on_complete_cb, base);
evhttp_set_cb(myhttp, "/", http_dispatcher_cb, base);
return (myhttp);
}
;
}
+
static void
http_delay_reply(evutil_socket_t fd, short what, void *arg)
{
;
}
+static void
+http_sent_cb(struct evhttp_request *req, void *arg)
+{
+ unsigned int val = (unsigned int)arg;
+
+ if (val != 0xDEADBEEF) {
+ fprintf(stdout, "FAILED on_complete_cb argument\n");
+ exit(1);
+ }
+
+ event_debug(("%s: called\n", __func__));
+
+ ++test_ok;
+}
+
+static void
+http_on_complete_cb(struct evhttp_request *req, void *arg)
+{
+ struct evbuffer *evb = evbuffer_new();
+
+ evhttp_request_set_on_complete_cb(req, http_sent_cb, (void *)0xDEADBEEF);
+
+ event_debug(("%s: called\n", __func__));
+ evbuffer_add_printf(evb, BASIC_REQUEST_BODY);
+
+ /* allow sending of an empty reply */
+ evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb);
+
+ evbuffer_free(evb);
+
+ ++test_ok;
+}
+
+static void
+http_on_complete_test(void *arg)
+{
+ struct basic_test_data *data = arg;
+ struct bufferevent *bev;
+ evutil_socket_t fd;
+ const char *http_request;
+ ev_uint16_t port = 0;
+
+ test_ok = 0;
+
+ http = http_setup(&port, data->base, 0);
+
+ fd = http_connect("127.0.0.1", port);
+
+ /* Stupid thing to send a request */
+ bev = bufferevent_socket_new(data->base, fd, 0);
+ bufferevent_setcb(bev, http_readcb, http_writecb,
+ http_errorcb, data->base);
+
+ http_request =
+ "DELETE /oncomplete HTTP/1.1\r\n"
+ "Host: somehost\r\n"
+ "Connection: close\r\n"
+ "\r\n";
+
+ bufferevent_write(bev, http_request, strlen(http_request));
+
+ event_base_dispatch(data->base);
+
+ bufferevent_free(bev);
+ evutil_closesocket(fd);
+
+ evhttp_free(http);
+
+ tt_int_op(test_ok, ==, 4);
+ end:
+ ;
+}
+
static void
http_allowed_methods_eventcb(struct bufferevent *bev, short what, void *arg)
{
HTTP(incomplete),
HTTP(incomplete_timeout),
HTTP(terminate_chunked),
+ HTTP(on_complete),
HTTP(highport),
HTTP(dispatcher),