mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-17 08:17:42 -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);
|
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);
|
evbuffer_drain(inbuf, inbuf->off);
|
||||||
|
}
|
||||||
|
|
||||||
return (res);
|
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);
|
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 */
|
/* Response codes */
|
||||||
@ -332,6 +338,10 @@ struct evhttp_request;
|
|||||||
/* Start an HTTP server on the specified address and port */
|
/* Start an HTTP server on the specified address and port */
|
||||||
struct evhttp *evhttp_start(const char *address, u_short 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);
|
void evhttp_free(struct evhttp* http);
|
||||||
|
|
||||||
/* Set a callback for a specified URI */
|
/* 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 */
|
/* Interfaces for making requests */
|
||||||
enum evhttp_cmd_type { EVHTTP_REQ_GET, EVHTTP_REQ_POST, EVHTTP_REQ_HEAD };
|
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(
|
struct evhttp_request *evhttp_request_new(
|
||||||
void (*cb)(struct evhttp_request *, void *), void *arg);
|
void (*cb)(struct evhttp_request *, void *), void *arg);
|
||||||
void evhttp_request_free(struct evhttp_request *req);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#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);
|
event_add(&req->ev, &tv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
evhttp_make_header(struct evbuffer *buf, struct evhttp_request *req)
|
evhttp_make_header_request(struct evbuffer *buf, struct evhttp_request *req)
|
||||||
{
|
{
|
||||||
char line[1024];
|
static char line[1024];
|
||||||
struct evkeyval *header;
|
|
||||||
const char *method;
|
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, "Accept-Encoding");
|
||||||
evhttp_remove_header(req->output_headers, "Proxy-Connection");
|
evhttp_remove_header(req->output_headers, "Proxy-Connection");
|
||||||
evhttp_remove_header(req->output_headers, "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 */
|
/* Add the content length on a post request if missing */
|
||||||
if (req->type == EVHTTP_REQ_POST &&
|
if (req->type == EVHTTP_REQ_POST &&
|
||||||
evhttp_find_header(req->output_headers,
|
evhttp_find_header(req->output_headers, "Content-Length") == NULL){
|
||||||
"Content-Length") == NULL) {
|
|
||||||
char size[12];
|
char size[12];
|
||||||
snprintf(size, sizeof(size), "%d",
|
snprintf(size, sizeof(size), "%d",
|
||||||
EVBUFFER_LENGTH(req->buffer));
|
EVBUFFER_LENGTH(req->buffer));
|
||||||
evhttp_add_header(req->output_headers,
|
evhttp_add_header(req->output_headers, "Content-Length", size);
|
||||||
"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",
|
snprintf(line, sizeof(line), "HTTP/%d.%d %d %s\r\n",
|
||||||
req->major, req->minor, req->response_code,
|
req->major, req->minor, req->response_code,
|
||||||
req->response_code_line);
|
req->response_code_line);
|
||||||
evbuffer_add(buf, line, strlen(line));
|
evbuffer_add(buf, line, strlen(line));
|
||||||
|
|
||||||
/* Potentially add headers */
|
/* Potentially add headers */
|
||||||
if (evhttp_find_header(req->output_headers,
|
if (evhttp_find_header(req->output_headers, "Content-Type") == NULL) {
|
||||||
"Content-Type") == NULL) {
|
|
||||||
evhttp_add_header(req->output_headers,
|
evhttp_add_header(req->output_headers,
|
||||||
"Content-Type", "text/html; charset=ISO-8859-1");
|
"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) {
|
TAILQ_FOREACH(header, req->output_headers, next) {
|
||||||
snprintf(line, sizeof(line), "%s: %s\r\n",
|
snprintf(line, sizeof(line), "%s: %s\r\n",
|
||||||
header->key, header->value);
|
header->key, header->value);
|
||||||
@ -230,7 +245,7 @@ evhttp_make_header(struct evbuffer *buf, struct evhttp_request *req)
|
|||||||
evbuffer_add(buf, "\r\n", 2);
|
evbuffer_add(buf, "\r\n", 2);
|
||||||
|
|
||||||
if (req->kind == EVHTTP_REQUEST) {
|
if (req->kind == EVHTTP_REQUEST) {
|
||||||
int len = req->buffer->off;
|
int len = EVBUFFER_LENGTH(req->buffer);
|
||||||
|
|
||||||
/* Add the POST data */
|
/* Add the POST data */
|
||||||
if (len > 0)
|
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
|
* 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.
|
* 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 *
|
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.
|
* Starts an HTTP request on the provided evhttp_connection object.
|
||||||
* In theory we might use this to queue requests on the connection object.
|
*
|
||||||
|
* In theory we might use this to queue requests on the connection
|
||||||
|
* object.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
evhttp_start_request(struct evhttp_connection *evcon,
|
evhttp_make_request(struct evhttp_connection *evcon,
|
||||||
struct evhttp_request *req,
|
struct evhttp_request *req,
|
||||||
enum evhttp_cmd_type type, const char *uri)
|
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 */
|
/* Create the header from the store arguments */
|
||||||
evhttp_make_header(evbuf, req);
|
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 */
|
/* Schedule the write */
|
||||||
req->save_cb = req->cb;
|
req->save_cb = req->cb;
|
||||||
req->save_cbarg = req->cb_arg;
|
req->save_cbarg = req->cb_arg;
|
||||||
@ -1022,6 +1050,7 @@ evhttp_parse_query(const char *uri, struct evkeyvalq *headers)
|
|||||||
|
|
||||||
TAILQ_INIT(headers);
|
TAILQ_INIT(headers);
|
||||||
|
|
||||||
|
/* No arguments - we are done */
|
||||||
if (strchr(uri, '?') == NULL)
|
if (strchr(uri, '?') == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -82,6 +82,7 @@ http_setup(short *pport)
|
|||||||
if (port == -1)
|
if (port == -1)
|
||||||
event_errx(1, "Could not start web server");
|
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);
|
evhttp_set_cb(myhttp, "/test", http_basic_cb, NULL);
|
||||||
|
|
||||||
*pport = port;
|
*pport = port;
|
||||||
@ -264,7 +265,7 @@ http_connectcb(struct evhttp_connection *evcon, void *arg)
|
|||||||
/* Add the information that we care about */
|
/* Add the information that we care about */
|
||||||
evhttp_add_header(req->output_headers, "Host", "somehost");
|
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");
|
fprintf(stdout, "FAILED\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user