2 * Copyright (c) 2002-2007 Niels Provos <provos@citi.umich.edu>
3 * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "event2/event-config.h"
29 #include "evconfig-private.h"
31 #ifdef EVENT__HAVE_SYS_PARAM_H
32 #include <sys/param.h>
34 #ifdef EVENT__HAVE_SYS_TYPES_H
35 #include <sys/types.h>
38 #ifdef EVENT__HAVE_SYS_TIME_H
41 #ifdef HAVE_SYS_IOCCOM_H
42 #include <sys/ioccom.h>
46 #include <sys/resource.h>
47 #include <sys/socket.h>
55 #include <sys/queue.h>
57 #ifdef EVENT__HAVE_NETINET_IN_H
58 #include <netinet/in.h>
60 #ifdef EVENT__HAVE_ARPA_INET_H
61 #include <arpa/inet.h>
63 #ifdef EVENT__HAVE_NETDB_H
80 #ifdef EVENT__HAVE_UNISTD_H
83 #ifdef EVENT__HAVE_FCNTL_H
87 #undef timeout_pending
88 #undef timeout_initialized
90 #include "strlcpy-internal.h"
91 #include "event2/http.h"
92 #include "event2/event.h"
93 #include "event2/buffer.h"
94 #include "event2/bufferevent.h"
95 #include "event2/http_struct.h"
96 #include "event2/http_compat.h"
97 #include "event2/util.h"
98 #include "event2/listener.h"
99 #include "log-internal.h"
100 #include "util-internal.h"
101 #include "http-internal.h"
102 #include "mm-internal.h"
103 #include "bufferevent-internal.h"
105 #ifndef EVENT__HAVE_GETNAMEINFO
106 #define NI_MAXSERV 32
107 #define NI_MAXHOST 1025
109 #ifndef NI_NUMERICHOST
110 #define NI_NUMERICHOST 1
113 #ifndef NI_NUMERICSERV
114 #define NI_NUMERICSERV 2
118 fake_getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
119 size_t hostlen, char *serv, size_t servlen, int flags)
121 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
125 evutil_snprintf(tmpserv, sizeof(tmpserv),
126 "%d", ntohs(sin->sin_port));
127 if (strlcpy(serv, tmpserv, servlen) >= servlen)
132 if (flags & NI_NUMERICHOST) {
133 if (strlcpy(host, inet_ntoa(sin->sin_addr),
140 hp = gethostbyaddr((char *)&sin->sin_addr,
141 sizeof(struct in_addr), AF_INET);
145 if (strlcpy(host, hp->h_name, hostlen) >= hostlen)
156 #define REQ_VERSION_BEFORE(req, major_v, minor_v) \
157 ((req)->major < (major_v) || \
158 ((req)->major == (major_v) && (req)->minor < (minor_v)))
160 #define REQ_VERSION_ATLEAST(req, major_v, minor_v) \
161 ((req)->major > (major_v) || \
162 ((req)->major == (major_v) && (req)->minor >= (minor_v)))
165 #define MIN(a,b) (((a)<(b))?(a):(b))
170 static evutil_socket_t bind_socket_ai(struct evutil_addrinfo *, int reuse);
171 static evutil_socket_t bind_socket(const char *, ev_uint16_t, int reuse);
172 static void name_from_addr(struct sockaddr *, ev_socklen_t, char **, char **);
173 static int evhttp_associate_new_request_with_connection(
174 struct evhttp_connection *evcon);
175 static void evhttp_connection_start_detectclose(
176 struct evhttp_connection *evcon);
177 static void evhttp_connection_stop_detectclose(
178 struct evhttp_connection *evcon);
179 static void evhttp_request_dispatch(struct evhttp_connection* evcon);
180 static void evhttp_read_firstline(struct evhttp_connection *evcon,
181 struct evhttp_request *req);
182 static void evhttp_read_header(struct evhttp_connection *evcon,
183 struct evhttp_request *req);
184 static int evhttp_add_header_internal(struct evkeyvalq *headers,
185 const char *key, const char *value);
186 static const char *evhttp_response_phrase_internal(int code);
187 static void evhttp_get_request(struct evhttp *, evutil_socket_t, struct sockaddr *, ev_socklen_t);
188 static void evhttp_write_buffer(struct evhttp_connection *,
189 void (*)(struct evhttp_connection *, void *), void *);
190 static void evhttp_make_header(struct evhttp_connection *, struct evhttp_request *);
192 /* callbacks for bufferevent */
193 static void evhttp_read_cb(struct bufferevent *, void *);
194 static void evhttp_write_cb(struct bufferevent *, void *);
195 static void evhttp_error_cb(struct bufferevent *bufev, short what, void *arg);
196 static int evhttp_find_vhost(struct evhttp *http, struct evhttp **outhttp,
197 const char *hostname);
199 #ifndef EVENT__HAVE_STRSEP
200 /* strsep replacement for platforms that lack it. Only works if
201 * del is one character long. */
203 strsep(char **s, const char *del)
206 EVUTIL_ASSERT(strlen(del) == 1);
210 d = strstr(tok, del);
221 html_replace(const char ch, const char **escaped)
247 * Replaces <, >, ", ' and & with <, >, ",
248 * ' and & correspondingly.
250 * The returned string needs to be freed by the caller.
254 evhttp_htmlescape(const char *html)
257 size_t new_size = 0, old_size = 0;
258 char *escaped_html, *p;
263 old_size = strlen(html);
264 for (i = 0; i < old_size; ++i) {
265 const char *replaced = NULL;
266 const size_t replace_size = html_replace(html[i], &replaced);
267 if (replace_size > EV_SIZE_MAX - new_size) {
268 event_warn("%s: html_replace overflow", __func__);
271 new_size += replace_size;
274 if (new_size == EV_SIZE_MAX)
276 p = escaped_html = mm_malloc(new_size + 1);
277 if (escaped_html == NULL) {
278 event_warn("%s: malloc(%lu)", __func__,
279 (unsigned long)(new_size + 1));
282 for (i = 0; i < old_size; ++i) {
283 const char *replaced = &html[i];
284 const size_t len = html_replace(html[i], &replaced);
285 memcpy(p, replaced, len);
291 return (escaped_html);
294 /** Given an evhttp_cmd_type, returns a constant string containing the
295 * equivalent HTTP command, or NULL if the evhttp_command_type is
298 evhttp_method(enum evhttp_cmd_type type)
306 case EVHTTP_REQ_POST:
309 case EVHTTP_REQ_HEAD:
315 case EVHTTP_REQ_DELETE:
318 case EVHTTP_REQ_OPTIONS:
321 case EVHTTP_REQ_TRACE:
324 case EVHTTP_REQ_CONNECT:
327 case EVHTTP_REQ_PATCH:
339 * Determines if a response should have a body.
340 * Follows the rules in RFC 2616 section 4.3.
341 * @return 1 if the response MUST have a body; 0 if the response MUST NOT have
345 evhttp_response_needs_body(struct evhttp_request *req)
347 return (req->response_code != HTTP_NOCONTENT &&
348 req->response_code != HTTP_NOTMODIFIED &&
349 (req->response_code < 100 || req->response_code >= 200) &&
350 req->type != EVHTTP_REQ_HEAD);
353 /** Helper: called after we've added some data to an evcon's bufferevent's
354 * output buffer. Sets the evconn's writing-is-done callback, and puts
355 * the bufferevent into writing mode.
358 evhttp_write_buffer(struct evhttp_connection *evcon,
359 void (*cb)(struct evhttp_connection *, void *), void *arg)
361 event_debug(("%s: preparing to write buffer\n", __func__));
367 /* Disable the read callback: we don't actually care about data;
368 * we only care about close detection. (We don't disable reading,
369 * since we *do* want to learn about any close events.) */
370 bufferevent_setcb(evcon->bufev,
376 bufferevent_enable(evcon->bufev, EV_WRITE);
380 evhttp_send_continue_done(struct evhttp_connection *evcon, void *arg)
382 bufferevent_disable(evcon->bufev, EV_WRITE);
386 evhttp_send_continue(struct evhttp_connection *evcon,
387 struct evhttp_request *req)
389 bufferevent_enable(evcon->bufev, EV_WRITE);
390 evbuffer_add_printf(bufferevent_get_output(evcon->bufev),
391 "HTTP/%d.%d 100 Continue\r\n\r\n",
392 req->major, req->minor);
393 evcon->cb = evhttp_send_continue_done;
394 evcon->cb_arg = NULL;
395 bufferevent_setcb(evcon->bufev,
402 /** Helper: returns true iff evconn is in any connected state. */
404 evhttp_connected(struct evhttp_connection *evcon)
406 switch (evcon->state) {
407 case EVCON_DISCONNECTED:
408 case EVCON_CONNECTING:
411 case EVCON_READING_FIRSTLINE:
412 case EVCON_READING_HEADERS:
413 case EVCON_READING_BODY:
414 case EVCON_READING_TRAILER:
421 /* Create the headers needed for an outgoing HTTP request, adds them to
422 * the request's header list, and writes the request line to the
423 * connection's output buffer.
426 evhttp_make_header_request(struct evhttp_connection *evcon,
427 struct evhttp_request *req)
431 evhttp_remove_header(req->output_headers, "Proxy-Connection");
433 /* Generate request line */
434 method = evhttp_method(req->type);
435 evbuffer_add_printf(bufferevent_get_output(evcon->bufev),
436 "%s %s HTTP/%d.%d\r\n",
437 method, req->uri, req->major, req->minor);
439 /* Add the content length on a post or put request if missing */
440 if ((req->type == EVHTTP_REQ_POST || req->type == EVHTTP_REQ_PUT) &&
441 evhttp_find_header(req->output_headers, "Content-Length") == NULL){
443 evutil_snprintf(size, sizeof(size), EV_SIZE_FMT,
444 EV_SIZE_ARG(evbuffer_get_length(req->output_buffer)));
445 evhttp_add_header(req->output_headers, "Content-Length", size);
449 /** Return true if the list of headers in 'headers', intepreted with respect
450 * to flags, means that we should send a "connection: close" when the request
453 evhttp_is_connection_close(int flags, struct evkeyvalq* headers)
455 if (flags & EVHTTP_PROXY_REQUEST) {
456 /* proxy connection */
457 const char *connection = evhttp_find_header(headers, "Proxy-Connection");
458 return (connection == NULL || evutil_ascii_strcasecmp(connection, "keep-alive") != 0);
460 const char *connection = evhttp_find_header(headers, "Connection");
461 return (connection != NULL && evutil_ascii_strcasecmp(connection, "close") == 0);
465 /* Return true iff 'headers' contains 'Connection: keep-alive' */
467 evhttp_is_connection_keepalive(struct evkeyvalq* headers)
469 const char *connection = evhttp_find_header(headers, "Connection");
470 return (connection != NULL
471 && evutil_ascii_strncasecmp(connection, "keep-alive", 10) == 0);
474 /* Add a correct "Date" header to headers, unless it already has one. */
476 evhttp_maybe_add_date_header(struct evkeyvalq *headers)
478 if (evhttp_find_header(headers, "Date") == NULL) {
484 time_t t = time(NULL);
491 if (strftime(date, sizeof(date),
492 "%a, %d %b %Y %H:%M:%S GMT", cur_p) != 0) {
493 evhttp_add_header(headers, "Date", date);
498 /* Add a "Content-Length" header with value 'content_length' to headers,
499 * unless it already has a content-length or transfer-encoding header. */
501 evhttp_maybe_add_content_length_header(struct evkeyvalq *headers,
502 size_t content_length)
504 if (evhttp_find_header(headers, "Transfer-Encoding") == NULL &&
505 evhttp_find_header(headers, "Content-Length") == NULL) {
507 evutil_snprintf(len, sizeof(len), EV_SIZE_FMT,
508 EV_SIZE_ARG(content_length));
509 evhttp_add_header(headers, "Content-Length", len);
514 * Create the headers needed for an HTTP reply in req->output_headers,
515 * and write the first HTTP response for req line to evcon.
518 evhttp_make_header_response(struct evhttp_connection *evcon,
519 struct evhttp_request *req)
521 int is_keepalive = evhttp_is_connection_keepalive(req->input_headers);
522 evbuffer_add_printf(bufferevent_get_output(evcon->bufev),
523 "HTTP/%d.%d %d %s\r\n",
524 req->major, req->minor, req->response_code,
525 req->response_code_line);
527 if (req->major == 1) {
529 evhttp_maybe_add_date_header(req->output_headers);
532 * if the protocol is 1.0; and the connection was keep-alive
533 * we need to add a keep-alive header, too.
535 if (req->minor == 0 && is_keepalive)
536 evhttp_add_header(req->output_headers,
537 "Connection", "keep-alive");
539 if ((req->minor >= 1 || is_keepalive) &&
540 evhttp_response_needs_body(req)) {
542 * we need to add the content length if the
543 * user did not give it, this is required for
544 * persistent connections to work.
546 evhttp_maybe_add_content_length_header(
548 evbuffer_get_length(req->output_buffer));
552 /* Potentially add headers for unidentified content. */
553 if (evhttp_response_needs_body(req)) {
554 if (evhttp_find_header(req->output_headers,
555 "Content-Type") == NULL
556 && evcon->http_server->default_content_type) {
557 evhttp_add_header(req->output_headers,
559 evcon->http_server->default_content_type);
563 /* if the request asked for a close, we send a close, too */
564 if (evhttp_is_connection_close(req->flags, req->input_headers)) {
565 evhttp_remove_header(req->output_headers, "Connection");
566 if (!(req->flags & EVHTTP_PROXY_REQUEST))
567 evhttp_add_header(req->output_headers, "Connection", "close");
568 evhttp_remove_header(req->output_headers, "Proxy-Connection");
572 /** Generate all headers appropriate for sending the http request in req (or
573 * the response, if we're sending a response), and write them to evcon's
574 * bufferevent. Also writes all data from req->output_buffer */
576 evhttp_make_header(struct evhttp_connection *evcon, struct evhttp_request *req)
578 struct evkeyval *header;
579 struct evbuffer *output = bufferevent_get_output(evcon->bufev);
582 * Depending if this is a HTTP request or response, we might need to
583 * add some new headers or remove existing headers.
585 if (req->kind == EVHTTP_REQUEST) {
586 evhttp_make_header_request(evcon, req);
588 evhttp_make_header_response(evcon, req);
591 TAILQ_FOREACH(header, req->output_headers, next) {
592 evbuffer_add_printf(output, "%s: %s\r\n",
593 header->key, header->value);
595 evbuffer_add(output, "\r\n", 2);
597 if (evbuffer_get_length(req->output_buffer) > 0) {
599 * For a request, we add the POST data, for a reply, this
600 * is the regular data.
602 /* XXX We might want to support waiting (a limited amount of
603 time) for a continue status line from the server before
604 sending POST/PUT message bodies. */
605 evbuffer_add_buffer(output, req->output_buffer);
610 evhttp_connection_set_max_headers_size(struct evhttp_connection *evcon,
611 ev_ssize_t new_max_headers_size)
613 if (new_max_headers_size<0)
614 evcon->max_headers_size = EV_SIZE_MAX;
616 evcon->max_headers_size = new_max_headers_size;
619 evhttp_connection_set_max_body_size(struct evhttp_connection* evcon,
620 ev_ssize_t new_max_body_size)
622 if (new_max_body_size<0)
623 evcon->max_body_size = EV_UINT64_MAX;
625 evcon->max_body_size = new_max_body_size;
629 evhttp_connection_incoming_fail(struct evhttp_request *req,
630 enum evhttp_request_error error)
633 case EVREQ_HTTP_TIMEOUT:
636 * these are cases in which we probably should just
637 * close the connection and not send a reply. this
638 * case may happen when a browser keeps a persistent
639 * connection open and we timeout on the read. when
640 * the request is still being used for sending, we
641 * need to disassociated it from the connection here.
643 if (!req->userdone) {
644 /* remove it so that it will not be freed */
645 TAILQ_REMOVE(&req->evcon->requests, req, next);
646 /* indicate that this request no longer has a
652 case EVREQ_HTTP_INVALID_HEADER:
653 case EVREQ_HTTP_BUFFER_ERROR:
654 case EVREQ_HTTP_REQUEST_CANCEL:
655 case EVREQ_HTTP_DATA_TOO_LONG:
656 default: /* xxx: probably should just error on default */
657 /* the callback looks at the uri to determine errors */
662 if (req->uri_elems) {
663 evhttp_uri_free(req->uri_elems);
664 req->uri_elems = NULL;
668 * the callback needs to send a reply, once the reply has
669 * been send, the connection should get freed.
671 (*req->cb)(req, req->cb_arg);
677 /* Called when evcon has experienced a (non-recoverable? -NM) error, as
678 * given in error. If it's an outgoing connection, reset the connection,
679 * retry any pending requests, and inform the user. If it's incoming,
680 * delegates to evhttp_connection_incoming_fail(). */
682 evhttp_connection_fail_(struct evhttp_connection *evcon,
683 enum evhttp_request_error error)
685 const int errsave = EVUTIL_SOCKET_ERROR();
686 struct evhttp_request* req = TAILQ_FIRST(&evcon->requests);
687 void (*cb)(struct evhttp_request *, void *);
689 void (*error_cb)(enum evhttp_request_error, void *);
691 EVUTIL_ASSERT(req != NULL);
693 bufferevent_disable(evcon->bufev, EV_READ|EV_WRITE);
695 if (evcon->flags & EVHTTP_CON_INCOMING) {
697 * for incoming requests, there are two different
698 * failure cases. it's either a network level error
699 * or an http layer error. for problems on the network
700 * layer like timeouts we just drop the connections.
701 * For HTTP problems, we might have to send back a
702 * reply before the connection can be freed.
704 if (evhttp_connection_incoming_fail(req, error) == -1)
705 evhttp_connection_free(evcon);
709 error_cb = req->error_cb;
710 error_cb_arg = req->cb_arg;
711 /* when the request was canceled, the callback is not executed */
712 if (error != EVREQ_HTTP_REQUEST_CANCEL) {
713 /* save the callback for later; the cb might free our object */
715 cb_arg = req->cb_arg;
721 /* do not fail all requests; the next request is going to get
722 * send over a new connection. when a user cancels a request,
723 * all other pending requests should be processed as normal
725 TAILQ_REMOVE(&evcon->requests, req, next);
726 evhttp_request_free(req);
728 /* reset the connection */
729 evhttp_connection_reset_(evcon);
731 /* We are trying the next request that was queued on us */
732 if (TAILQ_FIRST(&evcon->requests) != NULL)
733 evhttp_connection_connect_(evcon);
735 /* The call to evhttp_connection_reset_ overwrote errno.
736 * Let's restore the original errno, so that the user's
737 * callback can have a better idea of what the error was.
739 EVUTIL_SET_SOCKET_ERROR(errsave);
741 /* inform the user */
742 if (error_cb != NULL)
743 error_cb(error, error_cb_arg);
748 /* Bufferevent callback: invoked when any data has been written from an
749 * http connection's bufferevent */
751 evhttp_write_cb(struct bufferevent *bufev, void *arg)
753 struct evhttp_connection *evcon = arg;
755 /* Activate our call back */
756 if (evcon->cb != NULL)
757 (*evcon->cb)(evcon, evcon->cb_arg);
761 * Advance the connection state.
762 * - If this is an outgoing connection, we've just processed the response;
763 * idle or close the connection.
764 * - If this is an incoming connection, we've just processed the request;
768 evhttp_connection_done(struct evhttp_connection *evcon)
770 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
771 int con_outgoing = evcon->flags & EVHTTP_CON_OUTGOING;
775 /* idle or close the connection */
777 TAILQ_REMOVE(&evcon->requests, req, next);
780 evcon->state = EVCON_IDLE;
783 evhttp_is_connection_close(req->flags, req->input_headers)||
784 evhttp_is_connection_close(req->flags, req->output_headers);
786 /* check if we got asked to close the connection */
788 evhttp_connection_reset_(evcon);
790 if (TAILQ_FIRST(&evcon->requests) != NULL) {
792 * We have more requests; reset the connection
793 * and deal with the next request.
795 if (!evhttp_connected(evcon))
796 evhttp_connection_connect_(evcon);
798 evhttp_request_dispatch(evcon);
799 } else if (!need_close) {
801 * The connection is going to be persistent, but we
802 * need to detect if the other side closes it.
804 evhttp_connection_start_detectclose(evcon);
805 } else if ((evcon->flags & EVHTTP_CON_AUTOFREE)) {
807 * If we have no more requests that need completion
808 * and we're not waiting for the connection to close
814 * incoming connection - we need to leave the request on the
815 * connection so that we can reply to it.
817 evcon->state = EVCON_WRITING;
820 /* notify the user of the request */
821 (*req->cb)(req, req->cb_arg);
823 /* if this was an outgoing request, we own and it's done. so free it.
824 * unless the callback specifically requested to own the request.
826 if (con_outgoing && ((req->flags & EVHTTP_USER_OWNED) == 0)) {
827 evhttp_request_free(req);
830 /* If this was the last request of an outgoing connection and we're
831 * not waiting to receive a connection close event and we want to
832 * automatically free the connection. We check to ensure our request
833 * list is empty one last time just in case our callback added a
836 if (free_evcon && TAILQ_FIRST(&evcon->requests) == NULL) {
837 evhttp_connection_free(evcon);
842 * Handles reading from a chunked request.
843 * return ALL_DATA_READ:
844 * all data has been read
845 * return MORE_DATA_EXPECTED:
846 * more data is expected
847 * return DATA_CORRUPTED:
849 * return REQUEST_CANCELED:
850 * request was canceled by the user calling evhttp_cancel_request
851 * return DATA_TOO_LONG:
852 * ran over the maximum limit
855 static enum message_read_status
856 evhttp_handle_chunked_read(struct evhttp_request *req, struct evbuffer *buf)
858 if (req == NULL || buf == NULL) {
859 return DATA_CORRUPTED;
865 if ((buflen = evbuffer_get_length(buf)) == 0) {
869 /* evbuffer_get_length returns size_t, but len variable is ssize_t,
870 * check for overflow conditions */
871 if (buflen > EV_SSIZE_MAX) {
872 return DATA_CORRUPTED;
875 if (req->ntoread < 0) {
876 /* Read chunk size */
878 char *p = evbuffer_readln(buf, NULL, EVBUFFER_EOL_CRLF);
883 /* the last chunk is on a new line? */
884 if (strlen(p) == 0) {
888 ntoread = evutil_strtoll(p, &endp, 16);
889 error = (*p == '\0' ||
890 (*endp != '\0' && *endp != ' ') ||
894 /* could not get chunk size */
895 return (DATA_CORRUPTED);
898 /* ntoread is signed int64, body_size is unsigned size_t, check for under/overflow conditions */
899 if ((ev_uint64_t)ntoread > EV_SIZE_MAX - req->body_size) {
900 return DATA_CORRUPTED;
903 if (req->body_size + (size_t)ntoread > req->evcon->max_body_size) {
904 /* failed body length test */
905 event_debug(("Request body is too long"));
906 return (DATA_TOO_LONG);
909 req->body_size += (size_t)ntoread;
910 req->ntoread = ntoread;
911 if (req->ntoread == 0) {
913 return (ALL_DATA_READ);
918 /* req->ntoread is signed int64, len is ssize_t, based on arch,
919 * ssize_t could only be 32b, check for these conditions */
920 if (req->ntoread > EV_SSIZE_MAX) {
921 return DATA_CORRUPTED;
924 /* don't have enough to complete a chunk; wait for more */
925 if (req->ntoread > 0 && buflen < (ev_uint64_t)req->ntoread)
926 return (MORE_DATA_EXPECTED);
928 /* Completed chunk */
929 evbuffer_remove_buffer(buf, req->input_buffer, (size_t)req->ntoread);
931 if (req->chunk_cb != NULL) {
932 req->flags |= EVHTTP_REQ_DEFER_FREE;
933 (*req->chunk_cb)(req, req->cb_arg);
934 evbuffer_drain(req->input_buffer,
935 evbuffer_get_length(req->input_buffer));
936 req->flags &= ~EVHTTP_REQ_DEFER_FREE;
937 if ((req->flags & EVHTTP_REQ_NEEDS_FREE) != 0) {
938 return (REQUEST_CANCELED);
943 return (MORE_DATA_EXPECTED);
947 evhttp_read_trailer(struct evhttp_connection *evcon, struct evhttp_request *req)
949 struct evbuffer *buf = bufferevent_get_input(evcon->bufev);
951 switch (evhttp_parse_headers_(req, buf)) {
954 evhttp_connection_fail_(evcon, EVREQ_HTTP_DATA_TOO_LONG);
957 bufferevent_disable(evcon->bufev, EV_READ);
958 evhttp_connection_done(evcon);
960 case MORE_DATA_EXPECTED:
961 case REQUEST_CANCELED: /* ??? */
963 bufferevent_enable(evcon->bufev, EV_READ);
969 evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
971 struct evbuffer *buf = bufferevent_get_input(evcon->bufev);
974 switch (evhttp_handle_chunked_read(req, buf)) {
976 /* finished last chunk */
977 evcon->state = EVCON_READING_TRAILER;
978 evhttp_read_trailer(evcon, req);
983 evhttp_connection_fail_(evcon,
984 EVREQ_HTTP_DATA_TOO_LONG);
986 case REQUEST_CANCELED:
987 /* request canceled */
988 evhttp_request_free(req);
990 case MORE_DATA_EXPECTED:
994 } else if (req->ntoread < 0) {
995 /* Read until connection close. */
996 if ((size_t)(req->body_size + evbuffer_get_length(buf)) < req->body_size) {
997 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
1001 req->body_size += evbuffer_get_length(buf);
1002 evbuffer_add_buffer(req->input_buffer, buf);
1003 } else if (req->chunk_cb != NULL || evbuffer_get_length(buf) >= (size_t)req->ntoread) {
1004 /* XXX: the above get_length comparison has to be fixed for overflow conditions! */
1005 /* We've postponed moving the data until now, but we're
1006 * about to use it. */
1007 size_t n = evbuffer_get_length(buf);
1009 if (n > (size_t) req->ntoread)
1010 n = (size_t) req->ntoread;
1012 req->body_size += n;
1013 evbuffer_remove_buffer(buf, req->input_buffer, n);
1016 if (req->body_size > req->evcon->max_body_size ||
1017 (!req->chunked && req->ntoread >= 0 &&
1018 (size_t)req->ntoread > req->evcon->max_body_size)) {
1019 /* XXX: The above casted comparison must checked for overflow */
1020 /* failed body length test */
1021 event_debug(("Request body is too long"));
1022 evhttp_connection_fail_(evcon,
1023 EVREQ_HTTP_DATA_TOO_LONG);
1027 if (evbuffer_get_length(req->input_buffer) > 0 && req->chunk_cb != NULL) {
1028 req->flags |= EVHTTP_REQ_DEFER_FREE;
1029 (*req->chunk_cb)(req, req->cb_arg);
1030 req->flags &= ~EVHTTP_REQ_DEFER_FREE;
1031 evbuffer_drain(req->input_buffer,
1032 evbuffer_get_length(req->input_buffer));
1033 if ((req->flags & EVHTTP_REQ_NEEDS_FREE) != 0) {
1034 evhttp_request_free(req);
1039 if (req->ntoread == 0) {
1040 bufferevent_disable(evcon->bufev, EV_READ);
1041 /* Completed content length */
1042 evhttp_connection_done(evcon);
1047 bufferevent_enable(evcon->bufev, EV_READ);
1050 #define get_deferred_queue(evcon) \
1054 * Gets called when more data becomes available
1058 evhttp_read_cb(struct bufferevent *bufev, void *arg)
1060 struct evhttp_connection *evcon = arg;
1061 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1063 /* Cancel if it's pending. */
1064 event_deferred_cb_cancel_(get_deferred_queue(evcon),
1065 &evcon->read_more_deferred_cb);
1067 switch (evcon->state) {
1068 case EVCON_READING_FIRSTLINE:
1069 evhttp_read_firstline(evcon, req);
1070 /* note the request may have been freed in
1071 * evhttp_read_body */
1073 case EVCON_READING_HEADERS:
1074 evhttp_read_header(evcon, req);
1075 /* note the request may have been freed in
1076 * evhttp_read_body */
1078 case EVCON_READING_BODY:
1079 evhttp_read_body(evcon, req);
1080 /* note the request may have been freed in
1081 * evhttp_read_body */
1083 case EVCON_READING_TRAILER:
1084 evhttp_read_trailer(evcon, req);
1089 struct evbuffer *input;
1092 input = bufferevent_get_input(evcon->bufev);
1093 total_len = evbuffer_get_length(input);
1094 event_debug(("%s: read "EV_SIZE_FMT
1095 " bytes in EVCON_IDLE state,"
1096 " resetting connection",
1097 __func__, EV_SIZE_ARG(total_len)));
1100 evhttp_connection_reset_(evcon);
1103 case EVCON_DISCONNECTED:
1104 case EVCON_CONNECTING:
1107 event_errx(1, "%s: illegal connection state %d",
1108 __func__, evcon->state);
1113 evhttp_deferred_read_cb(struct event_callback *cb, void *data)
1115 struct evhttp_connection *evcon = data;
1116 evhttp_read_cb(evcon->bufev, evcon);
1120 evhttp_write_connectioncb(struct evhttp_connection *evcon, void *arg)
1122 /* This is after writing the request to the server */
1123 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1124 EVUTIL_ASSERT(req != NULL);
1126 EVUTIL_ASSERT(evcon->state == EVCON_WRITING);
1128 /* We are done writing our header and are now expecting the response */
1129 req->kind = EVHTTP_RESPONSE;
1131 evhttp_start_read_(evcon);
1135 * Clean up a connection object
1139 evhttp_connection_free(struct evhttp_connection *evcon)
1141 struct evhttp_request *req;
1143 /* notify interested parties that this connection is going down */
1144 if (evcon->fd != -1) {
1145 if (evhttp_connected(evcon) && evcon->closecb != NULL)
1146 (*evcon->closecb)(evcon, evcon->closecb_arg);
1149 /* remove all requests that might be queued on this
1150 * connection. for server connections, this should be empty.
1151 * because it gets dequeued either in evhttp_connection_done or
1152 * evhttp_connection_fail_.
1154 while ((req = TAILQ_FIRST(&evcon->requests)) != NULL) {
1155 TAILQ_REMOVE(&evcon->requests, req, next);
1156 evhttp_request_free(req);
1159 if (evcon->http_server != NULL) {
1160 struct evhttp *http = evcon->http_server;
1161 TAILQ_REMOVE(&http->connections, evcon, next);
1164 if (event_initialized(&evcon->retry_ev)) {
1165 event_del(&evcon->retry_ev);
1166 event_debug_unassign(&evcon->retry_ev);
1169 if (evcon->bufev != NULL)
1170 bufferevent_free(evcon->bufev);
1172 event_deferred_cb_cancel_(get_deferred_queue(evcon),
1173 &evcon->read_more_deferred_cb);
1175 if (evcon->fd != -1) {
1176 shutdown(evcon->fd, EVUTIL_SHUT_WR);
1177 if (!(bufferevent_get_options_(evcon->bufev) & BEV_OPT_CLOSE_ON_FREE)) {
1178 evutil_closesocket(evcon->fd);
1182 if (evcon->bind_address != NULL)
1183 mm_free(evcon->bind_address);
1185 if (evcon->address != NULL)
1186 mm_free(evcon->address);
1188 if (evcon->conn_address != NULL)
1189 mm_free(evcon->conn_address);
1195 evhttp_connection_free_on_completion(struct evhttp_connection *evcon) {
1196 evcon->flags |= EVHTTP_CON_AUTOFREE;
1200 evhttp_connection_set_local_address(struct evhttp_connection *evcon,
1201 const char *address)
1203 EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED);
1204 if (evcon->bind_address)
1205 mm_free(evcon->bind_address);
1206 if ((evcon->bind_address = mm_strdup(address)) == NULL)
1207 event_warn("%s: strdup", __func__);
1211 evhttp_connection_set_local_port(struct evhttp_connection *evcon,
1214 EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED);
1215 evcon->bind_port = port;
1219 evhttp_request_dispatch(struct evhttp_connection* evcon)
1221 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1223 /* this should not usually happy but it's possible */
1227 /* delete possible close detection events */
1228 evhttp_connection_stop_detectclose(evcon);
1230 /* we assume that the connection is connected already */
1231 EVUTIL_ASSERT(evcon->state == EVCON_IDLE);
1233 evcon->state = EVCON_WRITING;
1235 /* Create the header from the store arguments */
1236 evhttp_make_header(evcon, req);
1238 evhttp_write_buffer(evcon, evhttp_write_connectioncb, NULL);
1241 /* Reset our connection state: disables reading/writing, closes our fd (if
1242 * any), clears out buffers, and puts us in state DISCONNECTED. */
1244 evhttp_connection_reset_(struct evhttp_connection *evcon)
1246 struct evbuffer *tmp;
1248 /* XXXX This is not actually an optimal fix. Instead we ought to have
1249 an API for "stop connecting", or use bufferevent_setfd to turn off
1250 connecting. But for Libevent 2.0, this seems like a minimal change
1251 least likely to disrupt the rest of the bufferevent and http code.
1253 Why is this here? If the fd is set in the bufferevent, and the
1254 bufferevent is connecting, then you can't actually stop the
1255 bufferevent from trying to connect with bufferevent_disable(). The
1256 connect will never trigger, since we close the fd, but the timeout
1257 might. That caused an assertion failure in evhttp_connection_fail_.
1259 bufferevent_disable_hard_(evcon->bufev, EV_READ|EV_WRITE);
1261 if (evcon->fd != -1) {
1262 /* inform interested parties about connection close */
1263 if (evhttp_connected(evcon) && evcon->closecb != NULL)
1264 (*evcon->closecb)(evcon, evcon->closecb_arg);
1266 shutdown(evcon->fd, EVUTIL_SHUT_WR);
1267 evutil_closesocket(evcon->fd);
1268 bufferevent_setfd(evcon->bufev, -1);
1272 /* we need to clean up any buffered data */
1273 tmp = bufferevent_get_output(evcon->bufev);
1274 evbuffer_drain(tmp, evbuffer_get_length(tmp));
1275 tmp = bufferevent_get_input(evcon->bufev);
1276 evbuffer_drain(tmp, evbuffer_get_length(tmp));
1278 evcon->state = EVCON_DISCONNECTED;
1282 evhttp_connection_start_detectclose(struct evhttp_connection *evcon)
1284 evcon->flags |= EVHTTP_CON_CLOSEDETECT;
1286 bufferevent_enable(evcon->bufev, EV_READ);
1290 evhttp_connection_stop_detectclose(struct evhttp_connection *evcon)
1292 evcon->flags &= ~EVHTTP_CON_CLOSEDETECT;
1294 bufferevent_disable(evcon->bufev, EV_READ);
1298 evhttp_connection_retry(evutil_socket_t fd, short what, void *arg)
1300 struct evhttp_connection *evcon = arg;
1302 evcon->state = EVCON_DISCONNECTED;
1303 evhttp_connection_connect_(evcon);
1307 evhttp_connection_cb_cleanup(struct evhttp_connection *evcon)
1309 struct evcon_requestq requests;
1311 evhttp_connection_reset_(evcon);
1312 if (evcon->retry_max < 0 || evcon->retry_cnt < evcon->retry_max) {
1313 struct timeval tv_retry = evcon->initial_retry_timeout;
1315 evtimer_assign(&evcon->retry_ev, evcon->base, evhttp_connection_retry, evcon);
1316 /* XXXX handle failure from evhttp_add_event */
1317 for (i=0; i < evcon->retry_cnt; ++i) {
1318 tv_retry.tv_usec *= 2;
1319 if (tv_retry.tv_usec > 1000000) {
1320 tv_retry.tv_usec -= 1000000;
1321 tv_retry.tv_sec += 1;
1323 tv_retry.tv_sec *= 2;
1324 if (tv_retry.tv_sec > 3600) {
1325 tv_retry.tv_sec = 3600;
1326 tv_retry.tv_usec = 0;
1329 event_add(&evcon->retry_ev, &tv_retry);
1335 * User callback can do evhttp_make_request() on the same
1336 * evcon so new request will be added to evcon->requests. To
1337 * avoid freeing it prematurely we iterate over the copy of
1340 TAILQ_INIT(&requests);
1341 while (TAILQ_FIRST(&evcon->requests) != NULL) {
1342 struct evhttp_request *request = TAILQ_FIRST(&evcon->requests);
1343 TAILQ_REMOVE(&evcon->requests, request, next);
1344 TAILQ_INSERT_TAIL(&requests, request, next);
1347 /* for now, we just signal all requests by executing their callbacks */
1348 while (TAILQ_FIRST(&requests) != NULL) {
1349 struct evhttp_request *request = TAILQ_FIRST(&requests);
1350 TAILQ_REMOVE(&requests, request, next);
1351 request->evcon = NULL;
1353 /* we might want to set an error here */
1354 request->cb(request, request->cb_arg);
1355 evhttp_request_free(request);
1360 evhttp_error_cb(struct bufferevent *bufev, short what, void *arg)
1362 struct evhttp_connection *evcon = arg;
1363 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1365 if (evcon->fd == -1)
1366 evcon->fd = bufferevent_getfd(bufev);
1368 switch (evcon->state) {
1369 case EVCON_CONNECTING:
1370 if (what & BEV_EVENT_TIMEOUT) {
1371 event_debug(("%s: connection timeout for \"%s:%d\" on "
1373 __func__, evcon->address, evcon->port,
1374 EV_SOCK_ARG(evcon->fd)));
1375 evhttp_connection_cb_cleanup(evcon);
1380 case EVCON_READING_BODY:
1381 if (!req->chunked && req->ntoread < 0
1382 && what == (BEV_EVENT_READING|BEV_EVENT_EOF)) {
1383 /* EOF on read can be benign */
1384 evhttp_connection_done(evcon);
1389 case EVCON_DISCONNECTED:
1391 case EVCON_READING_FIRSTLINE:
1392 case EVCON_READING_HEADERS:
1393 case EVCON_READING_TRAILER:
1399 /* when we are in close detect mode, a read error means that
1400 * the other side closed their connection.
1402 if (evcon->flags & EVHTTP_CON_CLOSEDETECT) {
1403 evcon->flags &= ~EVHTTP_CON_CLOSEDETECT;
1404 EVUTIL_ASSERT(evcon->http_server == NULL);
1405 /* For connections from the client, we just
1406 * reset the connection so that it becomes
1409 EVUTIL_ASSERT(evcon->state == EVCON_IDLE);
1410 evhttp_connection_reset_(evcon);
1413 * If we have no more requests that need completion
1414 * and we want to auto-free the connection when all
1415 * requests have been completed.
1417 if (TAILQ_FIRST(&evcon->requests) == NULL
1418 && (evcon->flags & EVHTTP_CON_OUTGOING)
1419 && (evcon->flags & EVHTTP_CON_AUTOFREE)) {
1420 evhttp_connection_free(evcon);
1425 if (what & BEV_EVENT_TIMEOUT) {
1426 evhttp_connection_fail_(evcon, EVREQ_HTTP_TIMEOUT);
1427 } else if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
1428 evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
1429 } else if (what == BEV_EVENT_CONNECTED) {
1431 evhttp_connection_fail_(evcon, EVREQ_HTTP_BUFFER_ERROR);
1436 * Event callback for asynchronous connection attempt.
1439 evhttp_connection_cb(struct bufferevent *bufev, short what, void *arg)
1441 struct evhttp_connection *evcon = arg;
1443 ev_socklen_t errsz = sizeof(error);
1444 socklen_t conn_address_len = sizeof(*evcon->conn_address);
1446 if (evcon->fd == -1)
1447 evcon->fd = bufferevent_getfd(bufev);
1449 if (!(what & BEV_EVENT_CONNECTED)) {
1450 /* some operating systems return ECONNREFUSED immediately
1451 * when connecting to a local address. the cleanup is going
1452 * to reschedule this function call.
1455 if (errno == ECONNREFUSED)
1458 evhttp_error_cb(bufev, what, arg);
1462 if (evcon->fd == -1) {
1463 event_debug(("%s: bufferevent_getfd returned -1",
1468 /* Check if the connection completed */
1469 if (getsockopt(evcon->fd, SOL_SOCKET, SO_ERROR, (void*)&error,
1471 event_debug(("%s: getsockopt for \"%s:%d\" on "EV_SOCK_FMT,
1472 __func__, evcon->address, evcon->port,
1473 EV_SOCK_ARG(evcon->fd)));
1478 event_debug(("%s: connect failed for \"%s:%d\" on "
1480 __func__, evcon->address, evcon->port,
1481 EV_SOCK_ARG(evcon->fd),
1482 evutil_socket_error_to_string(error)));
1486 /* We are connected to the server now */
1487 event_debug(("%s: connected to \"%s:%d\" on "EV_SOCK_FMT"\n",
1488 __func__, evcon->address, evcon->port,
1489 EV_SOCK_ARG(evcon->fd)));
1491 /* Reset the retry count as we were successful in connecting */
1492 evcon->retry_cnt = 0;
1493 evcon->state = EVCON_IDLE;
1495 if (!evcon->conn_address) {
1496 evcon->conn_address = mm_malloc(sizeof(*evcon->conn_address));
1498 if (getpeername(evcon->fd, (struct sockaddr *)evcon->conn_address, &conn_address_len)) {
1499 mm_free(evcon->conn_address);
1500 evcon->conn_address = NULL;
1503 /* reset the bufferevent cbs */
1504 bufferevent_setcb(evcon->bufev,
1510 if (!evutil_timerisset(&evcon->timeout)) {
1511 const struct timeval read_tv = { HTTP_READ_TIMEOUT, 0 };
1512 const struct timeval write_tv = { HTTP_WRITE_TIMEOUT, 0 };
1513 bufferevent_set_timeouts(evcon->bufev, &read_tv, &write_tv);
1515 bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
1518 /* try to start requests that have queued up on this connection */
1519 evhttp_request_dispatch(evcon);
1523 evhttp_connection_cb_cleanup(evcon);
1527 * Check if we got a valid response code.
1531 evhttp_valid_response_code(int code)
1540 evhttp_parse_http_version(const char *version, struct evhttp_request *req)
1544 int n = sscanf(version, "HTTP/%d.%d%c", &major, &minor, &ch);
1545 if (n != 2 || major > 1) {
1546 event_debug(("%s: bad version %s on message %p from %s",
1547 __func__, version, req, req->remote_host));
1555 /* Parses the status line of a web server */
1558 evhttp_parse_response_line(struct evhttp_request *req, char *line)
1562 const char *readable = "";
1564 protocol = strsep(&line, " ");
1567 number = strsep(&line, " ");
1571 if (evhttp_parse_http_version(protocol, req) < 0)
1574 req->response_code = atoi(number);
1575 if (!evhttp_valid_response_code(req->response_code)) {
1576 event_debug(("%s: bad response code \"%s\"",
1581 if ((req->response_code_line = mm_strdup(readable)) == NULL) {
1582 event_warn("%s: strdup", __func__);
1589 /* Parse the first line of a HTTP request */
1592 evhttp_parse_request_line(struct evhttp_request *req, char *line)
1597 const char *hostname;
1600 enum evhttp_cmd_type type;
1602 /* Parse the request line */
1603 method = strsep(&line, " ");
1606 uri = strsep(&line, " ");
1609 version = strsep(&line, " ");
1613 method_len = (uri - method) - 1;
1614 type = EVHTTP_REQ_UNKNOWN_;
1617 switch (method_len) {
1619 /* The length of the method string is 3, meaning it can only be one of two methods: GET or PUT */
1621 /* Since both GET and PUT share the same character 'T' at the end,
1622 * if the string doesn't have 'T', we can immediately determine this
1623 * is an invalid HTTP method */
1625 if (method[2] != 'T') {
1631 /* This first byte is 'G', so make sure the next byte is
1632 * 'E', if it isn't then this isn't a valid method */
1634 if (method[1] == 'E') {
1635 type = EVHTTP_REQ_GET;
1640 /* First byte is P, check second byte for 'U', if not,
1641 * we know it's an invalid method */
1642 if (method[1] == 'U') {
1643 type = EVHTTP_REQ_PUT;
1651 /* The method length is 4 bytes, leaving only the methods "POST" and "HEAD" */
1654 if (method[3] == 'T' && method[2] == 'S' && method[1] == 'O') {
1655 type = EVHTTP_REQ_POST;
1659 if (method[3] == 'D' && method[2] == 'A' && method[1] == 'E') {
1660 type = EVHTTP_REQ_HEAD;
1668 /* Method length is 5 bytes, which can only encompass PATCH and TRACE */
1671 if (method[4] == 'H' && method[3] == 'C' && method[2] == 'T' && method[1] == 'A') {
1672 type = EVHTTP_REQ_PATCH;
1676 if (method[4] == 'E' && method[3] == 'C' && method[2] == 'A' && method[1] == 'R') {
1677 type = EVHTTP_REQ_TRACE;
1686 /* Method length is 6, only valid method 6 bytes in length is DELEte */
1688 /* If the first byte isn't 'D' then it's invalid */
1689 if (*method != 'D') {
1693 if (method[5] == 'E' && method[4] == 'T' && method[3] == 'E' && method[2] == 'L' && method[1] == 'E') {
1694 type = EVHTTP_REQ_DELETE;
1699 /* Method length is 7, only valid methods are "OPTIONS" and "CONNECT" */
1702 if (method[6] == 'S' && method[5] == 'N' && method[4] == 'O' &&
1703 method[3] == 'I' && method[2] == 'T' && method[1] == 'P') {
1704 type = EVHTTP_REQ_OPTIONS;
1709 if (method[6] == 'T' && method[5] == 'C' && method[4] == 'E' &&
1710 method[3] == 'N' && method[2] == 'N' && method[1] == 'O') {
1711 type = EVHTTP_REQ_CONNECT;
1721 if ((int)type == EVHTTP_REQ_UNKNOWN_) {
1722 event_debug(("%s: bad method %s on request %p from %s",
1723 __func__, method, req, req->remote_host));
1724 /* No error yet; we'll give a better error later when
1725 * we see that req->type is unsupported. */
1730 if (evhttp_parse_http_version(version, req) < 0)
1733 if ((req->uri = mm_strdup(uri)) == NULL) {
1734 event_debug(("%s: mm_strdup", __func__));
1738 if ((req->uri_elems = evhttp_uri_parse_with_flags(req->uri,
1739 EVHTTP_URI_NONCONFORMANT)) == NULL) {
1743 /* If we have an absolute-URI, check to see if it is an http request
1744 for a known vhost or server alias. If we don't know about this
1745 host, we consider it a proxy request. */
1746 scheme = evhttp_uri_get_scheme(req->uri_elems);
1747 hostname = evhttp_uri_get_host(req->uri_elems);
1748 if (scheme && (!evutil_ascii_strcasecmp(scheme, "http") ||
1749 !evutil_ascii_strcasecmp(scheme, "https")) &&
1751 !evhttp_find_vhost(req->evcon->http_server, NULL, hostname))
1752 req->flags |= EVHTTP_PROXY_REQUEST;
1758 evhttp_find_header(const struct evkeyvalq *headers, const char *key)
1760 struct evkeyval *header;
1762 TAILQ_FOREACH(header, headers, next) {
1763 if (evutil_ascii_strcasecmp(header->key, key) == 0)
1764 return (header->value);
1771 evhttp_clear_headers(struct evkeyvalq *headers)
1773 struct evkeyval *header;
1775 for (header = TAILQ_FIRST(headers);
1777 header = TAILQ_FIRST(headers)) {
1778 TAILQ_REMOVE(headers, header, next);
1779 mm_free(header->key);
1780 mm_free(header->value);
1786 * Returns 0, if the header was successfully removed.
1787 * Returns -1, if the header could not be found.
1791 evhttp_remove_header(struct evkeyvalq *headers, const char *key)
1793 struct evkeyval *header;
1795 TAILQ_FOREACH(header, headers, next) {
1796 if (evutil_ascii_strcasecmp(header->key, key) == 0)
1803 /* Free and remove the header that we found */
1804 TAILQ_REMOVE(headers, header, next);
1805 mm_free(header->key);
1806 mm_free(header->value);
1813 evhttp_header_is_valid_value(const char *value)
1815 const char *p = value;
1817 while ((p = strpbrk(p, "\r\n")) != NULL) {
1818 /* we really expect only one new line */
1819 p += strspn(p, "\r\n");
1820 /* we expect a space or tab for continuation */
1821 if (*p != ' ' && *p != '\t')
1828 evhttp_add_header(struct evkeyvalq *headers,
1829 const char *key, const char *value)
1831 event_debug(("%s: key: %s val: %s\n", __func__, key, value));
1833 if (strchr(key, '\r') != NULL || strchr(key, '\n') != NULL) {
1834 /* drop illegal headers */
1835 event_debug(("%s: dropping illegal header key\n", __func__));
1839 if (!evhttp_header_is_valid_value(value)) {
1840 event_debug(("%s: dropping illegal header value\n", __func__));
1844 return (evhttp_add_header_internal(headers, key, value));
1848 evhttp_add_header_internal(struct evkeyvalq *headers,
1849 const char *key, const char *value)
1851 struct evkeyval *header = mm_calloc(1, sizeof(struct evkeyval));
1852 if (header == NULL) {
1853 event_warn("%s: calloc", __func__);
1856 if ((header->key = mm_strdup(key)) == NULL) {
1858 event_warn("%s: strdup", __func__);
1861 if ((header->value = mm_strdup(value)) == NULL) {
1862 mm_free(header->key);
1864 event_warn("%s: strdup", __func__);
1868 TAILQ_INSERT_TAIL(headers, header, next);
1874 * Parses header lines from a request or a response into the specified
1875 * request object given an event buffer.
1878 * DATA_CORRUPTED on error
1879 * MORE_DATA_EXPECTED when we need to read more headers
1880 * ALL_DATA_READ when all headers have been read.
1883 enum message_read_status
1884 evhttp_parse_firstline_(struct evhttp_request *req, struct evbuffer *buffer)
1887 enum message_read_status status = ALL_DATA_READ;
1891 line = evbuffer_readln(buffer, &line_length, EVBUFFER_EOL_CRLF);
1893 if (req->evcon != NULL &&
1894 evbuffer_get_length(buffer) > req->evcon->max_headers_size)
1895 return (DATA_TOO_LONG);
1897 return (MORE_DATA_EXPECTED);
1900 if (req->evcon != NULL &&
1901 line_length > req->evcon->max_headers_size) {
1903 return (DATA_TOO_LONG);
1906 req->headers_size = line_length;
1908 switch (req->kind) {
1909 case EVHTTP_REQUEST:
1910 if (evhttp_parse_request_line(req, line) == -1)
1911 status = DATA_CORRUPTED;
1913 case EVHTTP_RESPONSE:
1914 if (evhttp_parse_response_line(req, line) == -1)
1915 status = DATA_CORRUPTED;
1918 status = DATA_CORRUPTED;
1926 evhttp_append_to_last_header(struct evkeyvalq *headers, char *line)
1928 struct evkeyval *header = TAILQ_LAST(headers, evkeyvalq);
1930 size_t old_len, line_len;
1935 old_len = strlen(header->value);
1937 /* Strip space from start and end of line. */
1938 while (*line == ' ' || *line == '\t')
1940 evutil_rtrim_lws_(line);
1942 line_len = strlen(line);
1944 newval = mm_realloc(header->value, old_len + line_len + 2);
1948 newval[old_len] = ' ';
1949 memcpy(newval + old_len + 1, line, line_len + 1);
1950 header->value = newval;
1955 enum message_read_status
1956 evhttp_parse_headers_(struct evhttp_request *req, struct evbuffer* buffer)
1958 enum message_read_status errcode = DATA_CORRUPTED;
1960 enum message_read_status status = MORE_DATA_EXPECTED;
1962 struct evkeyvalq* headers = req->input_headers;
1964 while ((line = evbuffer_readln(buffer, &line_length, EVBUFFER_EOL_CRLF))
1966 char *skey, *svalue;
1968 req->headers_size += line_length;
1970 if (req->evcon != NULL &&
1971 req->headers_size > req->evcon->max_headers_size) {
1972 errcode = DATA_TOO_LONG;
1976 if (*line == '\0') { /* Last header - Done */
1977 status = ALL_DATA_READ;
1982 /* Check if this is a continuation line */
1983 if (*line == ' ' || *line == '\t') {
1984 if (evhttp_append_to_last_header(headers, line) == -1)
1990 /* Processing of header lines */
1992 skey = strsep(&svalue, ":");
1996 svalue += strspn(svalue, " ");
1997 evutil_rtrim_lws_(svalue);
1999 if (evhttp_add_header(headers, skey, svalue) == -1)
2005 if (status == MORE_DATA_EXPECTED) {
2006 if (req->evcon != NULL &&
2007 req->headers_size + evbuffer_get_length(buffer) > req->evcon->max_headers_size)
2008 return (DATA_TOO_LONG);
2019 evhttp_get_body_length(struct evhttp_request *req)
2021 struct evkeyvalq *headers = req->input_headers;
2022 const char *content_length;
2023 const char *connection;
2025 content_length = evhttp_find_header(headers, "Content-Length");
2026 connection = evhttp_find_header(headers, "Connection");
2028 if (content_length == NULL && connection == NULL)
2030 else if (content_length == NULL &&
2031 evutil_ascii_strcasecmp(connection, "Close") != 0) {
2032 /* Bad combination, we don't know when it will end */
2033 event_warnx("%s: we got no content length, but the "
2034 "server wants to keep the connection open: %s.",
2035 __func__, connection);
2037 } else if (content_length == NULL) {
2041 ev_int64_t ntoread = evutil_strtoll(content_length, &endp, 10);
2042 if (*content_length == '\0' || *endp != '\0' || ntoread < 0) {
2043 event_debug(("%s: illegal content length: %s",
2044 __func__, content_length));
2047 req->ntoread = ntoread;
2050 event_debug(("%s: bytes to read: "EV_I64_FMT" (in buffer "EV_SIZE_FMT")\n",
2051 __func__, EV_I64_ARG(req->ntoread),
2052 EV_SIZE_ARG(evbuffer_get_length(bufferevent_get_input(req->evcon->bufev)))));
2058 evhttp_method_may_have_body(enum evhttp_cmd_type type)
2061 case EVHTTP_REQ_POST:
2062 case EVHTTP_REQ_PUT:
2063 case EVHTTP_REQ_PATCH:
2065 case EVHTTP_REQ_TRACE:
2067 /* XXX May any of the below methods have a body? */
2068 case EVHTTP_REQ_GET:
2069 case EVHTTP_REQ_HEAD:
2070 case EVHTTP_REQ_DELETE:
2071 case EVHTTP_REQ_OPTIONS:
2072 case EVHTTP_REQ_CONNECT:
2080 evhttp_get_body(struct evhttp_connection *evcon, struct evhttp_request *req)
2082 const char *xfer_enc;
2084 /* If this is a request without a body, then we are done */
2085 if (req->kind == EVHTTP_REQUEST &&
2086 !evhttp_method_may_have_body(req->type)) {
2087 evhttp_connection_done(evcon);
2090 evcon->state = EVCON_READING_BODY;
2091 xfer_enc = evhttp_find_header(req->input_headers, "Transfer-Encoding");
2092 if (xfer_enc != NULL && evutil_ascii_strcasecmp(xfer_enc, "chunked") == 0) {
2096 if (evhttp_get_body_length(req) == -1) {
2097 evhttp_connection_fail_(evcon,
2098 EVREQ_HTTP_INVALID_HEADER);
2101 if (req->kind == EVHTTP_REQUEST && req->ntoread < 1) {
2102 /* An incoming request with no content-length and no
2103 * transfer-encoding has no body. */
2104 evhttp_connection_done(evcon);
2109 /* Should we send a 100 Continue status line? */
2110 if (req->kind == EVHTTP_REQUEST && REQ_VERSION_ATLEAST(req, 1, 1)) {
2113 expect = evhttp_find_header(req->input_headers, "Expect");
2115 if (!evutil_ascii_strcasecmp(expect, "100-continue")) {
2116 /* XXX It would be nice to do some sanity
2117 checking here. Does the resource exist?
2118 Should the resource accept post requests? If
2119 no, we should respond with an error. For
2120 now, just optimistically tell the client to
2121 send their message body. */
2122 if (req->ntoread > 0) {
2123 /* ntoread is ev_int64_t, max_body_size is ev_uint64_t */
2124 if ((req->evcon->max_body_size <= EV_INT64_MAX) && (ev_uint64_t)req->ntoread > req->evcon->max_body_size) {
2125 evhttp_send_error(req, HTTP_ENTITYTOOLARGE, NULL);
2129 if (!evbuffer_get_length(bufferevent_get_input(evcon->bufev)))
2130 evhttp_send_continue(evcon, req);
2132 evhttp_send_error(req, HTTP_EXPECTATIONFAILED,
2139 evhttp_read_body(evcon, req);
2140 /* note the request may have been freed in evhttp_read_body */
2144 evhttp_read_firstline(struct evhttp_connection *evcon,
2145 struct evhttp_request *req)
2147 enum message_read_status res;
2149 res = evhttp_parse_firstline_(req, bufferevent_get_input(evcon->bufev));
2150 if (res == DATA_CORRUPTED || res == DATA_TOO_LONG) {
2151 /* Error while reading, terminate */
2152 event_debug(("%s: bad header lines on "EV_SOCK_FMT"\n",
2153 __func__, EV_SOCK_ARG(evcon->fd)));
2154 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2156 } else if (res == MORE_DATA_EXPECTED) {
2157 /* Need more header lines */
2161 evcon->state = EVCON_READING_HEADERS;
2162 evhttp_read_header(evcon, req);
2166 evhttp_read_header(struct evhttp_connection *evcon,
2167 struct evhttp_request *req)
2169 enum message_read_status res;
2170 evutil_socket_t fd = evcon->fd;
2172 res = evhttp_parse_headers_(req, bufferevent_get_input(evcon->bufev));
2173 if (res == DATA_CORRUPTED || res == DATA_TOO_LONG) {
2174 /* Error while reading, terminate */
2175 event_debug(("%s: bad header lines on "EV_SOCK_FMT"\n",
2176 __func__, EV_SOCK_ARG(fd)));
2177 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2179 } else if (res == MORE_DATA_EXPECTED) {
2180 /* Need more header lines */
2184 /* Disable reading for now */
2185 bufferevent_disable(evcon->bufev, EV_READ);
2187 /* Callback can shut down connection with negative return value */
2188 if (req->header_cb != NULL) {
2189 if ((*req->header_cb)(req, req->cb_arg) < 0) {
2190 evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
2195 /* Done reading headers, do the real work */
2196 switch (req->kind) {
2197 case EVHTTP_REQUEST:
2198 event_debug(("%s: checking for post data on "EV_SOCK_FMT"\n",
2199 __func__, EV_SOCK_ARG(fd)));
2200 evhttp_get_body(evcon, req);
2201 /* note the request may have been freed in evhttp_get_body */
2204 case EVHTTP_RESPONSE:
2205 /* Start over if we got a 100 Continue response. */
2206 if (req->response_code == 100) {
2207 evhttp_start_read_(evcon);
2210 if (!evhttp_response_needs_body(req)) {
2211 event_debug(("%s: skipping body for code %d\n",
2212 __func__, req->response_code));
2213 evhttp_connection_done(evcon);
2215 event_debug(("%s: start of read body for %s on "
2217 __func__, req->remote_host, EV_SOCK_ARG(fd)));
2218 evhttp_get_body(evcon, req);
2219 /* note the request may have been freed in
2220 * evhttp_get_body */
2225 event_warnx("%s: bad header on "EV_SOCK_FMT, __func__,
2227 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2230 /* request may have been freed above */
2234 * Creates a TCP connection to the specified port and executes a callback
2235 * when finished. Failure or success is indicate by the passed connection
2238 * Although this interface accepts a hostname, it is intended to take
2239 * only numeric hostnames so that non-blocking DNS resolution can
2243 struct evhttp_connection *
2244 evhttp_connection_new(const char *address, unsigned short port)
2246 return (evhttp_connection_base_new(NULL, NULL, address, port));
2249 struct evhttp_connection *
2250 evhttp_connection_base_bufferevent_new(struct event_base *base, struct evdns_base *dnsbase, struct bufferevent* bev,
2251 const char *address, unsigned short port)
2253 struct evhttp_connection *evcon = NULL;
2255 event_debug(("Attempting connection to %s:%d\n", address, port));
2257 if ((evcon = mm_calloc(1, sizeof(struct evhttp_connection))) == NULL) {
2258 event_warn("%s: calloc failed", __func__);
2265 evcon->max_headers_size = EV_SIZE_MAX;
2266 evcon->max_body_size = EV_SIZE_MAX;
2268 evutil_timerclear(&evcon->timeout);
2269 evcon->retry_cnt = evcon->retry_max = 0;
2271 if ((evcon->address = mm_strdup(address)) == NULL) {
2272 event_warn("%s: strdup failed", __func__);
2277 if (!(bev = bufferevent_socket_new(base, -1, 0))) {
2278 event_warn("%s: bufferevent_socket_new failed", __func__);
2283 bufferevent_setcb(bev, evhttp_read_cb, evhttp_write_cb, evhttp_error_cb, evcon);
2286 evcon->state = EVCON_DISCONNECTED;
2287 TAILQ_INIT(&evcon->requests);
2289 evcon->initial_retry_timeout.tv_sec = 2;
2290 evcon->initial_retry_timeout.tv_usec = 0;
2294 if (bufferevent_get_base(bev) != base)
2295 bufferevent_base_set(base, evcon->bufev);
2298 event_deferred_cb_init_(
2299 &evcon->read_more_deferred_cb,
2300 bufferevent_get_priority(bev),
2301 evhttp_deferred_read_cb, evcon);
2303 evcon->dns_base = dnsbase;
2304 evcon->ai_family = AF_UNSPEC;
2310 evhttp_connection_free(evcon);
2314 struct bufferevent* evhttp_connection_get_bufferevent(struct evhttp_connection *evcon)
2316 return evcon->bufev;
2320 evhttp_connection_get_server(struct evhttp_connection *evcon)
2322 return evcon->http_server;
2325 struct evhttp_connection *
2326 evhttp_connection_base_new(struct event_base *base, struct evdns_base *dnsbase,
2327 const char *address, unsigned short port)
2329 return evhttp_connection_base_bufferevent_new(base, dnsbase, NULL, address, port);
2332 void evhttp_connection_set_family(struct evhttp_connection *evcon,
2335 evcon->ai_family = family;
2339 evhttp_connection_set_base(struct evhttp_connection *evcon,
2340 struct event_base *base)
2342 EVUTIL_ASSERT(evcon->base == NULL);
2343 EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED);
2345 bufferevent_base_set(base, evcon->bufev);
2349 evhttp_connection_set_timeout(struct evhttp_connection *evcon,
2350 int timeout_in_secs)
2352 if (timeout_in_secs == -1)
2353 evhttp_connection_set_timeout_tv(evcon, NULL);
2356 tv.tv_sec = timeout_in_secs;
2358 evhttp_connection_set_timeout_tv(evcon, &tv);
2363 evhttp_connection_set_timeout_tv(struct evhttp_connection *evcon,
2364 const struct timeval* tv)
2367 evcon->timeout = *tv;
2368 bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
2370 const struct timeval read_tv = { HTTP_READ_TIMEOUT, 0 };
2371 const struct timeval write_tv = { HTTP_WRITE_TIMEOUT, 0 };
2372 evutil_timerclear(&evcon->timeout);
2373 bufferevent_set_timeouts(evcon->bufev, &read_tv, &write_tv);
2378 evhttp_connection_set_initial_retry_tv(struct evhttp_connection *evcon,
2379 const struct timeval *tv)
2382 evcon->initial_retry_timeout = *tv;
2384 evutil_timerclear(&evcon->initial_retry_timeout);
2385 evcon->initial_retry_timeout.tv_sec = 2;
2390 evhttp_connection_set_retries(struct evhttp_connection *evcon,
2393 evcon->retry_max = retry_max;
2397 evhttp_connection_set_closecb(struct evhttp_connection *evcon,
2398 void (*cb)(struct evhttp_connection *, void *), void *cbarg)
2400 evcon->closecb = cb;
2401 evcon->closecb_arg = cbarg;
2405 evhttp_connection_get_peer(struct evhttp_connection *evcon,
2406 char **address, ev_uint16_t *port)
2408 *address = evcon->address;
2409 *port = evcon->port;
2412 const struct sockaddr*
2413 evhttp_connection_get_addr(struct evhttp_connection *evcon)
2415 return (struct sockaddr *)evcon->conn_address;
2419 evhttp_connection_connect_(struct evhttp_connection *evcon)
2421 int old_state = evcon->state;
2423 if (evcon->state == EVCON_CONNECTING)
2426 evhttp_connection_reset_(evcon);
2428 EVUTIL_ASSERT(!(evcon->flags & EVHTTP_CON_INCOMING));
2429 evcon->flags |= EVHTTP_CON_OUTGOING;
2431 if (evcon->bind_address || evcon->bind_port) {
2432 evcon->fd = bind_socket(
2433 evcon->bind_address, evcon->bind_port, 0 /*reuse*/);
2434 if (evcon->fd == -1) {
2435 event_debug(("%s: failed to bind to \"%s\"",
2436 __func__, evcon->bind_address));
2440 bufferevent_setfd(evcon->bufev, evcon->fd);
2442 bufferevent_setfd(evcon->bufev, -1);
2445 /* Set up a callback for successful connection setup */
2446 bufferevent_setcb(evcon->bufev,
2447 NULL /* evhttp_read_cb */,
2448 NULL /* evhttp_write_cb */,
2449 evhttp_connection_cb,
2451 if (!evutil_timerisset(&evcon->timeout)) {
2452 const struct timeval conn_tv = { HTTP_CONNECT_TIMEOUT, 0 };
2453 bufferevent_set_timeouts(evcon->bufev, NULL, &conn_tv);
2455 bufferevent_set_timeouts(evcon->bufev, NULL, &evcon->timeout);
2457 /* make sure that we get a write callback */
2458 bufferevent_enable(evcon->bufev, EV_WRITE);
2460 evcon->state = EVCON_CONNECTING;
2462 if (bufferevent_socket_connect_hostname(evcon->bufev, evcon->dns_base,
2463 evcon->ai_family, evcon->address, evcon->port) < 0) {
2464 evcon->state = old_state;
2465 event_sock_warn(evcon->fd, "%s: connection to \"%s\" failed",
2466 __func__, evcon->address);
2467 /* some operating systems return ECONNREFUSED immediately
2468 * when connecting to a local address. the cleanup is going
2469 * to reschedule this function call.
2471 evhttp_connection_cb_cleanup(evcon);
2479 * Starts an HTTP request on the provided evhttp_connection object.
2480 * If the connection object is not connected to the web server already,
2481 * this will start the connection.
2485 evhttp_make_request(struct evhttp_connection *evcon,
2486 struct evhttp_request *req,
2487 enum evhttp_cmd_type type, const char *uri)
2489 /* We are making a request */
2490 req->kind = EVHTTP_REQUEST;
2492 if (req->uri != NULL)
2494 if ((req->uri = mm_strdup(uri)) == NULL) {
2495 event_warn("%s: strdup", __func__);
2496 evhttp_request_free(req);
2500 /* Set the protocol version if it is not supplied */
2501 if (!req->major && !req->minor) {
2506 EVUTIL_ASSERT(req->evcon == NULL);
2508 EVUTIL_ASSERT(!(req->flags & EVHTTP_REQ_OWN_CONNECTION));
2510 TAILQ_INSERT_TAIL(&evcon->requests, req, next);
2512 /* If the connection object is not connected; make it so */
2513 if (!evhttp_connected(evcon)) {
2514 int res = evhttp_connection_connect_(evcon);
2515 /* evhttp_connection_fail_(), which is called through
2516 * evhttp_connection_connect_(), assumes that req lies in
2517 * evcon->requests. Thus, enqueue the request in advance and
2518 * remove it in the error case. */
2520 TAILQ_REMOVE(&evcon->requests, req, next);
2526 * If it's connected already and we are the first in the queue,
2527 * then we can dispatch this request immediately. Otherwise, it
2528 * will be dispatched once the pending requests are completed.
2530 if (TAILQ_FIRST(&evcon->requests) == req)
2531 evhttp_request_dispatch(evcon);
2537 evhttp_cancel_request(struct evhttp_request *req)
2539 struct evhttp_connection *evcon = req->evcon;
2540 if (evcon != NULL) {
2541 /* We need to remove it from the connection */
2542 if (TAILQ_FIRST(&evcon->requests) == req) {
2543 /* it's currently being worked on, so reset
2546 evhttp_connection_fail_(evcon,
2547 EVREQ_HTTP_REQUEST_CANCEL);
2549 /* connection fail freed the request */
2552 /* otherwise, we can just remove it from the
2555 TAILQ_REMOVE(&evcon->requests, req, next);
2559 evhttp_request_free(req);
2563 * Reads data from file descriptor into request structure
2564 * Request structure needs to be set up correctly.
2568 evhttp_start_read_(struct evhttp_connection *evcon)
2570 /* Set up an event to read the headers */
2571 bufferevent_disable(evcon->bufev, EV_WRITE);
2572 bufferevent_enable(evcon->bufev, EV_READ);
2573 evcon->state = EVCON_READING_FIRSTLINE;
2574 /* Reset the bufferevent callbacks */
2575 bufferevent_setcb(evcon->bufev,
2581 /* If there's still data pending, process it next time through the
2582 * loop. Don't do it now; that could get recusive. */
2583 if (evbuffer_get_length(bufferevent_get_input(evcon->bufev))) {
2584 event_deferred_cb_schedule_(get_deferred_queue(evcon),
2585 &evcon->read_more_deferred_cb);
2590 evhttp_send_done(struct evhttp_connection *evcon, void *arg)
2593 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
2594 TAILQ_REMOVE(&evcon->requests, req, next);
2596 if (req->on_complete_cb != NULL) {
2597 req->on_complete_cb(req, req->on_complete_cb_arg);
2601 (REQ_VERSION_BEFORE(req, 1, 1) &&
2602 !evhttp_is_connection_keepalive(req->input_headers))||
2603 evhttp_is_connection_close(req->flags, req->input_headers) ||
2604 evhttp_is_connection_close(req->flags, req->output_headers);
2606 EVUTIL_ASSERT(req->flags & EVHTTP_REQ_OWN_CONNECTION);
2607 evhttp_request_free(req);
2610 evhttp_connection_free(evcon);
2614 /* we have a persistent connection; try to accept another request. */
2615 if (evhttp_associate_new_request_with_connection(evcon) == -1) {
2616 evhttp_connection_free(evcon);
2621 * Returns an error page.
2625 evhttp_send_error(struct evhttp_request *req, int error, const char *reason)
2628 #define ERR_FORMAT "<HTML><HEAD>\n" \
2629 "<TITLE>%d %s</TITLE>\n" \
2634 struct evbuffer *buf = evbuffer_new();
2636 /* if we cannot allocate memory; we just drop the connection */
2637 evhttp_connection_free(req->evcon);
2640 if (reason == NULL) {
2641 reason = evhttp_response_phrase_internal(error);
2644 evhttp_response_code_(req, error, reason);
2646 evbuffer_add_printf(buf, ERR_FORMAT, error, reason, reason);
2648 evhttp_send_page_(req, buf);
2654 /* Requires that headers and response code are already set up */
2657 evhttp_send(struct evhttp_request *req, struct evbuffer *databuf)
2659 struct evhttp_connection *evcon = req->evcon;
2661 if (evcon == NULL) {
2662 evhttp_request_free(req);
2666 EVUTIL_ASSERT(TAILQ_FIRST(&evcon->requests) == req);
2668 /* we expect no more calls form the user on this request */
2671 /* xxx: not sure if we really should expose the data buffer this way */
2672 if (databuf != NULL)
2673 evbuffer_add_buffer(req->output_buffer, databuf);
2675 /* Adds headers to the response */
2676 evhttp_make_header(evcon, req);
2678 evhttp_write_buffer(evcon, evhttp_send_done, NULL);
2682 evhttp_send_reply(struct evhttp_request *req, int code, const char *reason,
2683 struct evbuffer *databuf)
2685 evhttp_response_code_(req, code, reason);
2687 evhttp_send(req, databuf);
2691 evhttp_send_reply_start(struct evhttp_request *req, int code,
2694 evhttp_response_code_(req, code, reason);
2695 if (evhttp_find_header(req->output_headers, "Content-Length") == NULL &&
2696 REQ_VERSION_ATLEAST(req, 1, 1) &&
2697 evhttp_response_needs_body(req)) {
2699 * prefer HTTP/1.1 chunked encoding to closing the connection;
2700 * note RFC 2616 section 4.4 forbids it with Content-Length:
2701 * and it's not necessary then anyway.
2703 evhttp_add_header(req->output_headers, "Transfer-Encoding",
2709 evhttp_make_header(req->evcon, req);
2710 evhttp_write_buffer(req->evcon, NULL, NULL);
2714 evhttp_send_reply_chunk_with_cb(struct evhttp_request *req, struct evbuffer *databuf,
2715 void (*cb)(struct evhttp_connection *, void *), void *arg)
2717 struct evhttp_connection *evcon = req->evcon;
2718 struct evbuffer *output;
2723 output = bufferevent_get_output(evcon->bufev);
2725 if (evbuffer_get_length(databuf) == 0)
2727 if (!evhttp_response_needs_body(req))
2730 evbuffer_add_printf(output, "%x\r\n",
2731 (unsigned)evbuffer_get_length(databuf));
2733 evbuffer_add_buffer(output, databuf);
2735 evbuffer_add(output, "\r\n", 2);
2737 evhttp_write_buffer(evcon, cb, arg);
2741 evhttp_send_reply_chunk(struct evhttp_request *req, struct evbuffer *databuf)
2743 evhttp_send_reply_chunk_with_cb(req, databuf, NULL, NULL);
2746 evhttp_send_reply_end(struct evhttp_request *req)
2748 struct evhttp_connection *evcon = req->evcon;
2749 struct evbuffer *output;
2751 if (evcon == NULL) {
2752 evhttp_request_free(req);
2756 output = bufferevent_get_output(evcon->bufev);
2758 /* we expect no more calls form the user on this request */
2762 evbuffer_add(output, "0\r\n\r\n", 5);
2763 evhttp_write_buffer(req->evcon, evhttp_send_done, NULL);
2765 } else if (evbuffer_get_length(output) == 0) {
2766 /* let the connection know that we are done with the request */
2767 evhttp_send_done(evcon, NULL);
2769 /* make the callback execute after all data has been written */
2770 evcon->cb = evhttp_send_done;
2771 evcon->cb_arg = NULL;
2775 static const char *informational_phrases[] = {
2776 /* 100 */ "Continue",
2777 /* 101 */ "Switching Protocols"
2780 static const char *success_phrases[] = {
2782 /* 201 */ "Created",
2783 /* 202 */ "Accepted",
2784 /* 203 */ "Non-Authoritative Information",
2785 /* 204 */ "No Content",
2786 /* 205 */ "Reset Content",
2787 /* 206 */ "Partial Content"
2790 static const char *redirection_phrases[] = {
2791 /* 300 */ "Multiple Choices",
2792 /* 301 */ "Moved Permanently",
2794 /* 303 */ "See Other",
2795 /* 304 */ "Not Modified",
2796 /* 305 */ "Use Proxy",
2797 /* 307 */ "Temporary Redirect"
2800 static const char *client_error_phrases[] = {
2801 /* 400 */ "Bad Request",
2802 /* 401 */ "Unauthorized",
2803 /* 402 */ "Payment Required",
2804 /* 403 */ "Forbidden",
2805 /* 404 */ "Not Found",
2806 /* 405 */ "Method Not Allowed",
2807 /* 406 */ "Not Acceptable",
2808 /* 407 */ "Proxy Authentication Required",
2809 /* 408 */ "Request Time-out",
2810 /* 409 */ "Conflict",
2812 /* 411 */ "Length Required",
2813 /* 412 */ "Precondition Failed",
2814 /* 413 */ "Request Entity Too Large",
2815 /* 414 */ "Request-URI Too Large",
2816 /* 415 */ "Unsupported Media Type",
2817 /* 416 */ "Requested range not satisfiable",
2818 /* 417 */ "Expectation Failed"
2821 static const char *server_error_phrases[] = {
2822 /* 500 */ "Internal Server Error",
2823 /* 501 */ "Not Implemented",
2824 /* 502 */ "Bad Gateway",
2825 /* 503 */ "Service Unavailable",
2826 /* 504 */ "Gateway Time-out",
2827 /* 505 */ "HTTP Version not supported"
2830 struct response_class {
2832 size_t num_responses;
2833 const char **responses;
2837 #define MEMBERSOF(x) (sizeof(x)/sizeof(x[0]))
2840 static const struct response_class response_classes[] = {
2841 /* 1xx */ { "Informational", MEMBERSOF(informational_phrases), informational_phrases },
2842 /* 2xx */ { "Success", MEMBERSOF(success_phrases), success_phrases },
2843 /* 3xx */ { "Redirection", MEMBERSOF(redirection_phrases), redirection_phrases },
2844 /* 4xx */ { "Client Error", MEMBERSOF(client_error_phrases), client_error_phrases },
2845 /* 5xx */ { "Server Error", MEMBERSOF(server_error_phrases), server_error_phrases }
2849 evhttp_response_phrase_internal(int code)
2851 int klass = code / 100 - 1;
2852 int subcode = code % 100;
2854 /* Unknown class - can't do any better here */
2855 if (klass < 0 || klass >= (int) MEMBERSOF(response_classes))
2856 return "Unknown Status Class";
2858 /* Unknown sub-code, return class name at least */
2859 if (subcode >= (int) response_classes[klass].num_responses)
2860 return response_classes[klass].name;
2862 return response_classes[klass].responses[subcode];
2866 evhttp_response_code_(struct evhttp_request *req, int code, const char *reason)
2868 req->kind = EVHTTP_RESPONSE;
2869 req->response_code = code;
2870 if (req->response_code_line != NULL)
2871 mm_free(req->response_code_line);
2873 reason = evhttp_response_phrase_internal(code);
2874 req->response_code_line = mm_strdup(reason);
2875 if (req->response_code_line == NULL) {
2876 event_warn("%s: strdup", __func__);
2877 /* XXX what else can we do? */
2882 evhttp_send_page_(struct evhttp_request *req, struct evbuffer *databuf)
2884 if (!req->major || !req->minor) {
2889 if (req->kind != EVHTTP_RESPONSE)
2890 evhttp_response_code_(req, 200, "OK");
2892 evhttp_clear_headers(req->output_headers);
2893 evhttp_add_header(req->output_headers, "Content-Type", "text/html");
2894 evhttp_add_header(req->output_headers, "Connection", "close");
2896 evhttp_send(req, databuf);
2899 static const char uri_chars[256] = {
2901 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2902 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2903 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
2904 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
2906 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2907 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
2908 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2909 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0,
2911 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2912 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2913 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2914 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2916 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2917 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2918 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2919 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2922 #define CHAR_IS_UNRESERVED(c) \
2923 (uri_chars[(unsigned char)(c)])
2926 * Helper functions to encode/decode a string for inclusion in a URI.
2927 * The returned string must be freed by the caller.
2930 evhttp_uriencode(const char *uri, ev_ssize_t len, int space_as_plus)
2932 struct evbuffer *buf = evbuffer_new();
2933 const char *p, *end;
2942 end = uri+strlen(uri);
2944 for (p = uri; p < end; p++) {
2945 if (CHAR_IS_UNRESERVED(*p)) {
2946 evbuffer_add(buf, p, 1);
2947 } else if (*p == ' ' && space_as_plus) {
2948 evbuffer_add(buf, "+", 1);
2950 evbuffer_add_printf(buf, "%%%02X", (unsigned char)(*p));
2953 evbuffer_add(buf, "", 1); /* NUL-terminator. */
2954 result = mm_malloc(evbuffer_get_length(buf));
2956 evbuffer_remove(buf, result, evbuffer_get_length(buf));
2963 evhttp_encode_uri(const char *str)
2965 return evhttp_uriencode(str, -1, 0);
2969 * @param decode_plus_ctl: if 1, we decode plus into space. If 0, we don't.
2970 * If -1, when true we transform plus to space only after we've seen
2971 * a ?. -1 is deprecated.
2972 * @return the number of bytes written to 'ret'.
2975 evhttp_decode_uri_internal(
2976 const char *uri, size_t length, char *ret, int decode_plus_ctl)
2980 int decode_plus = (decode_plus_ctl == 1) ? 1: 0;
2983 for (i = j = 0; i < length; i++) {
2986 if (decode_plus_ctl < 0)
2988 } else if (c == '+' && decode_plus) {
2990 } else if ((i + 2) < length && c == '%' &&
2991 EVUTIL_ISXDIGIT_(uri[i+1]) && EVUTIL_ISXDIGIT_(uri[i+2])) {
2996 c = (char)strtol(tmp, NULL, 16);
3008 evhttp_decode_uri(const char *uri)
3012 if ((ret = mm_malloc(strlen(uri) + 1)) == NULL) {
3013 event_warn("%s: malloc(%lu)", __func__,
3014 (unsigned long)(strlen(uri) + 1));
3018 evhttp_decode_uri_internal(uri, strlen(uri),
3019 ret, -1 /*always_decode_plus*/);
3025 evhttp_uridecode(const char *uri, int decode_plus, size_t *size_out)
3030 if ((ret = mm_malloc(strlen(uri) + 1)) == NULL) {
3031 event_warn("%s: malloc(%lu)", __func__,
3032 (unsigned long)(strlen(uri) + 1));
3036 n = evhttp_decode_uri_internal(uri, strlen(uri),
3037 ret, !!decode_plus/*always_decode_plus*/);
3040 EVUTIL_ASSERT(n >= 0);
3041 *size_out = (size_t)n;
3048 * Helper function to parse out arguments in a query.
3049 * The arguments are separated by key and value.
3053 evhttp_parse_query_impl(const char *str, struct evkeyvalq *headers,
3059 const char *query_part;
3061 struct evhttp_uri *uri=NULL;
3063 TAILQ_INIT(headers);
3066 uri = evhttp_uri_parse(str);
3069 query_part = evhttp_uri_get_query(uri);
3074 /* No arguments - we are done */
3075 if (!query_part || !strlen(query_part)) {
3080 if ((line = mm_strdup(query_part)) == NULL) {
3081 event_warn("%s: strdup", __func__);
3085 p = argument = line;
3086 while (p != NULL && *p != '\0') {
3087 char *key, *value, *decoded_value;
3088 argument = strsep(&p, "&");
3091 key = strsep(&value, "=");
3092 if (value == NULL || *key == '\0') {
3096 if ((decoded_value = mm_malloc(strlen(value) + 1)) == NULL) {
3097 event_warn("%s: mm_malloc", __func__);
3100 evhttp_decode_uri_internal(value, strlen(value),
3101 decoded_value, 1 /*always_decode_plus*/);
3102 event_debug(("Query Param: %s -> %s\n", key, decoded_value));
3103 evhttp_add_header_internal(headers, key, decoded_value);
3104 mm_free(decoded_value);
3110 evhttp_clear_headers(headers);
3115 evhttp_uri_free(uri);
3120 evhttp_parse_query(const char *uri, struct evkeyvalq *headers)
3122 return evhttp_parse_query_impl(uri, headers, 1);
3125 evhttp_parse_query_str(const char *uri, struct evkeyvalq *headers)
3127 return evhttp_parse_query_impl(uri, headers, 0);
3130 static struct evhttp_cb *
3131 evhttp_dispatch_callback(struct httpcbq *callbacks, struct evhttp_request *req)
3133 struct evhttp_cb *cb;
3138 /* Test for different URLs */
3139 path = evhttp_uri_get_path(req->uri_elems);
3140 offset = strlen(path);
3141 if ((translated = mm_malloc(offset + 1)) == NULL)
3143 evhttp_decode_uri_internal(path, offset, translated,
3144 0 /* decode_plus */);
3146 TAILQ_FOREACH(cb, callbacks, next) {
3147 if (!strcmp(cb->what, translated)) {
3148 mm_free(translated);
3153 mm_free(translated);
3159 prefix_suffix_match(const char *pattern, const char *name, int ignorecase)
3164 switch (c = *pattern++) {
3166 return *name == '\0';
3169 while (*name != '\0') {
3170 if (prefix_suffix_match(pattern, name,
3179 EVUTIL_TOLOWER_(c) != EVUTIL_TOLOWER_(*name))
3189 Search the vhost hierarchy beginning with http for a server alias
3190 matching hostname. If a match is found, and outhttp is non-null,
3191 outhttp is set to the matching http object and 1 is returned.
3195 evhttp_find_alias(struct evhttp *http, struct evhttp **outhttp,
3196 const char *hostname)
3198 struct evhttp_server_alias *alias;
3199 struct evhttp *vhost;
3201 TAILQ_FOREACH(alias, &http->aliases, next) {
3202 /* XXX Do we need to handle IP addresses? */
3203 if (!evutil_ascii_strcasecmp(alias->alias, hostname)) {
3210 /* XXX It might be good to avoid recursion here, but I don't
3211 see a way to do that w/o a list. */
3212 TAILQ_FOREACH(vhost, &http->virtualhosts, next_vhost) {
3213 if (evhttp_find_alias(vhost, outhttp, hostname))
3221 Attempts to find the best http object to handle a request for a hostname.
3222 All aliases for the root http object and vhosts are searched for an exact
3223 match. Then, the vhost hierarchy is traversed again for a matching
3226 If an alias or vhost is matched, 1 is returned, and outhttp, if non-null,
3227 is set with the best matching http object. If there are no matches, the
3228 root http object is stored in outhttp and 0 is returned.
3232 evhttp_find_vhost(struct evhttp *http, struct evhttp **outhttp,
3233 const char *hostname)
3235 struct evhttp *vhost;
3236 struct evhttp *oldhttp;
3237 int match_found = 0;
3239 if (evhttp_find_alias(http, outhttp, hostname))
3244 TAILQ_FOREACH(vhost, &http->virtualhosts, next_vhost) {
3245 if (prefix_suffix_match(vhost->vhost_pattern,
3246 hostname, 1 /* ignorecase */)) {
3252 } while (oldhttp != http);
3261 evhttp_handle_request(struct evhttp_request *req, void *arg)
3263 struct evhttp *http = arg;
3264 struct evhttp_cb *cb = NULL;
3265 const char *hostname;
3267 /* we have a new request on which the user needs to take action */
3270 if (req->type == 0 || req->uri == NULL) {
3271 evhttp_send_error(req, HTTP_BADREQUEST, NULL);
3275 if ((http->allowed_methods & req->type) == 0) {
3276 event_debug(("Rejecting disallowed method %x (allowed: %x)\n",
3277 (unsigned)req->type, (unsigned)http->allowed_methods));
3278 evhttp_send_error(req, HTTP_NOTIMPLEMENTED, NULL);
3282 /* handle potential virtual hosts */
3283 hostname = evhttp_request_get_host(req);
3284 if (hostname != NULL) {
3285 evhttp_find_vhost(http, &http, hostname);
3288 if ((cb = evhttp_dispatch_callback(&http->callbacks, req)) != NULL) {
3289 (*cb->cb)(req, cb->cbarg);
3293 /* Generic call back */
3295 (*http->gencb)(req, http->gencbarg);
3298 /* We need to send a 404 here */
3299 #define ERR_FORMAT "<html><head>" \
3300 "<title>404 Not Found</title>" \
3302 "<h1>Not Found</h1>" \
3303 "<p>The requested URL %s was not found on this server.</p>"\
3307 struct evbuffer *buf;
3309 if ((escaped_html = evhttp_htmlescape(req->uri)) == NULL) {
3310 evhttp_connection_free(req->evcon);
3314 if ((buf = evbuffer_new()) == NULL) {
3315 mm_free(escaped_html);
3316 evhttp_connection_free(req->evcon);
3320 evhttp_response_code_(req, HTTP_NOTFOUND, "Not Found");
3322 evbuffer_add_printf(buf, ERR_FORMAT, escaped_html);
3324 mm_free(escaped_html);
3326 evhttp_send_page_(req, buf);
3333 /* Listener callback when a connection arrives at a server. */
3335 accept_socket_cb(struct evconnlistener *listener, evutil_socket_t nfd, struct sockaddr *peer_sa, int peer_socklen, void *arg)
3337 struct evhttp *http = arg;
3339 evhttp_get_request(http, nfd, peer_sa, peer_socklen);
3343 evhttp_bind_socket(struct evhttp *http, const char *address, ev_uint16_t port)
3345 struct evhttp_bound_socket *bound =
3346 evhttp_bind_socket_with_handle(http, address, port);
3352 struct evhttp_bound_socket *
3353 evhttp_bind_socket_with_handle(struct evhttp *http, const char *address, ev_uint16_t port)
3356 struct evhttp_bound_socket *bound;
3358 if ((fd = bind_socket(address, port, 1 /*reuse*/)) == -1)
3361 if (listen(fd, 128) == -1) {
3362 event_sock_warn(fd, "%s: listen", __func__);
3363 evutil_closesocket(fd);
3367 bound = evhttp_accept_socket_with_handle(http, fd);
3369 if (bound != NULL) {
3370 event_debug(("Bound to port %d - Awaiting connections ... ",
3379 evhttp_accept_socket(struct evhttp *http, evutil_socket_t fd)
3381 struct evhttp_bound_socket *bound =
3382 evhttp_accept_socket_with_handle(http, fd);
3389 evhttp_foreach_bound_socket(struct evhttp *http,
3390 evhttp_bound_socket_foreach_fn *function,
3393 struct evhttp_bound_socket *bound;
3395 TAILQ_FOREACH(bound, &http->sockets, next)
3396 function(bound, argument);
3399 struct evhttp_bound_socket *
3400 evhttp_accept_socket_with_handle(struct evhttp *http, evutil_socket_t fd)
3402 struct evhttp_bound_socket *bound;
3403 struct evconnlistener *listener;
3405 LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_EXEC|LEV_OPT_CLOSE_ON_FREE;
3407 listener = evconnlistener_new(http->base, NULL, NULL,
3409 0, /* Backlog is '0' because we already said 'listen' */
3414 bound = evhttp_bind_listener(http, listener);
3416 evconnlistener_free(listener);
3422 struct evhttp_bound_socket *
3423 evhttp_bind_listener(struct evhttp *http, struct evconnlistener *listener)
3425 struct evhttp_bound_socket *bound;
3427 bound = mm_malloc(sizeof(struct evhttp_bound_socket));
3431 bound->listener = listener;
3432 TAILQ_INSERT_TAIL(&http->sockets, bound, next);
3434 evconnlistener_set_cb(listener, accept_socket_cb, http);
3439 evhttp_bound_socket_get_fd(struct evhttp_bound_socket *bound)
3441 return evconnlistener_get_fd(bound->listener);
3444 struct evconnlistener *
3445 evhttp_bound_socket_get_listener(struct evhttp_bound_socket *bound)
3447 return bound->listener;
3451 evhttp_del_accept_socket(struct evhttp *http, struct evhttp_bound_socket *bound)
3453 TAILQ_REMOVE(&http->sockets, bound, next);
3454 evconnlistener_free(bound->listener);
3458 static struct evhttp*
3459 evhttp_new_object(void)
3461 struct evhttp *http = NULL;
3463 if ((http = mm_calloc(1, sizeof(struct evhttp))) == NULL) {
3464 event_warn("%s: calloc", __func__);
3468 evutil_timerclear(&http->timeout);
3469 evhttp_set_max_headers_size(http, EV_SIZE_MAX);
3470 evhttp_set_max_body_size(http, EV_SIZE_MAX);
3471 evhttp_set_default_content_type(http, "text/html; charset=ISO-8859-1");
3472 evhttp_set_allowed_methods(http,
3479 TAILQ_INIT(&http->sockets);
3480 TAILQ_INIT(&http->callbacks);
3481 TAILQ_INIT(&http->connections);
3482 TAILQ_INIT(&http->virtualhosts);
3483 TAILQ_INIT(&http->aliases);
3489 evhttp_new(struct event_base *base)
3491 struct evhttp *http = NULL;
3493 http = evhttp_new_object();
3502 * Start a web server on the specified address and port.
3506 evhttp_start(const char *address, unsigned short port)
3508 struct evhttp *http = NULL;
3510 http = evhttp_new_object();
3513 if (evhttp_bind_socket(http, address, port) == -1) {
3522 evhttp_free(struct evhttp* http)
3524 struct evhttp_cb *http_cb;
3525 struct evhttp_connection *evcon;
3526 struct evhttp_bound_socket *bound;
3527 struct evhttp* vhost;
3528 struct evhttp_server_alias *alias;
3530 /* Remove the accepting part */
3531 while ((bound = TAILQ_FIRST(&http->sockets)) != NULL) {
3532 TAILQ_REMOVE(&http->sockets, bound, next);
3534 evconnlistener_free(bound->listener);
3539 while ((evcon = TAILQ_FIRST(&http->connections)) != NULL) {
3540 /* evhttp_connection_free removes the connection */
3541 evhttp_connection_free(evcon);
3544 while ((http_cb = TAILQ_FIRST(&http->callbacks)) != NULL) {
3545 TAILQ_REMOVE(&http->callbacks, http_cb, next);
3546 mm_free(http_cb->what);
3550 while ((vhost = TAILQ_FIRST(&http->virtualhosts)) != NULL) {
3551 TAILQ_REMOVE(&http->virtualhosts, vhost, next_vhost);
3556 if (http->vhost_pattern != NULL)
3557 mm_free(http->vhost_pattern);
3559 while ((alias = TAILQ_FIRST(&http->aliases)) != NULL) {
3560 TAILQ_REMOVE(&http->aliases, alias, next);
3561 mm_free(alias->alias);
3569 evhttp_add_virtual_host(struct evhttp* http, const char *pattern,
3570 struct evhttp* vhost)
3572 /* a vhost can only be a vhost once and should not have bound sockets */
3573 if (vhost->vhost_pattern != NULL ||
3574 TAILQ_FIRST(&vhost->sockets) != NULL)
3577 vhost->vhost_pattern = mm_strdup(pattern);
3578 if (vhost->vhost_pattern == NULL)
3581 TAILQ_INSERT_TAIL(&http->virtualhosts, vhost, next_vhost);
3587 evhttp_remove_virtual_host(struct evhttp* http, struct evhttp* vhost)
3589 if (vhost->vhost_pattern == NULL)
3592 TAILQ_REMOVE(&http->virtualhosts, vhost, next_vhost);
3594 mm_free(vhost->vhost_pattern);
3595 vhost->vhost_pattern = NULL;
3601 evhttp_add_server_alias(struct evhttp *http, const char *alias)
3603 struct evhttp_server_alias *evalias;
3605 evalias = mm_calloc(1, sizeof(*evalias));
3609 evalias->alias = mm_strdup(alias);
3610 if (!evalias->alias) {
3615 TAILQ_INSERT_TAIL(&http->aliases, evalias, next);
3621 evhttp_remove_server_alias(struct evhttp *http, const char *alias)
3623 struct evhttp_server_alias *evalias;
3625 TAILQ_FOREACH(evalias, &http->aliases, next) {
3626 if (evutil_ascii_strcasecmp(evalias->alias, alias) == 0) {
3627 TAILQ_REMOVE(&http->aliases, evalias, next);
3628 mm_free(evalias->alias);
3638 evhttp_set_timeout(struct evhttp* http, int timeout_in_secs)
3640 if (timeout_in_secs == -1) {
3641 evhttp_set_timeout_tv(http, NULL);
3644 tv.tv_sec = timeout_in_secs;
3646 evhttp_set_timeout_tv(http, &tv);
3651 evhttp_set_timeout_tv(struct evhttp* http, const struct timeval* tv)
3654 http->timeout = *tv;
3656 evutil_timerclear(&http->timeout);
3661 evhttp_set_max_headers_size(struct evhttp* http, ev_ssize_t max_headers_size)
3663 if (max_headers_size < 0)
3664 http->default_max_headers_size = EV_SIZE_MAX;
3666 http->default_max_headers_size = max_headers_size;
3670 evhttp_set_max_body_size(struct evhttp* http, ev_ssize_t max_body_size)
3672 if (max_body_size < 0)
3673 http->default_max_body_size = EV_UINT64_MAX;
3675 http->default_max_body_size = max_body_size;
3679 evhttp_set_default_content_type(struct evhttp *http,
3680 const char *content_type) {
3681 http->default_content_type = content_type;
3685 evhttp_set_allowed_methods(struct evhttp* http, ev_uint16_t methods)
3687 http->allowed_methods = methods;
3691 evhttp_set_cb(struct evhttp *http, const char *uri,
3692 void (*cb)(struct evhttp_request *, void *), void *cbarg)
3694 struct evhttp_cb *http_cb;
3696 TAILQ_FOREACH(http_cb, &http->callbacks, next) {
3697 if (strcmp(http_cb->what, uri) == 0)
3701 if ((http_cb = mm_calloc(1, sizeof(struct evhttp_cb))) == NULL) {
3702 event_warn("%s: calloc", __func__);
3706 http_cb->what = mm_strdup(uri);
3707 if (http_cb->what == NULL) {
3708 event_warn("%s: strdup", __func__);
3713 http_cb->cbarg = cbarg;
3715 TAILQ_INSERT_TAIL(&http->callbacks, http_cb, next);
3721 evhttp_del_cb(struct evhttp *http, const char *uri)
3723 struct evhttp_cb *http_cb;
3725 TAILQ_FOREACH(http_cb, &http->callbacks, next) {
3726 if (strcmp(http_cb->what, uri) == 0)
3729 if (http_cb == NULL)
3732 TAILQ_REMOVE(&http->callbacks, http_cb, next);
3733 mm_free(http_cb->what);
3740 evhttp_set_gencb(struct evhttp *http,
3741 void (*cb)(struct evhttp_request *, void *), void *cbarg)
3744 http->gencbarg = cbarg;
3748 evhttp_set_bevcb(struct evhttp *http,
3749 struct bufferevent* (*cb)(struct event_base *, void *), void *cbarg)
3752 http->bevcbarg = cbarg;
3756 * Request related functions
3759 struct evhttp_request *
3760 evhttp_request_new(void (*cb)(struct evhttp_request *, void *), void *arg)
3762 struct evhttp_request *req = NULL;
3764 /* Allocate request structure */
3765 if ((req = mm_calloc(1, sizeof(struct evhttp_request))) == NULL) {
3766 event_warn("%s: calloc", __func__);
3770 req->headers_size = 0;
3773 req->kind = EVHTTP_RESPONSE;
3774 req->input_headers = mm_calloc(1, sizeof(struct evkeyvalq));
3775 if (req->input_headers == NULL) {
3776 event_warn("%s: calloc", __func__);
3779 TAILQ_INIT(req->input_headers);
3781 req->output_headers = mm_calloc(1, sizeof(struct evkeyvalq));
3782 if (req->output_headers == NULL) {
3783 event_warn("%s: calloc", __func__);
3786 TAILQ_INIT(req->output_headers);
3788 if ((req->input_buffer = evbuffer_new()) == NULL) {
3789 event_warn("%s: evbuffer_new", __func__);
3793 if ((req->output_buffer = evbuffer_new()) == NULL) {
3794 event_warn("%s: evbuffer_new", __func__);
3805 evhttp_request_free(req);
3810 evhttp_request_free(struct evhttp_request *req)
3812 if ((req->flags & EVHTTP_REQ_DEFER_FREE) != 0) {
3813 req->flags |= EVHTTP_REQ_NEEDS_FREE;
3817 if (req->remote_host != NULL)
3818 mm_free(req->remote_host);
3819 if (req->uri != NULL)
3821 if (req->uri_elems != NULL)
3822 evhttp_uri_free(req->uri_elems);
3823 if (req->response_code_line != NULL)
3824 mm_free(req->response_code_line);
3825 if (req->host_cache != NULL)
3826 mm_free(req->host_cache);
3828 evhttp_clear_headers(req->input_headers);
3829 mm_free(req->input_headers);
3831 evhttp_clear_headers(req->output_headers);
3832 mm_free(req->output_headers);
3834 if (req->input_buffer != NULL)
3835 evbuffer_free(req->input_buffer);
3837 if (req->output_buffer != NULL)
3838 evbuffer_free(req->output_buffer);
3844 evhttp_request_own(struct evhttp_request *req)
3846 req->flags |= EVHTTP_USER_OWNED;
3850 evhttp_request_is_owned(struct evhttp_request *req)
3852 return (req->flags & EVHTTP_USER_OWNED) != 0;
3855 struct evhttp_connection *
3856 evhttp_request_get_connection(struct evhttp_request *req)
3862 evhttp_connection_get_base(struct evhttp_connection *conn)
3868 evhttp_request_set_chunked_cb(struct evhttp_request *req,
3869 void (*cb)(struct evhttp_request *, void *))
3875 evhttp_request_set_header_cb(struct evhttp_request *req,
3876 int (*cb)(struct evhttp_request *, void *))
3878 req->header_cb = cb;
3882 evhttp_request_set_error_cb(struct evhttp_request *req,
3883 void (*cb)(enum evhttp_request_error, void *))
3889 evhttp_request_set_on_complete_cb(struct evhttp_request *req,
3890 void (*cb)(struct evhttp_request *, void *), void *cb_arg)
3892 req->on_complete_cb = cb;
3893 req->on_complete_cb_arg = cb_arg;
3897 * Allows for inspection of the request URI
3901 evhttp_request_get_uri(const struct evhttp_request *req) {
3902 if (req->uri == NULL)
3903 event_debug(("%s: request %p has no uri\n", __func__, req));
3907 const struct evhttp_uri *
3908 evhttp_request_get_evhttp_uri(const struct evhttp_request *req) {
3909 if (req->uri_elems == NULL)
3910 event_debug(("%s: request %p has no uri elems\n",
3912 return (req->uri_elems);
3916 evhttp_request_get_host(struct evhttp_request *req)
3918 const char *host = NULL;
3920 if (req->host_cache)
3921 return req->host_cache;
3924 host = evhttp_uri_get_host(req->uri_elems);
3925 if (!host && req->input_headers) {
3929 host = evhttp_find_header(req->input_headers, "Host");
3930 /* The Host: header may include a port. Remove it here
3931 to be consistent with uri_elems case above. */
3933 p = host + strlen(host) - 1;
3934 while (p > host && EVUTIL_ISDIGIT_(*p))
3936 if (p > host && *p == ':') {
3938 req->host_cache = mm_malloc(len + 1);
3939 if (!req->host_cache) {
3940 event_warn("%s: malloc", __func__);
3943 memcpy(req->host_cache, host, len);
3944 req->host_cache[len] = '\0';
3945 host = req->host_cache;
3953 enum evhttp_cmd_type
3954 evhttp_request_get_command(const struct evhttp_request *req) {
3959 evhttp_request_get_response_code(const struct evhttp_request *req)
3961 return req->response_code;
3965 evhttp_request_get_response_code_line(const struct evhttp_request *req)
3967 return req->response_code_line;
3970 /** Returns the input headers */
3971 struct evkeyvalq *evhttp_request_get_input_headers(struct evhttp_request *req)
3973 return (req->input_headers);
3976 /** Returns the output headers */
3977 struct evkeyvalq *evhttp_request_get_output_headers(struct evhttp_request *req)
3979 return (req->output_headers);
3982 /** Returns the input buffer */
3983 struct evbuffer *evhttp_request_get_input_buffer(struct evhttp_request *req)
3985 return (req->input_buffer);
3988 /** Returns the output buffer */
3989 struct evbuffer *evhttp_request_get_output_buffer(struct evhttp_request *req)
3991 return (req->output_buffer);
3996 * Takes a file descriptor to read a request from.
3997 * The callback is executed once the whole request has been read.
4000 static struct evhttp_connection*
4001 evhttp_get_request_connection(
4002 struct evhttp* http,
4003 evutil_socket_t fd, struct sockaddr *sa, ev_socklen_t salen)
4005 struct evhttp_connection *evcon;
4006 char *hostname = NULL, *portname = NULL;
4007 struct bufferevent* bev = NULL;
4009 name_from_addr(sa, salen, &hostname, &portname);
4010 if (hostname == NULL || portname == NULL) {
4011 if (hostname) mm_free(hostname);
4012 if (portname) mm_free(portname);
4016 event_debug(("%s: new request from %s:%s on "EV_SOCK_FMT"\n",
4017 __func__, hostname, portname, EV_SOCK_ARG(fd)));
4019 /* we need a connection object to put the http request on */
4020 if (http->bevcb != NULL) {
4021 bev = (*http->bevcb)(http->base, http->bevcbarg);
4023 evcon = evhttp_connection_base_bufferevent_new(
4024 http->base, NULL, bev, hostname, atoi(portname));
4030 evcon->max_headers_size = http->default_max_headers_size;
4031 evcon->max_body_size = http->default_max_body_size;
4033 evcon->flags |= EVHTTP_CON_INCOMING;
4034 evcon->state = EVCON_READING_FIRSTLINE;
4038 bufferevent_setfd(evcon->bufev, fd);
4044 evhttp_associate_new_request_with_connection(struct evhttp_connection *evcon)
4046 struct evhttp *http = evcon->http_server;
4047 struct evhttp_request *req;
4048 if ((req = evhttp_request_new(evhttp_handle_request, http)) == NULL)
4051 if ((req->remote_host = mm_strdup(evcon->address)) == NULL) {
4052 event_warn("%s: strdup", __func__);
4053 evhttp_request_free(req);
4056 req->remote_port = evcon->port;
4058 req->evcon = evcon; /* the request ends up owning the connection */
4059 req->flags |= EVHTTP_REQ_OWN_CONNECTION;
4061 /* We did not present the request to the user user yet, so treat it as
4062 * if the user was done with the request. This allows us to free the
4063 * request on a persistent connection if the client drops it without
4064 * sending a request.
4068 TAILQ_INSERT_TAIL(&evcon->requests, req, next);
4070 req->kind = EVHTTP_REQUEST;
4073 evhttp_start_read_(evcon);
4079 evhttp_get_request(struct evhttp *http, evutil_socket_t fd,
4080 struct sockaddr *sa, ev_socklen_t salen)
4082 struct evhttp_connection *evcon;
4084 evcon = evhttp_get_request_connection(http, fd, sa, salen);
4085 if (evcon == NULL) {
4086 event_sock_warn(fd, "%s: cannot get connection on "EV_SOCK_FMT,
4087 __func__, EV_SOCK_ARG(fd));
4088 evutil_closesocket(fd);
4092 /* the timeout can be used by the server to close idle connections */
4093 if (evutil_timerisset(&http->timeout))
4094 evhttp_connection_set_timeout_tv(evcon, &http->timeout);
4097 * if we want to accept more than one request on a connection,
4098 * we need to know which http server it belongs to.
4100 evcon->http_server = http;
4101 TAILQ_INSERT_TAIL(&http->connections, evcon, next);
4103 if (evhttp_associate_new_request_with_connection(evcon) == -1)
4104 evhttp_connection_free(evcon);
4109 * Network helper functions that we do not want to export to the rest of
4114 name_from_addr(struct sockaddr *sa, ev_socklen_t salen,
4115 char **phost, char **pport)
4117 char ntop[NI_MAXHOST];
4118 char strport[NI_MAXSERV];
4121 #ifdef EVENT__HAVE_GETNAMEINFO
4122 ni_result = getnameinfo(sa, salen,
4123 ntop, sizeof(ntop), strport, sizeof(strport),
4124 NI_NUMERICHOST|NI_NUMERICSERV);
4126 if (ni_result != 0) {
4128 /* Windows doesn't have an EAI_SYSTEM. */
4129 if (ni_result == EAI_SYSTEM)
4130 event_err(1, "getnameinfo failed");
4133 event_errx(1, "getnameinfo failed: %s", gai_strerror(ni_result));
4137 ni_result = fake_getnameinfo(sa, salen,
4138 ntop, sizeof(ntop), strport, sizeof(strport),
4139 NI_NUMERICHOST|NI_NUMERICSERV);
4144 *phost = mm_strdup(ntop);
4145 *pport = mm_strdup(strport);
4148 /* Create a non-blocking socket and bind it */
4149 /* todo: rename this function */
4150 static evutil_socket_t
4151 bind_socket_ai(struct evutil_addrinfo *ai, int reuse)
4158 /* Create listen socket */
4159 fd = evutil_socket_(ai ? ai->ai_family : AF_INET,
4160 SOCK_STREAM|EVUTIL_SOCK_NONBLOCK|EVUTIL_SOCK_CLOEXEC, 0);
4162 event_sock_warn(-1, "socket");
4166 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on))<0)
4169 if (evutil_make_listen_socket_reuseable(fd) < 0)
4174 r = bind(fd, ai->ai_addr, (ev_socklen_t)ai->ai_addrlen);
4182 serrno = EVUTIL_SOCKET_ERROR();
4183 evutil_closesocket(fd);
4184 EVUTIL_SET_SOCKET_ERROR(serrno);
4188 static struct evutil_addrinfo *
4189 make_addrinfo(const char *address, ev_uint16_t port)
4191 struct evutil_addrinfo *ai = NULL;
4193 struct evutil_addrinfo hints;
4194 char strport[NI_MAXSERV];
4197 memset(&hints, 0, sizeof(hints));
4198 hints.ai_family = AF_UNSPEC;
4199 hints.ai_socktype = SOCK_STREAM;
4200 /* turn NULL hostname into INADDR_ANY, and skip looking up any address
4201 * types we don't have an interface to connect to. */
4202 hints.ai_flags = EVUTIL_AI_PASSIVE|EVUTIL_AI_ADDRCONFIG;
4203 evutil_snprintf(strport, sizeof(strport), "%d", port);
4204 if ((ai_result = evutil_getaddrinfo(address, strport, &hints, &ai))
4206 if (ai_result == EVUTIL_EAI_SYSTEM)
4207 event_warn("getaddrinfo");
4209 event_warnx("getaddrinfo: %s",
4210 evutil_gai_strerror(ai_result));
4217 static evutil_socket_t
4218 bind_socket(const char *address, ev_uint16_t port, int reuse)
4221 struct evutil_addrinfo *aitop = NULL;
4223 /* just create an unbound socket */
4224 if (address == NULL && port == 0)
4225 return bind_socket_ai(NULL, 0);
4227 aitop = make_addrinfo(address, port);
4232 fd = bind_socket_ai(aitop, reuse);
4234 evutil_freeaddrinfo(aitop);
4241 char *scheme; /* scheme; e.g http, ftp etc */
4242 char *userinfo; /* userinfo (typically username:pass), or NULL */
4243 char *host; /* hostname, IP address, or NULL */
4244 int port; /* port, or zero */
4245 char *path; /* path, or "". */
4246 char *query; /* query, or NULL */
4247 char *fragment; /* fragment or NULL */
4251 evhttp_uri_new(void)
4253 struct evhttp_uri *uri = mm_calloc(sizeof(struct evhttp_uri), 1);
4260 evhttp_uri_set_flags(struct evhttp_uri *uri, unsigned flags)
4265 /* Return true if the string starting at s and ending immediately before eos
4266 * is a valid URI scheme according to RFC3986
4269 scheme_ok(const char *s, const char *eos)
4271 /* scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */
4272 EVUTIL_ASSERT(eos >= s);
4275 if (!EVUTIL_ISALPHA_(*s))
4278 if (! EVUTIL_ISALNUM_(*s) &&
4279 *s != '+' && *s != '-' && *s != '.')
4285 #define SUBDELIMS "!$&'()*+,;="
4287 /* Return true iff [s..eos) is a valid userinfo */
4289 userinfo_ok(const char *s, const char *eos)
4292 if (CHAR_IS_UNRESERVED(*s) ||
4293 strchr(SUBDELIMS, *s) ||
4296 else if (*s == '%' && s+2 < eos &&
4297 EVUTIL_ISXDIGIT_(s[1]) &&
4298 EVUTIL_ISXDIGIT_(s[2]))
4307 regname_ok(const char *s, const char *eos)
4309 while (s && s<eos) {
4310 if (CHAR_IS_UNRESERVED(*s) ||
4311 strchr(SUBDELIMS, *s))
4313 else if (*s == '%' &&
4314 EVUTIL_ISXDIGIT_(s[1]) &&
4315 EVUTIL_ISXDIGIT_(s[2]))
4324 parse_port(const char *s, const char *eos)
4328 if (! EVUTIL_ISDIGIT_(*s))
4330 portnum = (portnum * 10) + (*s - '0');
4333 if (portnum > 65535)
4340 /* returns 0 for bad, 1 for ipv6, 2 for IPvFuture */
4342 bracket_addr_ok(const char *s, const char *eos)
4344 if (s + 3 > eos || *s != '[' || *(eos-1) != ']')
4347 /* IPvFuture, or junk.
4348 "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
4350 s += 2; /* skip [v */
4352 if (!EVUTIL_ISXDIGIT_(*s)) /*require at least one*/
4354 while (s < eos && *s != '.') {
4355 if (EVUTIL_ISXDIGIT_(*s))
4364 if (CHAR_IS_UNRESERVED(*s) ||
4365 strchr(SUBDELIMS, *s) ||
4375 ev_ssize_t n_chars = eos-s-2;
4376 struct in6_addr in6;
4377 if (n_chars >= 64) /* way too long */
4379 memcpy(buf, s+1, n_chars);
4381 return (evutil_inet_pton(AF_INET6,buf,&in6)==1) ? 1 : 0;
4386 parse_authority(struct evhttp_uri *uri, char *s, char *eos)
4391 uri->host = mm_strdup("");
4392 if (uri->host == NULL) {
4393 event_warn("%s: strdup", __func__);
4399 /* Optionally, we start with "userinfo@" */
4401 cp = strchr(s, '@');
4402 if (cp && cp < eos) {
4403 if (! userinfo_ok(s,cp))
4406 uri->userinfo = mm_strdup(s);
4407 if (uri->userinfo == NULL) {
4408 event_warn("%s: strdup", __func__);
4414 /* Optionally, we end with ":port" */
4415 for (port=eos-1; port >= cp && EVUTIL_ISDIGIT_(*port); --port)
4417 if (port >= cp && *port == ':') {
4418 if (port+1 == eos) /* Leave port unspecified; the RFC allows a
4421 else if ((uri->port = parse_port(port+1, eos))<0)
4425 /* Now, cp..eos holds the "host" port, which can be an IPv4Address,
4426 * an IP-Literal, or a reg-name */
4427 EVUTIL_ASSERT(eos >= cp);
4428 if (*cp == '[' && eos >= cp+2 && *(eos-1) == ']') {
4429 /* IPv6address, IP-Literal, or junk. */
4430 if (! bracket_addr_ok(cp, eos))
4433 /* Make sure the host part is ok. */
4434 if (! regname_ok(cp,eos)) /* Match IPv4Address or reg-name */
4437 uri->host = mm_malloc(eos-cp+1);
4438 if (uri->host == NULL) {
4439 event_warn("%s: malloc", __func__);
4442 memcpy(uri->host, cp, eos-cp);
4443 uri->host[eos-cp] = '\0';
4449 end_of_authority(char *cp)
4452 if (*cp == '?' || *cp == '#' || *cp == '/')
4465 /* Return the character after the longest prefix of 'cp' that matches...
4466 * *pchar / "/" if allow_qchars is false, or
4467 * *(pchar / "/" / "?") if allow_qchars is true.
4470 end_of_path(char *cp, enum uri_part part, unsigned flags)
4472 if (flags & EVHTTP_URI_NONCONFORMANT) {
4473 /* If NONCONFORMANT:
4474 * Path is everything up to a # or ? or nul.
4475 * Query is everything up a # or nul
4476 * Fragment is everything up to a nul.
4480 while (*cp && *cp != '#' && *cp != '?')
4484 while (*cp && *cp != '#')
4495 if (CHAR_IS_UNRESERVED(*cp) ||
4496 strchr(SUBDELIMS, *cp) ||
4497 *cp == ':' || *cp == '@' || *cp == '/')
4499 else if (*cp == '%' && EVUTIL_ISXDIGIT_(cp[1]) &&
4500 EVUTIL_ISXDIGIT_(cp[2]))
4502 else if (*cp == '?' && part != PART_PATH)
4511 path_matches_noscheme(const char *cp)
4516 else if (*cp == '/')
4524 evhttp_uri_parse(const char *source_uri)
4526 return evhttp_uri_parse_with_flags(source_uri, 0);
4530 evhttp_uri_parse_with_flags(const char *source_uri, unsigned flags)
4532 char *readbuf = NULL, *readp = NULL, *token = NULL, *query = NULL;
4533 char *path = NULL, *fragment = NULL;
4534 int got_authority = 0;
4536 struct evhttp_uri *uri = mm_calloc(1, sizeof(struct evhttp_uri));
4538 event_warn("%s: calloc", __func__);
4544 readbuf = mm_strdup(source_uri);
4545 if (readbuf == NULL) {
4546 event_warn("%s: strdup", __func__);
4553 /* We try to follow RFC3986 here as much as we can, and match
4556 URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
4558 relative-ref = relative-part [ "?" query ] [ "#" fragment ]
4562 token = strchr(readp, ':');
4563 if (token && scheme_ok(readp,token)) {
4565 uri->scheme = mm_strdup(readp);
4566 if (uri->scheme == NULL) {
4567 event_warn("%s: strdup", __func__);
4570 readp = token+1; /* eat : */
4573 /* 2. Optionally, "//" then an 'authority' part. */
4574 if (readp[0]=='/' && readp[1] == '/') {
4578 path = end_of_authority(readp);
4579 if (parse_authority(uri, authority, path) < 0)
4585 /* 3. Query: path-abempty, path-absolute, path-rootless, or path-empty
4588 readp = end_of_path(path, PART_PATH, flags);
4591 if (*readp == '?') {
4595 readp = end_of_path(readp, PART_QUERY, flags);
4598 if (*readp == '#') {
4602 readp = end_of_path(readp, PART_FRAGMENT, flags);
4604 if (*readp != '\0') {
4608 /* These next two cases may be unreachable; I'm leaving them
4609 * in to be defensive. */
4610 /* If you didn't get an authority, the path can't begin with "//" */
4611 if (!got_authority && path[0]=='/' && path[1]=='/')
4613 /* If you did get an authority, the path must begin with "/" or be
4615 if (got_authority && path[0] != '/' && path[0] != '\0')
4617 /* (End of maybe-unreachable cases) */
4619 /* If there was no scheme, the first part of the path (if any) must
4620 * have no colon in it. */
4621 if (! uri->scheme && !path_matches_noscheme(path))
4624 EVUTIL_ASSERT(path);
4625 uri->path = mm_strdup(path);
4626 if (uri->path == NULL) {
4627 event_warn("%s: strdup", __func__);
4632 uri->query = mm_strdup(query);
4633 if (uri->query == NULL) {
4634 event_warn("%s: strdup", __func__);
4639 uri->fragment = mm_strdup(fragment);
4640 if (uri->fragment == NULL) {
4641 event_warn("%s: strdup", __func__);
4651 evhttp_uri_free(uri);
4658 evhttp_uri_free(struct evhttp_uri *uri)
4660 #define URI_FREE_STR_(f) \
4665 URI_FREE_STR_(scheme);
4666 URI_FREE_STR_(userinfo);
4667 URI_FREE_STR_(host);
4668 URI_FREE_STR_(path);
4669 URI_FREE_STR_(query);
4670 URI_FREE_STR_(fragment);
4673 #undef URI_FREE_STR_
4677 evhttp_uri_join(struct evhttp_uri *uri, char *buf, size_t limit)
4679 struct evbuffer *tmp = 0;
4680 size_t joined_size = 0;
4681 char *output = NULL;
4683 #define URI_ADD_(f) evbuffer_add(tmp, uri->f, strlen(uri->f))
4685 if (!uri || !buf || !limit)
4688 tmp = evbuffer_new();
4694 evbuffer_add(tmp, ":", 1);
4697 evbuffer_add(tmp, "//", 2);
4699 evbuffer_add_printf(tmp,"%s@", uri->userinfo);
4702 evbuffer_add_printf(tmp,":%d", uri->port);
4704 if (uri->path && uri->path[0] != '/' && uri->path[0] != '\0')
4712 evbuffer_add(tmp, "?", 1);
4716 if (uri->fragment) {
4717 evbuffer_add(tmp, "#", 1);
4721 evbuffer_add(tmp, "\0", 1); /* NUL */
4723 joined_size = evbuffer_get_length(tmp);
4725 if (joined_size > limit) {
4726 /* It doesn't fit. */
4730 evbuffer_remove(tmp, buf, joined_size);
4741 evhttp_uri_get_scheme(const struct evhttp_uri *uri)
4746 evhttp_uri_get_userinfo(const struct evhttp_uri *uri)
4748 return uri->userinfo;
4751 evhttp_uri_get_host(const struct evhttp_uri *uri)
4756 evhttp_uri_get_port(const struct evhttp_uri *uri)
4761 evhttp_uri_get_path(const struct evhttp_uri *uri)
4766 evhttp_uri_get_query(const struct evhttp_uri *uri)
4771 evhttp_uri_get_fragment(const struct evhttp_uri *uri)
4773 return uri->fragment;
4776 #define URI_SET_STR_(f) do { \
4780 if ((uri->f = mm_strdup(f)) == NULL) { \
4781 event_warn("%s: strdup()", __func__); \
4790 evhttp_uri_set_scheme(struct evhttp_uri *uri, const char *scheme)
4792 if (scheme && !scheme_ok(scheme, scheme+strlen(scheme)))
4795 URI_SET_STR_(scheme);
4799 evhttp_uri_set_userinfo(struct evhttp_uri *uri, const char *userinfo)
4801 if (userinfo && !userinfo_ok(userinfo, userinfo+strlen(userinfo)))
4803 URI_SET_STR_(userinfo);
4807 evhttp_uri_set_host(struct evhttp_uri *uri, const char *host)
4810 if (host[0] == '[') {
4811 if (! bracket_addr_ok(host, host+strlen(host)))
4814 if (! regname_ok(host, host+strlen(host)))
4823 evhttp_uri_set_port(struct evhttp_uri *uri, int port)
4830 #define end_of_cpath(cp,p,f) \
4831 ((const char*)(end_of_path(((char*)(cp)), (p), (f))))
4834 evhttp_uri_set_path(struct evhttp_uri *uri, const char *path)
4836 if (path && end_of_cpath(path, PART_PATH, uri->flags) != path+strlen(path))
4843 evhttp_uri_set_query(struct evhttp_uri *uri, const char *query)
4845 if (query && end_of_cpath(query, PART_QUERY, uri->flags) != query+strlen(query))
4847 URI_SET_STR_(query);
4851 evhttp_uri_set_fragment(struct evhttp_uri *uri, const char *fragment)
4853 if (fragment && end_of_cpath(fragment, PART_FRAGMENT, uri->flags) != fragment+strlen(fragment))
4855 URI_SET_STR_(fragment);