mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-09 20:41:27 -04:00
make a simple test for HTTP POST requests
svn:r205
This commit is contained in:
parent
60192b4625
commit
38b33048eb
30
event.3
30
event.3
@ -75,7 +75,9 @@
|
|||||||
.Nm evbuffer_write ,
|
.Nm evbuffer_write ,
|
||||||
.Nm evbuffer_read ,
|
.Nm evbuffer_read ,
|
||||||
.Nm evbuffer_find ,
|
.Nm evbuffer_find ,
|
||||||
.Nm evbuffer_readline
|
.Nm evbuffer_readline ,
|
||||||
|
.Nm evhttp_start ,
|
||||||
|
.Nm evhttp_free
|
||||||
.Nd execute a function when a specific event occurs
|
.Nd execute a function when a specific event occurs
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Fd #include <sys/time.h>
|
.Fd #include <sys/time.h>
|
||||||
@ -172,6 +174,10 @@
|
|||||||
.Fn "evbuffer_find" "struct evbuffer *buf" "u_char *data" "size_t size"
|
.Fn "evbuffer_find" "struct evbuffer *buf" "u_char *data" "size_t size"
|
||||||
.Ft "char *"
|
.Ft "char *"
|
||||||
.Fn "evbuffer_readline" "struct evbuffer *buf"
|
.Fn "evbuffer_readline" "struct evbuffer *buf"
|
||||||
|
.Ft "struct evhttp *"
|
||||||
|
.Fn "evhttp_start" "const char *address" "u_short port"
|
||||||
|
.Ft "void"
|
||||||
|
.Fn "evhttp_free" "struct evhttp* http"
|
||||||
.Ft int
|
.Ft int
|
||||||
.Fa (*event_sigcb)(void) ;
|
.Fa (*event_sigcb)(void) ;
|
||||||
.Ft int
|
.Ft int
|
||||||
@ -513,6 +519,28 @@ Both functions return the amount of data written or read.
|
|||||||
.Pp
|
.Pp
|
||||||
If multiple bases are in use, bufferevent_base_set() must be called before
|
If multiple bases are in use, bufferevent_base_set() must be called before
|
||||||
enabling the bufferevent for the first time.
|
enabling the bufferevent for the first time.
|
||||||
|
.Sh NON-BLOCKING HTTP SUPPORT
|
||||||
|
.Nm libevent
|
||||||
|
provides a very thin HTTP layer that can be used both to host an HTTP
|
||||||
|
server and also to make HTTP requests.
|
||||||
|
An HTTP server can be created by calling
|
||||||
|
.Fn evhttp_start .
|
||||||
|
When the HTTP server is no longer used, it can be freed via
|
||||||
|
.Fn evhttp_free .
|
||||||
|
.Pp
|
||||||
|
To be notified of HTTP requests, a user needs to register callbacks with the
|
||||||
|
HTTP server.
|
||||||
|
This can be done by calling
|
||||||
|
.Fn evhttp_set_cb .
|
||||||
|
The second argument is the URI for which a callback is being registered.
|
||||||
|
The corresponding callback will receive an
|
||||||
|
.Va struct evhttp_request
|
||||||
|
object that contains all information about the request.
|
||||||
|
.Pp
|
||||||
|
This section does not document all the possible function calls, please
|
||||||
|
check
|
||||||
|
.Va event.h
|
||||||
|
for the public interfaces.
|
||||||
.Sh RETURN VALUES
|
.Sh RETURN VALUES
|
||||||
Upon successful completion
|
Upon successful completion
|
||||||
.Fn event_add
|
.Fn event_add
|
||||||
|
9
event.h
9
event.h
@ -353,7 +353,7 @@ struct evhttp_request;
|
|||||||
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
|
* Free the previously create HTTP server. Works only if no requests are
|
||||||
* currently being served.
|
* currently being served.
|
||||||
*/
|
*/
|
||||||
void evhttp_free(struct evhttp* http);
|
void evhttp_free(struct evhttp* http);
|
||||||
@ -376,15 +376,18 @@ enum evhttp_cmd_type { EVHTTP_REQ_GET, EVHTTP_REQ_POST, EVHTTP_REQ_HEAD };
|
|||||||
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);
|
||||||
|
const char *evhttp_request_uri(struct evhttp_request *req);
|
||||||
|
|
||||||
/* Interfaces for dealing with HTTP headers */
|
/* Interfaces for dealing with HTTP headers */
|
||||||
|
|
||||||
char *evhttp_find_header(struct evkeyvalq *, const char *);
|
const char *evhttp_find_header(struct evkeyvalq *, const char *);
|
||||||
void evhttp_remove_header(struct evkeyvalq *, const char *);
|
int evhttp_remove_header(struct evkeyvalq *, const char *);
|
||||||
int evhttp_add_header(struct evkeyvalq *, const char *, const char *);
|
int evhttp_add_header(struct evkeyvalq *, const char *, const char *);
|
||||||
void evhttp_clear_headers(struct evkeyvalq *);
|
void evhttp_clear_headers(struct evkeyvalq *);
|
||||||
|
|
||||||
|
/* Miscellaneous utility functions */
|
||||||
void evhttp_parse_query(const char *uri, struct evkeyvalq *);
|
void evhttp_parse_query(const char *uri, struct evkeyvalq *);
|
||||||
|
char *evhttp_htmlescape(const char *html);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
90
http.c
90
http.c
@ -1,7 +1,28 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002, 2003, 2005 Niels Provos <provos@citi.umich.edu>
|
* Copyright (c) 2002-2006 Niels Provos <provos@citi.umich.edu>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
@ -149,7 +170,8 @@ evhttp_form_response(struct evbuffer *buf, struct evhttp_request *req)
|
|||||||
evhttp_make_header(buf, req);
|
evhttp_make_header(buf, req);
|
||||||
|
|
||||||
/* Append the response buffer */
|
/* Append the response buffer */
|
||||||
evbuffer_add(buf, req->buffer->buffer, req->buffer->off);
|
evbuffer_add(buf,
|
||||||
|
EVBUFFER_DATA(req->buffer), EVBUFFER_LENGTH(req->buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -177,6 +199,9 @@ evhttp_write_buffer(struct evhttp_request *req, struct evbuffer *buffer,
|
|||||||
event_add(&req->ev, &tv);
|
event_add(&req->ev, &tv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create the headers need for an HTTP reply
|
||||||
|
*/
|
||||||
static void
|
static void
|
||||||
evhttp_make_header_request(struct evbuffer *buf, struct evhttp_request *req)
|
evhttp_make_header_request(struct evbuffer *buf, struct evhttp_request *req)
|
||||||
{
|
{
|
||||||
@ -205,6 +230,9 @@ evhttp_make_header_request(struct evbuffer *buf, struct evhttp_request *req)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create the headers needed for an HTTP reply
|
||||||
|
*/
|
||||||
static void
|
static void
|
||||||
evhttp_make_header_response(struct evbuffer *buf, struct evhttp_request *req)
|
evhttp_make_header_response(struct evbuffer *buf, struct evhttp_request *req)
|
||||||
{
|
{
|
||||||
@ -249,7 +277,7 @@ evhttp_make_header(struct evbuffer *buf, struct evhttp_request *req)
|
|||||||
|
|
||||||
/* Add the POST data */
|
/* Add the POST data */
|
||||||
if (len > 0)
|
if (len > 0)
|
||||||
evbuffer_add(buf, req->buffer->buffer, len);
|
evbuffer_add(buf, EVBUFFER_DATA(req->buffer), len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,7 +367,7 @@ evhttp_write(int fd, short what, void *arg)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req->buffer->off != 0) {
|
if (EVBUFFER_LENGTH(req->buffer) != 0) {
|
||||||
timerclear(&tv);
|
timerclear(&tv);
|
||||||
tv.tv_sec = HTTP_WRITE_TIMEOUT;
|
tv.tv_sec = HTTP_WRITE_TIMEOUT;
|
||||||
event_add(&req->ev, &tv);
|
event_add(&req->ev, &tv);
|
||||||
@ -580,7 +608,7 @@ evhttp_parse_request_line(struct evhttp_request *req, char *line)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
const char *
|
||||||
evhttp_find_header(struct evkeyvalq *headers, const char *key)
|
evhttp_find_header(struct evkeyvalq *headers, const char *key)
|
||||||
{
|
{
|
||||||
struct evkeyval *header;
|
struct evkeyval *header;
|
||||||
@ -608,7 +636,12 @@ evhttp_clear_headers(struct evkeyvalq *headers)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
/*
|
||||||
|
* Returns 0, if the header was successfully removed.
|
||||||
|
* Returns -1, if the header could not be found.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
evhttp_remove_header(struct evkeyvalq *headers, const char *key)
|
evhttp_remove_header(struct evkeyvalq *headers, const char *key)
|
||||||
{
|
{
|
||||||
struct evkeyval *header;
|
struct evkeyval *header;
|
||||||
@ -619,13 +652,15 @@ evhttp_remove_header(struct evkeyvalq *headers, const char *key)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (header == NULL)
|
if (header == NULL)
|
||||||
return;
|
return (-1);
|
||||||
|
|
||||||
/* Free and remove the header that we found */
|
/* Free and remove the header that we found */
|
||||||
TAILQ_REMOVE(headers, header, next);
|
TAILQ_REMOVE(headers, header, next);
|
||||||
free(header->key);
|
free(header->key);
|
||||||
free(header->value);
|
free(header->value);
|
||||||
free(header);
|
free(header);
|
||||||
|
|
||||||
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -639,10 +674,13 @@ evhttp_add_header(struct evkeyvalq *headers, const char *key, const char *value)
|
|||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
if ((header->key = strdup(key)) == NULL) {
|
if ((header->key = strdup(key)) == NULL) {
|
||||||
|
free(header);
|
||||||
event_warn("%s: strdup", __func__);
|
event_warn("%s: strdup", __func__);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
if ((header->value = strdup(value)) == NULL) {
|
if ((header->value = strdup(value)) == NULL) {
|
||||||
|
free(header->key);
|
||||||
|
free(header);
|
||||||
event_warn("%s: strdup", __func__);
|
event_warn("%s: strdup", __func__);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
@ -672,7 +710,7 @@ evhttp_parse_lines(struct evhttp_request *req, struct evbuffer* buffer)
|
|||||||
while ((endp = evbuffer_find(buffer, "\r\n", 2)) != NULL) {
|
while ((endp = evbuffer_find(buffer, "\r\n", 2)) != NULL) {
|
||||||
char *skey, *svalue;
|
char *skey, *svalue;
|
||||||
|
|
||||||
if (strncmp(buffer->buffer, "\r\n", 2) == 0) {
|
if (strncmp(EVBUFFER_DATA(buffer), "\r\n", 2) == 0) {
|
||||||
evbuffer_drain(buffer, 2);
|
evbuffer_drain(buffer, 2);
|
||||||
/* Last header - Done */
|
/* Last header - Done */
|
||||||
done = 1;
|
done = 1;
|
||||||
@ -682,17 +720,17 @@ evhttp_parse_lines(struct evhttp_request *req, struct evbuffer* buffer)
|
|||||||
*endp = '\0';
|
*endp = '\0';
|
||||||
endp += 2;
|
endp += 2;
|
||||||
|
|
||||||
event_debug(("%s: Got: %s\n", __func__, buffer->buffer));
|
event_debug(("%s: Got: %s\n", __func__, EVBUFFER_DATA(buffer)));
|
||||||
|
|
||||||
/* Processing of header lines */
|
/* Processing of header lines */
|
||||||
if (req->got_firstline == 0) {
|
if (req->got_firstline == 0) {
|
||||||
switch (req->kind) {
|
switch (req->kind) {
|
||||||
case EVHTTP_REQUEST:
|
case EVHTTP_REQUEST:
|
||||||
if (evhttp_parse_request_line(req, buffer->buffer) == -1)
|
if (evhttp_parse_request_line(req, EVBUFFER_DATA(buffer)) == -1)
|
||||||
return (-1);
|
return (-1);
|
||||||
break;
|
break;
|
||||||
case EVHTTP_RESPONSE:
|
case EVHTTP_RESPONSE:
|
||||||
if (evhttp_parse_response_line(req, buffer->buffer) == -1)
|
if (evhttp_parse_response_line(req, EVBUFFER_DATA(buffer)) == -1)
|
||||||
return (-1);
|
return (-1);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -701,7 +739,7 @@ evhttp_parse_lines(struct evhttp_request *req, struct evbuffer* buffer)
|
|||||||
req->got_firstline = 1;
|
req->got_firstline = 1;
|
||||||
} else {
|
} else {
|
||||||
/* Regular header */
|
/* Regular header */
|
||||||
svalue = buffer->buffer;
|
svalue = EVBUFFER_DATA(buffer);
|
||||||
skey = strsep(&svalue, ":");
|
skey = strsep(&svalue, ":");
|
||||||
if (svalue == NULL)
|
if (svalue == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
@ -713,7 +751,7 @@ evhttp_parse_lines(struct evhttp_request *req, struct evbuffer* buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Move the uncompleted headers forward */
|
/* Move the uncompleted headers forward */
|
||||||
evbuffer_drain(buffer, endp - buffer->buffer);
|
evbuffer_drain(buffer, endp - EVBUFFER_DATA(buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (done);
|
return (done);
|
||||||
@ -723,8 +761,8 @@ void
|
|||||||
evhttp_get_body(struct evhttp_request *req)
|
evhttp_get_body(struct evhttp_request *req)
|
||||||
{
|
{
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
char *content_length;
|
const char *content_length;
|
||||||
char *connection;
|
const char *connection;
|
||||||
struct evkeyvalq *headers = req->input_headers;
|
struct evkeyvalq *headers = req->input_headers;
|
||||||
|
|
||||||
/* If this is a request without a body, then we are done */
|
/* If this is a request without a body, then we are done */
|
||||||
@ -752,10 +790,10 @@ evhttp_get_body(struct evhttp_request *req)
|
|||||||
req->ntoread = atoi(content_length);
|
req->ntoread = atoi(content_length);
|
||||||
|
|
||||||
event_debug(("%s: bytes to read: %d (in buffer %d)\n",
|
event_debug(("%s: bytes to read: %d (in buffer %d)\n",
|
||||||
__func__, req->ntoread, req->buffer->off));
|
__func__, req->ntoread, EVBUFFER_LENGTH(req->buffer)));
|
||||||
|
|
||||||
if (req->ntoread > 0)
|
if (req->ntoread > 0)
|
||||||
req->ntoread -= req->buffer->off;
|
req->ntoread -= EVBUFFER_LENGTH(req->buffer);
|
||||||
|
|
||||||
if (req->ntoread == 0) {
|
if (req->ntoread == 0) {
|
||||||
(*req->cb)(req, req->cb_arg);
|
(*req->cb)(req, req->cb_arg);
|
||||||
@ -918,13 +956,6 @@ evhttp_make_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;
|
||||||
@ -1307,6 +1338,17 @@ evhttp_request_free(struct evhttp_request *req)
|
|||||||
free(req);
|
free(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allows for inspection of the request URI
|
||||||
|
*/
|
||||||
|
|
||||||
|
const char *
|
||||||
|
evhttp_request_uri(struct evhttp_request *req) {
|
||||||
|
if (req->uri == NULL)
|
||||||
|
event_debug(("%s: request %p has no uri\n", req));
|
||||||
|
return (req->uri);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Takes a file descriptor to read a request from.
|
* Takes a file descriptor to read a request from.
|
||||||
* The callback is executed once the whole request has been read.
|
* The callback is executed once the whole request has been read.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2004 Niels Provos <provos@citi.umich.edu>
|
* Copyright (c) 2003-2006 Niels Provos <provos@citi.umich.edu>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -62,6 +62,7 @@ extern int test_ok;
|
|||||||
static struct evhttp *http;
|
static struct evhttp *http;
|
||||||
|
|
||||||
void http_basic_cb(struct evhttp_request *req, void *arg);
|
void http_basic_cb(struct evhttp_request *req, void *arg);
|
||||||
|
void http_post_cb(struct evhttp_request *req, void *arg);
|
||||||
|
|
||||||
struct evhttp *
|
struct evhttp *
|
||||||
http_setup(short *pport)
|
http_setup(short *pport)
|
||||||
@ -84,6 +85,7 @@ http_setup(short *pport)
|
|||||||
|
|
||||||
/* Register a callback for certain types of requests */
|
/* 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);
|
||||||
|
evhttp_set_cb(myhttp, "/postit", http_post_cb, NULL);
|
||||||
|
|
||||||
*pport = port;
|
*pport = port;
|
||||||
return (myhttp);
|
return (myhttp);
|
||||||
@ -232,11 +234,6 @@ http_connection_test(void)
|
|||||||
|
|
||||||
event_dispatch();
|
event_dispatch();
|
||||||
|
|
||||||
/*
|
|
||||||
* At this point, we want to schedule a request to the HTTP
|
|
||||||
* server using our start request method.
|
|
||||||
*/
|
|
||||||
|
|
||||||
evhttp_connection_free(evcon);
|
evhttp_connection_free(evcon);
|
||||||
evhttp_free(http);
|
evhttp_free(http);
|
||||||
|
|
||||||
@ -260,6 +257,11 @@ http_connectcb(struct evhttp_connection *evcon, void *arg)
|
|||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* At this point, we want to schedule a request to the HTTP
|
||||||
|
* server using our make request method.
|
||||||
|
*/
|
||||||
|
|
||||||
req = evhttp_request_new(http_request_done, NULL);
|
req = evhttp_request_new(http_request_done, NULL);
|
||||||
|
|
||||||
/* Add the information that we care about */
|
/* Add the information that we care about */
|
||||||
@ -282,8 +284,7 @@ http_request_done(struct evhttp_request *req, void *arg)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (evhttp_find_header(req->input_headers,
|
if (evhttp_find_header(req->input_headers, "Content-Type") == NULL) {
|
||||||
"Content-Type") == NULL) {
|
|
||||||
fprintf(stderr, "FAILED\n");
|
fprintf(stderr, "FAILED\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -302,9 +303,137 @@ http_request_done(struct evhttp_request *req, void *arg)
|
|||||||
event_loopexit(NULL);
|
event_loopexit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* HTTP POST test.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void http_connect_forpostcb(struct evhttp_connection *evcon, void *arg);
|
||||||
|
|
||||||
|
void
|
||||||
|
http_post_test(void)
|
||||||
|
{
|
||||||
|
short port = -1;
|
||||||
|
struct evhttp_connection *evcon = NULL;
|
||||||
|
|
||||||
|
test_ok = 0;
|
||||||
|
fprintf(stdout, "Testing HTTP POST Request: ");
|
||||||
|
|
||||||
|
http = http_setup(&port);
|
||||||
|
|
||||||
|
evcon = evhttp_connect("127.0.0.1", port, http_connect_forpostcb, NULL);
|
||||||
|
if (evcon == NULL) {
|
||||||
|
fprintf(stdout, "FAILED\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
event_dispatch();
|
||||||
|
|
||||||
|
evhttp_connection_free(evcon);
|
||||||
|
evhttp_free(http);
|
||||||
|
|
||||||
|
if (test_ok != 1) {
|
||||||
|
fprintf(stdout, "FAILED\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stdout, "OK\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void http_postrequest_done(struct evhttp_request *, void *);
|
||||||
|
|
||||||
|
#define POST_DATA "Okay. Not really printf"
|
||||||
|
|
||||||
|
void
|
||||||
|
http_connect_forpostcb(struct evhttp_connection *evcon, void *arg)
|
||||||
|
{
|
||||||
|
struct evhttp_request *req = NULL;
|
||||||
|
|
||||||
|
if (evcon == NULL) {
|
||||||
|
fprintf(stdout, "FAILED\n");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* At this point, we want to schedule an HTTP POST request
|
||||||
|
* server using our make request method.
|
||||||
|
*/
|
||||||
|
|
||||||
|
req = evhttp_request_new(http_postrequest_done, NULL);
|
||||||
|
|
||||||
|
/* Add the information that we care about */
|
||||||
|
evhttp_add_header(req->output_headers, "Host", "somehost");
|
||||||
|
evbuffer_add_printf(req->buffer, POST_DATA);
|
||||||
|
|
||||||
|
if (evhttp_make_request(evcon, req, EVHTTP_REQ_POST, "/postit") == -1) {
|
||||||
|
fprintf(stdout, "FAILED\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
http_post_cb(struct evhttp_request *req, void *arg)
|
||||||
|
{
|
||||||
|
event_debug((stderr, "%s: called\n", __func__));
|
||||||
|
|
||||||
|
/* Yes, we are expecting a post request */
|
||||||
|
if (req->type != EVHTTP_REQ_POST) {
|
||||||
|
fprintf(stdout, "FAILED\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EVBUFFER_LENGTH(req->buffer) != strlen(POST_DATA)) {
|
||||||
|
fprintf(stdout, "FAILED\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(EVBUFFER_DATA(req->buffer), POST_DATA)) {
|
||||||
|
fprintf(stdout, "FAILED\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct evbuffer *evb = evbuffer_new();
|
||||||
|
evbuffer_add_printf(evb, "This is funny");
|
||||||
|
|
||||||
|
evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb);
|
||||||
|
|
||||||
|
evbuffer_free(evb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
http_postrequest_done(struct evhttp_request *req, void *arg)
|
||||||
|
{
|
||||||
|
const char *what = "This is funny";
|
||||||
|
|
||||||
|
if (req->response_code != HTTP_OK) {
|
||||||
|
|
||||||
|
fprintf(stderr, "FAILED\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (evhttp_find_header(req->input_headers, "Content-Type") == NULL) {
|
||||||
|
fprintf(stderr, "FAILED\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EVBUFFER_LENGTH(req->buffer) != strlen(what)) {
|
||||||
|
fprintf(stderr, "FAILED\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(EVBUFFER_DATA(req->buffer), what, strlen(what)) != 0) {
|
||||||
|
fprintf(stderr, "FAILED\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
test_ok = 1;
|
||||||
|
event_loopexit(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
http_suite(void)
|
http_suite(void)
|
||||||
{
|
{
|
||||||
http_basic_test();
|
http_basic_test();
|
||||||
http_connection_test();
|
http_connection_test();
|
||||||
|
http_post_test();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user