mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-16 07:45:23 -04:00
many changes for fixing a small bug: post requests would not send the post
data. I took the opportunity to reorganize a bit. svn:r201
This commit is contained in:
parent
7b78c82823
commit
896bf3a260
4
buffer.c
4
buffer.c
@ -117,8 +117,10 @@ evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf)
|
||||
}
|
||||
|
||||
res = evbuffer_add(outbuf, inbuf->buffer, inbuf->off);
|
||||
if (res == 0)
|
||||
if (res == 0) {
|
||||
/* We drain the input buffer on success */
|
||||
evbuffer_drain(inbuf, inbuf->off);
|
||||
}
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
34
event.h
34
event.h
@ -317,7 +317,13 @@ int evtag_unmarshal_timeval(struct evbuffer *evbuf, u_int8_t need_tag,
|
||||
struct timeval *ptv);
|
||||
|
||||
/*
|
||||
* Basic support for HTTP serving
|
||||
* Basic support for HTTP serving.
|
||||
*
|
||||
* As libevent is a library for dealing with event notification and most
|
||||
* interesting applications are networked today, I have often found the
|
||||
* need to write HTTP code. The following prototypes and definitions provide
|
||||
* an application with a minimal interface for making HTTP requests and for
|
||||
* creating a very simple HTTP server.
|
||||
*/
|
||||
|
||||
/* Response codes */
|
||||
@ -332,6 +338,10 @@ struct evhttp_request;
|
||||
/* Start an HTTP server on the specified address and port */
|
||||
struct evhttp *evhttp_start(const char *address, u_short port);
|
||||
|
||||
/*
|
||||
* Free the previously create HTTP server. Works only if not requests are
|
||||
* currently being served.
|
||||
*/
|
||||
void evhttp_free(struct evhttp* http);
|
||||
|
||||
/* Set a callback for a specified URI */
|
||||
@ -348,12 +358,32 @@ void evhttp_send_reply(struct evhttp_request *, int, const char *,
|
||||
|
||||
/* Interfaces for making requests */
|
||||
enum evhttp_cmd_type { EVHTTP_REQ_GET, EVHTTP_REQ_POST, EVHTTP_REQ_HEAD };
|
||||
enum evhttp_request_kind { EVHTTP_REQUEST, EVHTTP_RESPONSE };
|
||||
|
||||
struct evhttp_request *evhttp_request_new(
|
||||
void (*cb)(struct evhttp_request *, void *), void *arg);
|
||||
void evhttp_request_free(struct evhttp_request *req);
|
||||
|
||||
/* Interfaces for dealing with HTTP headers */
|
||||
|
||||
/*
|
||||
* Key-Value pairs. Can be used for HTTP headers but also for
|
||||
* query argument parsing.
|
||||
*/
|
||||
struct evkeyval {
|
||||
TAILQ_ENTRY(evkeyval) next;
|
||||
|
||||
char *key;
|
||||
char *value;
|
||||
};
|
||||
|
||||
TAILQ_HEAD(evkeyvalq, evkeyval);
|
||||
|
||||
char *evhttp_find_header(struct evkeyvalq *, const char *);
|
||||
void evhttp_remove_header(struct evkeyvalq *, const char *);
|
||||
int evhttp_add_header(struct evkeyvalq *, const char *, const char *);
|
||||
void evhttp_clear_headers(struct evkeyvalq *);
|
||||
|
||||
void evhttp_parse_query(const char *uri, struct evkeyvalq *);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
65
http.c
65
http.c
@ -177,15 +177,12 @@ evhttp_write_buffer(struct evhttp_request *req, struct evbuffer *buffer,
|
||||
event_add(&req->ev, &tv);
|
||||
}
|
||||
|
||||
void
|
||||
evhttp_make_header(struct evbuffer *buf, struct evhttp_request *req)
|
||||
static void
|
||||
evhttp_make_header_request(struct evbuffer *buf, struct evhttp_request *req)
|
||||
{
|
||||
char line[1024];
|
||||
struct evkeyval *header;
|
||||
static char line[1024];
|
||||
const char *method;
|
||||
|
||||
/* First we make a few tiny modifications */
|
||||
if (req->kind == EVHTTP_REQUEST) {
|
||||
evhttp_remove_header(req->output_headers, "Accept-Encoding");
|
||||
evhttp_remove_header(req->output_headers, "Proxy-Connection");
|
||||
evhttp_remove_header(req->output_headers, "Connection");
|
||||
@ -200,28 +197,46 @@ evhttp_make_header(struct evbuffer *buf, struct evhttp_request *req)
|
||||
|
||||
/* Add the content length on a post request if missing */
|
||||
if (req->type == EVHTTP_REQ_POST &&
|
||||
evhttp_find_header(req->output_headers,
|
||||
"Content-Length") == NULL) {
|
||||
evhttp_find_header(req->output_headers, "Content-Length") == NULL){
|
||||
char size[12];
|
||||
snprintf(size, sizeof(size), "%d",
|
||||
EVBUFFER_LENGTH(req->buffer));
|
||||
evhttp_add_header(req->output_headers,
|
||||
"Content-Length", size);
|
||||
evhttp_add_header(req->output_headers, "Content-Length", size);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
static void
|
||||
evhttp_make_header_response(struct evbuffer *buf, struct evhttp_request *req)
|
||||
{
|
||||
static char line[1024];
|
||||
snprintf(line, sizeof(line), "HTTP/%d.%d %d %s\r\n",
|
||||
req->major, req->minor, req->response_code,
|
||||
req->response_code_line);
|
||||
evbuffer_add(buf, line, strlen(line));
|
||||
|
||||
/* Potentially add headers */
|
||||
if (evhttp_find_header(req->output_headers,
|
||||
"Content-Type") == NULL) {
|
||||
if (evhttp_find_header(req->output_headers, "Content-Type") == NULL) {
|
||||
evhttp_add_header(req->output_headers,
|
||||
"Content-Type", "text/html; charset=ISO-8859-1");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
evhttp_make_header(struct evbuffer *buf, struct evhttp_request *req)
|
||||
{
|
||||
static char line[1024];
|
||||
struct evkeyval *header;
|
||||
|
||||
/*
|
||||
* Depending if this is a HTTP request or response, we might need to
|
||||
* add some new headers or remove existing headers.
|
||||
*/
|
||||
if (req->kind == EVHTTP_REQUEST) {
|
||||
evhttp_make_header_request(buf, req);
|
||||
} else {
|
||||
evhttp_make_header_response(buf, req);
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(header, req->output_headers, next) {
|
||||
snprintf(line, sizeof(line), "%s: %s\r\n",
|
||||
header->key, header->value);
|
||||
@ -230,7 +245,7 @@ evhttp_make_header(struct evbuffer *buf, struct evhttp_request *req)
|
||||
evbuffer_add(buf, "\r\n", 2);
|
||||
|
||||
if (req->kind == EVHTTP_REQUEST) {
|
||||
int len = req->buffer->off;
|
||||
int len = EVBUFFER_LENGTH(req->buffer);
|
||||
|
||||
/* Add the POST data */
|
||||
if (len > 0)
|
||||
@ -815,8 +830,12 @@ evhttp_read_header(int fd, short what, void *arg)
|
||||
|
||||
/*
|
||||
* Creates a TCP connection to the specified port and executes a callback
|
||||
* when finished. Failure of sucess is indicate by the passed connection
|
||||
* when finished. Failure or sucess is indicate by the passed connection
|
||||
* object.
|
||||
*
|
||||
* Although this interface accepts a hostname, it is intended to take
|
||||
* only numeric hostnames so that non-blocking DNS resolution can
|
||||
* happen elsewhere.
|
||||
*/
|
||||
|
||||
struct evhttp_connection *
|
||||
@ -865,12 +884,14 @@ evhttp_connect(const char *address, unsigned short port,
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't know if we just want to pass a file descriptor or the evcon object.
|
||||
* In theory we might use this to queue requests on the connection object.
|
||||
* Starts an HTTP request on the provided evhttp_connection object.
|
||||
*
|
||||
* In theory we might use this to queue requests on the connection
|
||||
* object.
|
||||
*/
|
||||
|
||||
int
|
||||
evhttp_start_request(struct evhttp_connection *evcon,
|
||||
evhttp_make_request(struct evhttp_connection *evcon,
|
||||
struct evhttp_request *req,
|
||||
enum evhttp_cmd_type type, const char *uri)
|
||||
{
|
||||
@ -897,6 +918,13 @@ evhttp_start_request(struct evhttp_connection *evcon,
|
||||
/* Create the header from the store arguments */
|
||||
evhttp_make_header(evbuf, req);
|
||||
|
||||
/*
|
||||
* If this was a post request or for other reasons we need to append
|
||||
* our post data to the request.
|
||||
*/
|
||||
evbuffer_add_buffer(evbuf, req->buffer);
|
||||
|
||||
|
||||
/* Schedule the write */
|
||||
req->save_cb = req->cb;
|
||||
req->save_cbarg = req->cb_arg;
|
||||
@ -1022,6 +1050,7 @@ evhttp_parse_query(const char *uri, struct evkeyvalq *headers)
|
||||
|
||||
TAILQ_INIT(headers);
|
||||
|
||||
/* No arguments - we are done */
|
||||
if (strchr(uri, '?') == NULL)
|
||||
return;
|
||||
|
||||
|
@ -82,6 +82,7 @@ http_setup(short *pport)
|
||||
if (port == -1)
|
||||
event_errx(1, "Could not start web server");
|
||||
|
||||
/* Register a callback for certain types of requests */
|
||||
evhttp_set_cb(myhttp, "/test", http_basic_cb, NULL);
|
||||
|
||||
*pport = port;
|
||||
@ -264,7 +265,7 @@ http_connectcb(struct evhttp_connection *evcon, void *arg)
|
||||
/* Add the information that we care about */
|
||||
evhttp_add_header(req->output_headers, "Host", "somehost");
|
||||
|
||||
if (evhttp_start_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) {
|
||||
if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) {
|
||||
fprintf(stdout, "FAILED\n");
|
||||
exit(1);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user