mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-12 05:48:51 -04:00
Define enumerators for all HTTP methods, including PATCH from RFC5789
This patch defines enumerators for all HTTP methods that exist (including PATCH introduced in RFC 5789). It also makes them bit-masky (that's not a word, is it?), breaking binary- but not source-code compatibility. evhttp now stores a bitmask specifying for which methods requests to dispatch and which ones to reject with "405 Method Not Allowed". By default that's the ones we currently have (GET, POST, HEAD, PUT, DELETE), thereby keeping functional compatibility (besides the minor change that one of the other methods will now cause 405 instead of 400. But I believe that could even be considered a bug-fix). evhttp is extended by evhttp_set_allowed_methods() with which the user can change that bitmask. no regressions here and my test-app still works. Haven't yet actually tested any of the new methods. What's obviously missing here is the special logic for the methods: OPTIONS: We should be fine here - I believe our current dispatch logic should work fine. Some convenience functions would be fine though. TRACE: I'm pretty certain we should never dispatch this to the callbacks and simply implement the necessary functionality built-in. CONNECT: Pretty straight-forward to implement (and considering the framework in which we implement it very efficient too). Should probably go built-in. PATCH: Except for checking the RFC against our pre-dispatch logic (there just might be some "MUST not have Some-Header" lurking somewhere) there is nothing to be done here, this is completely up to the user. Nothing to do.
This commit is contained in:
parent
78762383b7
commit
75a73414a4
@ -145,6 +145,9 @@ struct evhttp {
|
||||
size_t default_max_headers_size;
|
||||
ev_uint64_t default_max_body_size;
|
||||
|
||||
/* bitmask of all allowed methods */
|
||||
short allowed_methods;
|
||||
|
||||
/* Fallback callback if all the other callbacks for this connection
|
||||
don't match. */
|
||||
void (*gencb)(struct evhttp_request *req, void *);
|
||||
|
37
http.c
37
http.c
@ -288,6 +288,18 @@ evhttp_method(enum evhttp_cmd_type type)
|
||||
case EVHTTP_REQ_DELETE:
|
||||
method = "DELETE";
|
||||
break;
|
||||
case EVHTTP_REQ_OPTIONS:
|
||||
method = "OPTIONS";
|
||||
break;
|
||||
case EVHTTP_REQ_TRACE:
|
||||
method = "TRACE";
|
||||
break;
|
||||
case EVHTTP_REQ_CONNECT:
|
||||
method = "CONNECT";
|
||||
break;
|
||||
case EVHTTP_REQ_PATCH:
|
||||
method = "PATCH";
|
||||
break;
|
||||
default:
|
||||
method = NULL;
|
||||
break;
|
||||
@ -1379,6 +1391,12 @@ evhttp_parse_request_line(struct evhttp_request *req, char *line)
|
||||
req->type = EVHTTP_REQ_PUT;
|
||||
} else if (strcmp(method, "DELETE") == 0) {
|
||||
req->type = EVHTTP_REQ_DELETE;
|
||||
} else if (strcmp(method, "OPTIONS") == 0) {
|
||||
req->type = EVHTTP_REQ_OPTIONS;
|
||||
} else if (strcmp(method, "TRACE") == 0) {
|
||||
req->type = EVHTTP_REQ_TRACE;
|
||||
} else if (strcmp(method, "PATCH") == 0) {
|
||||
req->type = EVHTTP_REQ_PATCH;
|
||||
} else {
|
||||
event_debug(("%s: bad method %s on request %p from %s",
|
||||
__func__, method, req, req->remote_host));
|
||||
@ -2668,11 +2686,17 @@ evhttp_handle_request(struct evhttp_request *req, void *arg)
|
||||
/* we have a new request on which the user needs to take action */
|
||||
req->userdone = 0;
|
||||
|
||||
if (req->uri == NULL) {
|
||||
if (req->type == 0 || req->uri == NULL) {
|
||||
evhttp_send_error(req, HTTP_BADREQUEST, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((http->allowed_methods & req->type) == 0) {
|
||||
event_debug(("Rejecting disallowed method %d (allowed: %d)\n", req->type, http->allowed_methods));
|
||||
evhttp_send_error(req, HTTP_BADMETHOD, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/* handle potential virtual hosts */
|
||||
hostname = evhttp_find_header(req->input_headers, "Host");
|
||||
if (hostname != NULL) {
|
||||
@ -2858,6 +2882,11 @@ evhttp_new_object(void)
|
||||
http->timeout = -1;
|
||||
evhttp_set_max_headers_size(http, EV_SIZE_MAX);
|
||||
evhttp_set_max_body_size(http, EV_SIZE_MAX);
|
||||
evhttp_set_allowed_methods(http, EVHTTP_REQ_GET |
|
||||
EVHTTP_REQ_POST |
|
||||
EVHTTP_REQ_HEAD |
|
||||
EVHTTP_REQ_PUT |
|
||||
EVHTTP_REQ_DELETE);
|
||||
|
||||
TAILQ_INIT(&http->sockets);
|
||||
TAILQ_INIT(&http->callbacks);
|
||||
@ -2990,6 +3019,12 @@ evhttp_set_max_body_size(struct evhttp* http, ev_ssize_t max_body_size)
|
||||
http->default_max_body_size = max_body_size;
|
||||
}
|
||||
|
||||
void
|
||||
evhttp_set_allowed_methods(struct evhttp* http, short methods)
|
||||
{
|
||||
http->allowed_methods = methods;
|
||||
}
|
||||
|
||||
int
|
||||
evhttp_set_cb(struct evhttp *http, const char *uri,
|
||||
void (*cb)(struct evhttp_request *, void *), void *cbarg)
|
||||
|
@ -57,6 +57,7 @@ struct event_base;
|
||||
#define HTTP_NOTMODIFIED 304 /**< page was not modified from last */
|
||||
#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 */
|
||||
#define HTTP_SERVUNAVAIL 503 /**< the server is not available */
|
||||
|
||||
struct evhttp;
|
||||
@ -183,6 +184,17 @@ void evhttp_set_max_headers_size(struct evhttp* http, ev_ssize_t max_headers_siz
|
||||
/** XXX Document. */
|
||||
void evhttp_set_max_body_size(struct evhttp* http, ev_ssize_t max_body_size);
|
||||
|
||||
/**
|
||||
Sets the what HTTP methods are supported in requests accepted by this server.
|
||||
If not supported they will generate a "405 Method not allowed" response.
|
||||
|
||||
By default this includes the following methods: GET, POST, HEAD, PUT, DELETE
|
||||
|
||||
@param http the http server on which to set the methods
|
||||
@param methods bit mask constructed from evhttp_cmd_type values
|
||||
*/
|
||||
void evhttp_set_allowed_methods(struct evhttp* http, short methods);
|
||||
|
||||
/**
|
||||
Set a callback for a specified URI
|
||||
|
||||
@ -329,11 +341,15 @@ void evhttp_send_reply_end(struct evhttp_request *req);
|
||||
|
||||
/** the different request types supported by evhttp */
|
||||
enum evhttp_cmd_type {
|
||||
EVHTTP_REQ_GET,
|
||||
EVHTTP_REQ_POST,
|
||||
EVHTTP_REQ_HEAD,
|
||||
EVHTTP_REQ_PUT,
|
||||
EVHTTP_REQ_DELETE
|
||||
EVHTTP_REQ_GET = 1 << 0,
|
||||
EVHTTP_REQ_POST = 1 << 1,
|
||||
EVHTTP_REQ_HEAD = 1 << 2,
|
||||
EVHTTP_REQ_PUT = 1 << 3,
|
||||
EVHTTP_REQ_DELETE = 1 << 4,
|
||||
EVHTTP_REQ_OPTIONS = 1 << 5,
|
||||
EVHTTP_REQ_TRACE = 1 << 6,
|
||||
EVHTTP_REQ_CONNECT = 1 << 7,
|
||||
EVHTTP_REQ_PATCH = 1 << 8
|
||||
};
|
||||
|
||||
/** a request object can represent either a request or a reply */
|
||||
|
Loading…
x
Reference in New Issue
Block a user