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 HAVE_SYS_IOCCOM_H
39 #include <sys/ioccom.h>
41 #ifdef EVENT__HAVE_SYS_RESOURCE_H
42 #include <sys/resource.h>
44 #ifdef EVENT__HAVE_SYS_TIME_H
47 #ifdef EVENT__HAVE_SYS_WAIT_H
52 #include <sys/socket.h>
59 #include <sys/queue.h>
61 #ifdef EVENT__HAVE_NETINET_IN_H
62 #include <netinet/in.h>
64 #ifdef EVENT__HAVE_ARPA_INET_H
65 #include <arpa/inet.h>
67 #ifdef EVENT__HAVE_NETDB_H
84 #ifdef EVENT__HAVE_UNISTD_H
87 #ifdef EVENT__HAVE_FCNTL_H
91 #undef timeout_pending
92 #undef timeout_initialized
94 #include "strlcpy-internal.h"
95 #include "event2/http.h"
96 #include "event2/event.h"
97 #include "event2/buffer.h"
98 #include "event2/bufferevent.h"
99 #include "event2/http_struct.h"
100 #include "event2/http_compat.h"
101 #include "event2/util.h"
102 #include "event2/listener.h"
103 #include "log-internal.h"
104 #include "util-internal.h"
105 #include "http-internal.h"
106 #include "mm-internal.h"
107 #include "bufferevent-internal.h"
109 #ifndef EVENT__HAVE_GETNAMEINFO
110 #define NI_MAXSERV 32
111 #define NI_MAXHOST 1025
113 #ifndef NI_NUMERICHOST
114 #define NI_NUMERICHOST 1
117 #ifndef NI_NUMERICSERV
118 #define NI_NUMERICSERV 2
122 fake_getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
123 size_t hostlen, char *serv, size_t servlen, int flags)
125 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
129 evutil_snprintf(tmpserv, sizeof(tmpserv),
130 "%d", ntohs(sin->sin_port));
131 if (strlcpy(serv, tmpserv, servlen) >= servlen)
136 if (flags & NI_NUMERICHOST) {
137 if (strlcpy(host, inet_ntoa(sin->sin_addr),
144 hp = gethostbyaddr((char *)&sin->sin_addr,
145 sizeof(struct in_addr), AF_INET);
149 if (strlcpy(host, hp->h_name, hostlen) >= hostlen)
160 #define REQ_VERSION_BEFORE(req, major_v, minor_v) \
161 ((req)->major < (major_v) || \
162 ((req)->major == (major_v) && (req)->minor < (minor_v)))
164 #define REQ_VERSION_ATLEAST(req, major_v, minor_v) \
165 ((req)->major > (major_v) || \
166 ((req)->major == (major_v) && (req)->minor >= (minor_v)))
169 #define MIN(a,b) (((a)<(b))?(a):(b))
174 static evutil_socket_t bind_socket_ai(struct evutil_addrinfo *, int reuse);
175 static evutil_socket_t bind_socket(const char *, ev_uint16_t, int reuse);
176 static void name_from_addr(struct sockaddr *, ev_socklen_t, char **, char **);
177 static int evhttp_associate_new_request_with_connection(
178 struct evhttp_connection *evcon);
179 static void evhttp_connection_start_detectclose(
180 struct evhttp_connection *evcon);
181 static void evhttp_connection_stop_detectclose(
182 struct evhttp_connection *evcon);
183 static void evhttp_request_dispatch(struct evhttp_connection* evcon);
184 static void evhttp_read_firstline(struct evhttp_connection *evcon,
185 struct evhttp_request *req);
186 static void evhttp_read_header(struct evhttp_connection *evcon,
187 struct evhttp_request *req);
188 static int evhttp_add_header_internal(struct evkeyvalq *headers,
189 const char *key, const char *value);
190 static const char *evhttp_response_phrase_internal(int code);
191 static void evhttp_get_request(struct evhttp *, evutil_socket_t, struct sockaddr *, ev_socklen_t);
192 static void evhttp_write_buffer(struct evhttp_connection *,
193 void (*)(struct evhttp_connection *, void *), void *);
194 static void evhttp_make_header(struct evhttp_connection *, struct evhttp_request *);
196 /* callbacks for bufferevent */
197 static void evhttp_read_cb(struct bufferevent *, void *);
198 static void evhttp_write_cb(struct bufferevent *, void *);
199 static void evhttp_error_cb(struct bufferevent *bufev, short what, void *arg);
200 static int evhttp_find_vhost(struct evhttp *http, struct evhttp **outhttp,
201 const char *hostname);
203 #ifndef EVENT__HAVE_STRSEP
204 /* strsep replacement for platforms that lack it. Only works if
205 * del is one character long. */
207 strsep(char **s, const char *del)
210 EVUTIL_ASSERT(strlen(del) == 1);
214 d = strstr(tok, del);
225 html_replace(const char ch, const char **escaped)
251 * Replaces <, >, ", ' and & with <, >, ",
252 * ' and & correspondingly.
254 * The returned string needs to be freed by the caller.
258 evhttp_htmlescape(const char *html)
261 size_t new_size = 0, old_size = 0;
262 char *escaped_html, *p;
267 old_size = strlen(html);
268 for (i = 0; i < old_size; ++i) {
269 const char *replaced = NULL;
270 const size_t replace_size = html_replace(html[i], &replaced);
271 if (replace_size > EV_SIZE_MAX - new_size) {
272 event_warn("%s: html_replace overflow", __func__);
275 new_size += replace_size;
278 if (new_size == EV_SIZE_MAX)
280 p = escaped_html = mm_malloc(new_size + 1);
281 if (escaped_html == NULL) {
282 event_warn("%s: malloc(%lu)", __func__,
283 (unsigned long)(new_size + 1));
286 for (i = 0; i < old_size; ++i) {
287 const char *replaced = &html[i];
288 const size_t len = html_replace(html[i], &replaced);
289 memcpy(p, replaced, len);
295 return (escaped_html);
298 /** Given an evhttp_cmd_type, returns a constant string containing the
299 * equivalent HTTP command, or NULL if the evhttp_command_type is
302 evhttp_method(enum evhttp_cmd_type type)
310 case EVHTTP_REQ_POST:
313 case EVHTTP_REQ_HEAD:
319 case EVHTTP_REQ_DELETE:
322 case EVHTTP_REQ_OPTIONS:
325 case EVHTTP_REQ_TRACE:
328 case EVHTTP_REQ_CONNECT:
331 case EVHTTP_REQ_PATCH:
343 * Determines if a response should have a body.
344 * Follows the rules in RFC 2616 section 4.3.
345 * @return 1 if the response MUST have a body; 0 if the response MUST NOT have
349 evhttp_response_needs_body(struct evhttp_request *req)
351 return (req->response_code != HTTP_NOCONTENT &&
352 req->response_code != HTTP_NOTMODIFIED &&
353 (req->response_code < 100 || req->response_code >= 200) &&
354 req->type != EVHTTP_REQ_HEAD);
357 /** Helper: called after we've added some data to an evcon's bufferevent's
358 * output buffer. Sets the evconn's writing-is-done callback, and puts
359 * the bufferevent into writing mode.
362 evhttp_write_buffer(struct evhttp_connection *evcon,
363 void (*cb)(struct evhttp_connection *, void *), void *arg)
365 event_debug(("%s: preparing to write buffer\n", __func__));
371 /* Disable the read callback: we don't actually care about data;
372 * we only care about close detection. (We don't disable reading,
373 * since we *do* want to learn about any close events.) */
374 bufferevent_setcb(evcon->bufev,
380 bufferevent_enable(evcon->bufev, EV_WRITE);
384 evhttp_send_continue_done(struct evhttp_connection *evcon, void *arg)
386 bufferevent_disable(evcon->bufev, EV_WRITE);
390 evhttp_send_continue(struct evhttp_connection *evcon,
391 struct evhttp_request *req)
393 bufferevent_enable(evcon->bufev, EV_WRITE);
394 evbuffer_add_printf(bufferevent_get_output(evcon->bufev),
395 "HTTP/%d.%d 100 Continue\r\n\r\n",
396 req->major, req->minor);
397 evcon->cb = evhttp_send_continue_done;
398 evcon->cb_arg = NULL;
399 bufferevent_setcb(evcon->bufev,
406 /** Helper: returns true iff evconn is in any connected state. */
408 evhttp_connected(struct evhttp_connection *evcon)
410 switch (evcon->state) {
411 case EVCON_DISCONNECTED:
412 case EVCON_CONNECTING:
415 case EVCON_READING_FIRSTLINE:
416 case EVCON_READING_HEADERS:
417 case EVCON_READING_BODY:
418 case EVCON_READING_TRAILER:
425 /* Create the headers needed for an outgoing HTTP request, adds them to
426 * the request's header list, and writes the request line to the
427 * connection's output buffer.
430 evhttp_make_header_request(struct evhttp_connection *evcon,
431 struct evhttp_request *req)
435 evhttp_remove_header(req->output_headers, "Proxy-Connection");
437 /* Generate request line */
438 method = evhttp_method(req->type);
439 evbuffer_add_printf(bufferevent_get_output(evcon->bufev),
440 "%s %s HTTP/%d.%d\r\n",
441 method, req->uri, req->major, req->minor);
443 /* Add the content length on a post or put request if missing */
444 if ((req->type == EVHTTP_REQ_POST || req->type == EVHTTP_REQ_PUT) &&
445 evhttp_find_header(req->output_headers, "Content-Length") == NULL){
447 evutil_snprintf(size, sizeof(size), EV_SIZE_FMT,
448 EV_SIZE_ARG(evbuffer_get_length(req->output_buffer)));
449 evhttp_add_header(req->output_headers, "Content-Length", size);
453 /** Return true if the list of headers in 'headers', intepreted with respect
454 * to flags, means that we should send a "connection: close" when the request
457 evhttp_is_connection_close(int flags, struct evkeyvalq* headers)
459 if (flags & EVHTTP_PROXY_REQUEST) {
460 /* proxy connection */
461 const char *connection = evhttp_find_header(headers, "Proxy-Connection");
462 return (connection == NULL || evutil_ascii_strcasecmp(connection, "keep-alive") != 0);
464 const char *connection = evhttp_find_header(headers, "Connection");
465 return (connection != NULL && evutil_ascii_strcasecmp(connection, "close") == 0);
469 evhttp_is_request_connection_close(struct evhttp_request *req)
472 evhttp_is_connection_close(req->flags, req->input_headers) ||
473 evhttp_is_connection_close(req->flags, req->output_headers);
476 /* Return true iff 'headers' contains 'Connection: keep-alive' */
478 evhttp_is_connection_keepalive(struct evkeyvalq* headers)
480 const char *connection = evhttp_find_header(headers, "Connection");
481 return (connection != NULL
482 && evutil_ascii_strncasecmp(connection, "keep-alive", 10) == 0);
485 /* Add a correct "Date" header to headers, unless it already has one. */
487 evhttp_maybe_add_date_header(struct evkeyvalq *headers)
489 if (evhttp_find_header(headers, "Date") == NULL) {
495 time_t t = time(NULL);
502 if (strftime(date, sizeof(date),
503 "%a, %d %b %Y %H:%M:%S GMT", cur_p) != 0) {
504 evhttp_add_header(headers, "Date", date);
509 /* Add a "Content-Length" header with value 'content_length' to headers,
510 * unless it already has a content-length or transfer-encoding header. */
512 evhttp_maybe_add_content_length_header(struct evkeyvalq *headers,
513 size_t content_length)
515 if (evhttp_find_header(headers, "Transfer-Encoding") == NULL &&
516 evhttp_find_header(headers, "Content-Length") == NULL) {
518 evutil_snprintf(len, sizeof(len), EV_SIZE_FMT,
519 EV_SIZE_ARG(content_length));
520 evhttp_add_header(headers, "Content-Length", len);
525 * Create the headers needed for an HTTP reply in req->output_headers,
526 * and write the first HTTP response for req line to evcon.
529 evhttp_make_header_response(struct evhttp_connection *evcon,
530 struct evhttp_request *req)
532 int is_keepalive = evhttp_is_connection_keepalive(req->input_headers);
533 evbuffer_add_printf(bufferevent_get_output(evcon->bufev),
534 "HTTP/%d.%d %d %s\r\n",
535 req->major, req->minor, req->response_code,
536 req->response_code_line);
538 if (req->major == 1) {
540 evhttp_maybe_add_date_header(req->output_headers);
543 * if the protocol is 1.0; and the connection was keep-alive
544 * we need to add a keep-alive header, too.
546 if (req->minor == 0 && is_keepalive)
547 evhttp_add_header(req->output_headers,
548 "Connection", "keep-alive");
550 if ((req->minor >= 1 || is_keepalive) &&
551 evhttp_response_needs_body(req)) {
553 * we need to add the content length if the
554 * user did not give it, this is required for
555 * persistent connections to work.
557 evhttp_maybe_add_content_length_header(
559 evbuffer_get_length(req->output_buffer));
563 /* Potentially add headers for unidentified content. */
564 if (evhttp_response_needs_body(req)) {
565 if (evhttp_find_header(req->output_headers,
566 "Content-Type") == NULL
567 && evcon->http_server->default_content_type) {
568 evhttp_add_header(req->output_headers,
570 evcon->http_server->default_content_type);
574 /* if the request asked for a close, we send a close, too */
575 if (evhttp_is_connection_close(req->flags, req->input_headers)) {
576 evhttp_remove_header(req->output_headers, "Connection");
577 if (!(req->flags & EVHTTP_PROXY_REQUEST))
578 evhttp_add_header(req->output_headers, "Connection", "close");
579 evhttp_remove_header(req->output_headers, "Proxy-Connection");
583 /** Generate all headers appropriate for sending the http request in req (or
584 * the response, if we're sending a response), and write them to evcon's
585 * bufferevent. Also writes all data from req->output_buffer */
587 evhttp_make_header(struct evhttp_connection *evcon, struct evhttp_request *req)
589 struct evkeyval *header;
590 struct evbuffer *output = bufferevent_get_output(evcon->bufev);
593 * Depending if this is a HTTP request or response, we might need to
594 * add some new headers or remove existing headers.
596 if (req->kind == EVHTTP_REQUEST) {
597 evhttp_make_header_request(evcon, req);
599 evhttp_make_header_response(evcon, req);
602 TAILQ_FOREACH(header, req->output_headers, next) {
603 evbuffer_add_printf(output, "%s: %s\r\n",
604 header->key, header->value);
606 evbuffer_add(output, "\r\n", 2);
608 if (evbuffer_get_length(req->output_buffer) > 0) {
610 * For a request, we add the POST data, for a reply, this
611 * is the regular data.
613 /* XXX We might want to support waiting (a limited amount of
614 time) for a continue status line from the server before
615 sending POST/PUT message bodies. */
616 evbuffer_add_buffer(output, req->output_buffer);
621 evhttp_connection_set_max_headers_size(struct evhttp_connection *evcon,
622 ev_ssize_t new_max_headers_size)
624 if (new_max_headers_size<0)
625 evcon->max_headers_size = EV_SIZE_MAX;
627 evcon->max_headers_size = new_max_headers_size;
630 evhttp_connection_set_max_body_size(struct evhttp_connection* evcon,
631 ev_ssize_t new_max_body_size)
633 if (new_max_body_size<0)
634 evcon->max_body_size = EV_UINT64_MAX;
636 evcon->max_body_size = new_max_body_size;
640 evhttp_connection_incoming_fail(struct evhttp_request *req,
641 enum evhttp_request_error error)
644 case EVREQ_HTTP_TIMEOUT:
647 * these are cases in which we probably should just
648 * close the connection and not send a reply. this
649 * case may happen when a browser keeps a persistent
650 * connection open and we timeout on the read. when
651 * the request is still being used for sending, we
652 * need to disassociated it from the connection here.
654 if (!req->userdone) {
655 /* remove it so that it will not be freed */
656 TAILQ_REMOVE(&req->evcon->requests, req, next);
657 /* indicate that this request no longer has a
663 case EVREQ_HTTP_INVALID_HEADER:
664 case EVREQ_HTTP_BUFFER_ERROR:
665 case EVREQ_HTTP_REQUEST_CANCEL:
666 case EVREQ_HTTP_DATA_TOO_LONG:
667 default: /* xxx: probably should just error on default */
668 /* the callback looks at the uri to determine errors */
673 if (req->uri_elems) {
674 evhttp_uri_free(req->uri_elems);
675 req->uri_elems = NULL;
679 * the callback needs to send a reply, once the reply has
680 * been send, the connection should get freed.
682 (*req->cb)(req, req->cb_arg);
688 /* Free connection ownership of which can be acquired by user using
689 * evhttp_request_own(). */
691 evhttp_request_free_auto(struct evhttp_request *req)
693 if (!(req->flags & EVHTTP_USER_OWNED)) {
694 evhttp_request_free(req);
699 evhttp_request_free_(struct evhttp_connection *evcon, struct evhttp_request *req)
701 TAILQ_REMOVE(&evcon->requests, req, next);
702 evhttp_request_free_auto(req);
705 /* Called when evcon has experienced a (non-recoverable? -NM) error, as
706 * given in error. If it's an outgoing connection, reset the connection,
707 * retry any pending requests, and inform the user. If it's incoming,
708 * delegates to evhttp_connection_incoming_fail(). */
710 evhttp_connection_fail_(struct evhttp_connection *evcon,
711 enum evhttp_request_error error)
713 const int errsave = EVUTIL_SOCKET_ERROR();
714 struct evhttp_request* req = TAILQ_FIRST(&evcon->requests);
715 void (*cb)(struct evhttp_request *, void *);
717 void (*error_cb)(enum evhttp_request_error, void *);
719 EVUTIL_ASSERT(req != NULL);
721 bufferevent_disable(evcon->bufev, EV_READ|EV_WRITE);
723 if (evcon->flags & EVHTTP_CON_INCOMING) {
725 * for incoming requests, there are two different
726 * failure cases. it's either a network level error
727 * or an http layer error. for problems on the network
728 * layer like timeouts we just drop the connections.
729 * For HTTP problems, we might have to send back a
730 * reply before the connection can be freed.
732 if (evhttp_connection_incoming_fail(req, error) == -1)
733 evhttp_connection_free(evcon);
737 error_cb = req->error_cb;
738 error_cb_arg = req->cb_arg;
739 /* when the request was canceled, the callback is not executed */
740 if (error != EVREQ_HTTP_REQUEST_CANCEL) {
741 /* save the callback for later; the cb might free our object */
743 cb_arg = req->cb_arg;
749 /* do not fail all requests; the next request is going to get
750 * send over a new connection. when a user cancels a request,
751 * all other pending requests should be processed as normal
753 evhttp_request_free_(evcon, req);
755 /* reset the connection */
756 evhttp_connection_reset_(evcon);
758 /* We are trying the next request that was queued on us */
759 if (TAILQ_FIRST(&evcon->requests) != NULL)
760 evhttp_connection_connect_(evcon);
762 /* The call to evhttp_connection_reset_ overwrote errno.
763 * Let's restore the original errno, so that the user's
764 * callback can have a better idea of what the error was.
766 EVUTIL_SET_SOCKET_ERROR(errsave);
768 /* inform the user */
769 if (error_cb != NULL)
770 error_cb(error, error_cb_arg);
775 /* Bufferevent callback: invoked when any data has been written from an
776 * http connection's bufferevent */
778 evhttp_write_cb(struct bufferevent *bufev, void *arg)
780 struct evhttp_connection *evcon = arg;
782 /* Activate our call back */
783 if (evcon->cb != NULL)
784 (*evcon->cb)(evcon, evcon->cb_arg);
788 * Advance the connection state.
789 * - If this is an outgoing connection, we've just processed the response;
790 * idle or close the connection.
791 * - If this is an incoming connection, we've just processed the request;
795 evhttp_connection_done(struct evhttp_connection *evcon)
797 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
798 int con_outgoing = evcon->flags & EVHTTP_CON_OUTGOING;
802 /* idle or close the connection */
803 int need_close = evhttp_is_request_connection_close(req);
804 TAILQ_REMOVE(&evcon->requests, req, next);
807 evcon->state = EVCON_IDLE;
809 /* check if we got asked to close the connection */
811 evhttp_connection_reset_(evcon);
813 if (TAILQ_FIRST(&evcon->requests) != NULL) {
815 * We have more requests; reset the connection
816 * and deal with the next request.
818 if (!evhttp_connected(evcon))
819 evhttp_connection_connect_(evcon);
821 evhttp_request_dispatch(evcon);
822 } else if (!need_close) {
824 * The connection is going to be persistent, but we
825 * need to detect if the other side closes it.
827 evhttp_connection_start_detectclose(evcon);
828 } else if ((evcon->flags & EVHTTP_CON_AUTOFREE)) {
830 * If we have no more requests that need completion
831 * and we're not waiting for the connection to close
837 * incoming connection - we need to leave the request on the
838 * connection so that we can reply to it.
840 evcon->state = EVCON_WRITING;
843 /* notify the user of the request */
844 (*req->cb)(req, req->cb_arg);
846 /* if this was an outgoing request, we own and it's done. so free it. */
848 evhttp_request_free_auto(req);
851 /* If this was the last request of an outgoing connection and we're
852 * not waiting to receive a connection close event and we want to
853 * automatically free the connection. We check to ensure our request
854 * list is empty one last time just in case our callback added a
857 if (free_evcon && TAILQ_FIRST(&evcon->requests) == NULL) {
858 evhttp_connection_free(evcon);
863 * Handles reading from a chunked request.
864 * return ALL_DATA_READ:
865 * all data has been read
866 * return MORE_DATA_EXPECTED:
867 * more data is expected
868 * return DATA_CORRUPTED:
870 * return REQUEST_CANCELED:
871 * request was canceled by the user calling evhttp_cancel_request
872 * return DATA_TOO_LONG:
873 * ran over the maximum limit
876 static enum message_read_status
877 evhttp_handle_chunked_read(struct evhttp_request *req, struct evbuffer *buf)
879 if (req == NULL || buf == NULL) {
880 return DATA_CORRUPTED;
886 if ((buflen = evbuffer_get_length(buf)) == 0) {
890 /* evbuffer_get_length returns size_t, but len variable is ssize_t,
891 * check for overflow conditions */
892 if (buflen > EV_SSIZE_MAX) {
893 return DATA_CORRUPTED;
896 if (req->ntoread < 0) {
897 /* Read chunk size */
899 char *p = evbuffer_readln(buf, NULL, EVBUFFER_EOL_CRLF);
904 /* the last chunk is on a new line? */
905 if (strlen(p) == 0) {
909 ntoread = evutil_strtoll(p, &endp, 16);
910 error = (*p == '\0' ||
911 (*endp != '\0' && *endp != ' ') ||
915 /* could not get chunk size */
916 return (DATA_CORRUPTED);
919 /* ntoread is signed int64, body_size is unsigned size_t, check for under/overflow conditions */
920 if ((ev_uint64_t)ntoread > EV_SIZE_MAX - req->body_size) {
921 return DATA_CORRUPTED;
924 if (req->body_size + (size_t)ntoread > req->evcon->max_body_size) {
925 /* failed body length test */
926 event_debug(("Request body is too long"));
927 return (DATA_TOO_LONG);
930 req->body_size += (size_t)ntoread;
931 req->ntoread = ntoread;
932 if (req->ntoread == 0) {
934 return (ALL_DATA_READ);
939 /* req->ntoread is signed int64, len is ssize_t, based on arch,
940 * ssize_t could only be 32b, check for these conditions */
941 if (req->ntoread > EV_SSIZE_MAX) {
942 return DATA_CORRUPTED;
945 /* don't have enough to complete a chunk; wait for more */
946 if (req->ntoread > 0 && buflen < (ev_uint64_t)req->ntoread)
947 return (MORE_DATA_EXPECTED);
949 /* Completed chunk */
950 evbuffer_remove_buffer(buf, req->input_buffer, (size_t)req->ntoread);
952 if (req->chunk_cb != NULL) {
953 req->flags |= EVHTTP_REQ_DEFER_FREE;
954 (*req->chunk_cb)(req, req->cb_arg);
955 evbuffer_drain(req->input_buffer,
956 evbuffer_get_length(req->input_buffer));
957 req->flags &= ~EVHTTP_REQ_DEFER_FREE;
958 if ((req->flags & EVHTTP_REQ_NEEDS_FREE) != 0) {
959 return (REQUEST_CANCELED);
964 return (MORE_DATA_EXPECTED);
968 evhttp_read_trailer(struct evhttp_connection *evcon, struct evhttp_request *req)
970 struct evbuffer *buf = bufferevent_get_input(evcon->bufev);
972 switch (evhttp_parse_headers_(req, buf)) {
975 evhttp_connection_fail_(evcon, EVREQ_HTTP_DATA_TOO_LONG);
978 bufferevent_disable(evcon->bufev, EV_READ);
979 evhttp_connection_done(evcon);
981 case MORE_DATA_EXPECTED:
982 case REQUEST_CANCELED: /* ??? */
989 evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
991 struct evbuffer *buf = bufferevent_get_input(evcon->bufev);
994 switch (evhttp_handle_chunked_read(req, buf)) {
996 /* finished last chunk */
997 evcon->state = EVCON_READING_TRAILER;
998 evhttp_read_trailer(evcon, req);
1000 case DATA_CORRUPTED:
1002 /* corrupted data */
1003 evhttp_connection_fail_(evcon,
1004 EVREQ_HTTP_DATA_TOO_LONG);
1006 case REQUEST_CANCELED:
1007 /* request canceled */
1008 evhttp_request_free_auto(req);
1010 case MORE_DATA_EXPECTED:
1014 } else if (req->ntoread < 0) {
1015 /* Read until connection close. */
1016 if ((size_t)(req->body_size + evbuffer_get_length(buf)) < req->body_size) {
1017 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
1021 req->body_size += evbuffer_get_length(buf);
1022 evbuffer_add_buffer(req->input_buffer, buf);
1023 } else if (req->chunk_cb != NULL || evbuffer_get_length(buf) >= (size_t)req->ntoread) {
1024 /* XXX: the above get_length comparison has to be fixed for overflow conditions! */
1025 /* We've postponed moving the data until now, but we're
1026 * about to use it. */
1027 size_t n = evbuffer_get_length(buf);
1029 if (n > (size_t) req->ntoread)
1030 n = (size_t) req->ntoread;
1032 req->body_size += n;
1033 evbuffer_remove_buffer(buf, req->input_buffer, n);
1036 if (req->body_size > req->evcon->max_body_size ||
1037 (!req->chunked && req->ntoread >= 0 &&
1038 (size_t)req->ntoread > req->evcon->max_body_size)) {
1039 /* XXX: The above casted comparison must checked for overflow */
1040 /* failed body length test */
1041 event_debug(("Request body is too long"));
1042 evhttp_connection_fail_(evcon,
1043 EVREQ_HTTP_DATA_TOO_LONG);
1047 if (evbuffer_get_length(req->input_buffer) > 0 && req->chunk_cb != NULL) {
1048 req->flags |= EVHTTP_REQ_DEFER_FREE;
1049 (*req->chunk_cb)(req, req->cb_arg);
1050 req->flags &= ~EVHTTP_REQ_DEFER_FREE;
1051 evbuffer_drain(req->input_buffer,
1052 evbuffer_get_length(req->input_buffer));
1053 if ((req->flags & EVHTTP_REQ_NEEDS_FREE) != 0) {
1054 evhttp_request_free_auto(req);
1059 if (req->ntoread == 0) {
1060 bufferevent_disable(evcon->bufev, EV_READ);
1061 /* Completed content length */
1062 evhttp_connection_done(evcon);
1067 #define get_deferred_queue(evcon) \
1071 * Gets called when more data becomes available
1075 evhttp_read_cb(struct bufferevent *bufev, void *arg)
1077 struct evhttp_connection *evcon = arg;
1078 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1080 /* Cancel if it's pending. */
1081 event_deferred_cb_cancel_(get_deferred_queue(evcon),
1082 &evcon->read_more_deferred_cb);
1084 switch (evcon->state) {
1085 case EVCON_READING_FIRSTLINE:
1086 evhttp_read_firstline(evcon, req);
1087 /* note the request may have been freed in
1088 * evhttp_read_body */
1090 case EVCON_READING_HEADERS:
1091 evhttp_read_header(evcon, req);
1092 /* note the request may have been freed in
1093 * evhttp_read_body */
1095 case EVCON_READING_BODY:
1096 evhttp_read_body(evcon, req);
1097 /* note the request may have been freed in
1098 * evhttp_read_body */
1100 case EVCON_READING_TRAILER:
1101 evhttp_read_trailer(evcon, req);
1106 struct evbuffer *input;
1109 input = bufferevent_get_input(evcon->bufev);
1110 total_len = evbuffer_get_length(input);
1111 event_debug(("%s: read "EV_SIZE_FMT
1112 " bytes in EVCON_IDLE state,"
1113 " resetting connection",
1114 __func__, EV_SIZE_ARG(total_len)));
1117 evhttp_connection_reset_(evcon);
1120 case EVCON_DISCONNECTED:
1121 case EVCON_CONNECTING:
1124 event_errx(1, "%s: illegal connection state %d",
1125 __func__, evcon->state);
1130 evhttp_deferred_read_cb(struct event_callback *cb, void *data)
1132 struct evhttp_connection *evcon = data;
1133 evhttp_read_cb(evcon->bufev, evcon);
1137 evhttp_write_connectioncb(struct evhttp_connection *evcon, void *arg)
1139 /* This is after writing the request to the server */
1140 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1141 EVUTIL_ASSERT(req != NULL);
1143 EVUTIL_ASSERT(evcon->state == EVCON_WRITING);
1145 /* We need to wait until we've written all of our output data before we can continue */
1146 if (evbuffer_get_length(bufferevent_get_output(evcon->bufev)) > 0) { return; }
1148 /* We are done writing our header and are now expecting the response */
1149 req->kind = EVHTTP_RESPONSE;
1151 evhttp_start_read_(evcon);
1155 * Clean up a connection object
1159 evhttp_connection_free(struct evhttp_connection *evcon)
1161 struct evhttp_request *req;
1163 /* notify interested parties that this connection is going down */
1164 if (evcon->fd != -1) {
1165 if (evhttp_connected(evcon) && evcon->closecb != NULL)
1166 (*evcon->closecb)(evcon, evcon->closecb_arg);
1169 /* remove all requests that might be queued on this
1170 * connection. for server connections, this should be empty.
1171 * because it gets dequeued either in evhttp_connection_done or
1172 * evhttp_connection_fail_.
1174 while ((req = TAILQ_FIRST(&evcon->requests)) != NULL) {
1175 evhttp_request_free_(evcon, req);
1178 if (evcon->http_server != NULL) {
1179 struct evhttp *http = evcon->http_server;
1180 TAILQ_REMOVE(&http->connections, evcon, next);
1183 if (event_initialized(&evcon->retry_ev)) {
1184 event_del(&evcon->retry_ev);
1185 event_debug_unassign(&evcon->retry_ev);
1188 if (evcon->bufev != NULL)
1189 bufferevent_free(evcon->bufev);
1191 event_deferred_cb_cancel_(get_deferred_queue(evcon),
1192 &evcon->read_more_deferred_cb);
1194 if (evcon->fd != -1) {
1195 shutdown(evcon->fd, EVUTIL_SHUT_WR);
1196 if (!(bufferevent_get_options_(evcon->bufev) & BEV_OPT_CLOSE_ON_FREE)) {
1197 evutil_closesocket(evcon->fd);
1201 if (evcon->bind_address != NULL)
1202 mm_free(evcon->bind_address);
1204 if (evcon->address != NULL)
1205 mm_free(evcon->address);
1211 evhttp_connection_free_on_completion(struct evhttp_connection *evcon) {
1212 evcon->flags |= EVHTTP_CON_AUTOFREE;
1216 evhttp_connection_set_local_address(struct evhttp_connection *evcon,
1217 const char *address)
1219 EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED);
1220 if (evcon->bind_address)
1221 mm_free(evcon->bind_address);
1222 if ((evcon->bind_address = mm_strdup(address)) == NULL)
1223 event_warn("%s: strdup", __func__);
1227 evhttp_connection_set_local_port(struct evhttp_connection *evcon,
1230 EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED);
1231 evcon->bind_port = port;
1235 evhttp_request_dispatch(struct evhttp_connection* evcon)
1237 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1239 /* this should not usually happy but it's possible */
1243 /* delete possible close detection events */
1244 evhttp_connection_stop_detectclose(evcon);
1246 /* we assume that the connection is connected already */
1247 EVUTIL_ASSERT(evcon->state == EVCON_IDLE);
1249 evcon->state = EVCON_WRITING;
1251 /* Create the header from the store arguments */
1252 evhttp_make_header(evcon, req);
1254 evhttp_write_buffer(evcon, evhttp_write_connectioncb, NULL);
1257 /* Reset our connection state: disables reading/writing, closes our fd (if
1258 * any), clears out buffers, and puts us in state DISCONNECTED. */
1260 evhttp_connection_reset_(struct evhttp_connection *evcon)
1262 struct evbuffer *tmp;
1264 /* XXXX This is not actually an optimal fix. Instead we ought to have
1265 an API for "stop connecting", or use bufferevent_setfd to turn off
1266 connecting. But for Libevent 2.0, this seems like a minimal change
1267 least likely to disrupt the rest of the bufferevent and http code.
1269 Why is this here? If the fd is set in the bufferevent, and the
1270 bufferevent is connecting, then you can't actually stop the
1271 bufferevent from trying to connect with bufferevent_disable(). The
1272 connect will never trigger, since we close the fd, but the timeout
1273 might. That caused an assertion failure in evhttp_connection_fail_.
1275 bufferevent_disable_hard_(evcon->bufev, EV_READ|EV_WRITE);
1277 if (evcon->fd != -1) {
1278 /* inform interested parties about connection close */
1279 if (evhttp_connected(evcon) && evcon->closecb != NULL)
1280 (*evcon->closecb)(evcon, evcon->closecb_arg);
1282 shutdown(evcon->fd, EVUTIL_SHUT_WR);
1283 evutil_closesocket(evcon->fd);
1284 bufferevent_setfd(evcon->bufev, -1);
1288 /* we need to clean up any buffered data */
1289 tmp = bufferevent_get_output(evcon->bufev);
1290 evbuffer_drain(tmp, evbuffer_get_length(tmp));
1291 tmp = bufferevent_get_input(evcon->bufev);
1292 evbuffer_drain(tmp, evbuffer_get_length(tmp));
1294 evcon->state = EVCON_DISCONNECTED;
1298 evhttp_connection_start_detectclose(struct evhttp_connection *evcon)
1300 evcon->flags |= EVHTTP_CON_CLOSEDETECT;
1302 bufferevent_enable(evcon->bufev, EV_READ);
1306 evhttp_connection_stop_detectclose(struct evhttp_connection *evcon)
1308 evcon->flags &= ~EVHTTP_CON_CLOSEDETECT;
1310 bufferevent_disable(evcon->bufev, EV_READ);
1314 evhttp_connection_retry(evutil_socket_t fd, short what, void *arg)
1316 struct evhttp_connection *evcon = arg;
1318 evcon->state = EVCON_DISCONNECTED;
1319 evhttp_connection_connect_(evcon);
1323 evhttp_connection_cb_cleanup(struct evhttp_connection *evcon)
1325 struct evcon_requestq requests;
1327 evhttp_connection_reset_(evcon);
1328 if (evcon->retry_max < 0 || evcon->retry_cnt < evcon->retry_max) {
1329 struct timeval tv_retry = evcon->initial_retry_timeout;
1331 evtimer_assign(&evcon->retry_ev, evcon->base, evhttp_connection_retry, evcon);
1332 /* XXXX handle failure from evhttp_add_event */
1333 for (i=0; i < evcon->retry_cnt; ++i) {
1334 tv_retry.tv_usec *= 2;
1335 if (tv_retry.tv_usec > 1000000) {
1336 tv_retry.tv_usec -= 1000000;
1337 tv_retry.tv_sec += 1;
1339 tv_retry.tv_sec *= 2;
1340 if (tv_retry.tv_sec > 3600) {
1341 tv_retry.tv_sec = 3600;
1342 tv_retry.tv_usec = 0;
1345 event_add(&evcon->retry_ev, &tv_retry);
1351 * User callback can do evhttp_make_request() on the same
1352 * evcon so new request will be added to evcon->requests. To
1353 * avoid freeing it prematurely we iterate over the copy of
1356 TAILQ_INIT(&requests);
1357 while (TAILQ_FIRST(&evcon->requests) != NULL) {
1358 struct evhttp_request *request = TAILQ_FIRST(&evcon->requests);
1359 TAILQ_REMOVE(&evcon->requests, request, next);
1360 TAILQ_INSERT_TAIL(&requests, request, next);
1363 /* for now, we just signal all requests by executing their callbacks */
1364 while (TAILQ_FIRST(&requests) != NULL) {
1365 struct evhttp_request *request = TAILQ_FIRST(&requests);
1366 TAILQ_REMOVE(&requests, request, next);
1367 request->evcon = NULL;
1369 /* we might want to set an error here */
1370 request->cb(request, request->cb_arg);
1371 evhttp_request_free_auto(request);
1376 evhttp_error_cb(struct bufferevent *bufev, short what, void *arg)
1378 struct evhttp_connection *evcon = arg;
1379 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1381 if (evcon->fd == -1)
1382 evcon->fd = bufferevent_getfd(bufev);
1384 switch (evcon->state) {
1385 case EVCON_CONNECTING:
1386 if (what & BEV_EVENT_TIMEOUT) {
1387 event_debug(("%s: connection timeout for \"%s:%d\" on "
1389 __func__, evcon->address, evcon->port,
1390 EV_SOCK_ARG(evcon->fd)));
1391 evhttp_connection_cb_cleanup(evcon);
1396 case EVCON_READING_BODY:
1397 if (!req->chunked && req->ntoread < 0
1398 && what == (BEV_EVENT_READING|BEV_EVENT_EOF)) {
1399 /* EOF on read can be benign */
1400 evhttp_connection_done(evcon);
1405 case EVCON_DISCONNECTED:
1407 case EVCON_READING_FIRSTLINE:
1408 case EVCON_READING_HEADERS:
1409 case EVCON_READING_TRAILER:
1415 /* when we are in close detect mode, a read error means that
1416 * the other side closed their connection.
1418 if (evcon->flags & EVHTTP_CON_CLOSEDETECT) {
1419 evcon->flags &= ~EVHTTP_CON_CLOSEDETECT;
1420 EVUTIL_ASSERT(evcon->http_server == NULL);
1421 /* For connections from the client, we just
1422 * reset the connection so that it becomes
1425 EVUTIL_ASSERT(evcon->state == EVCON_IDLE);
1426 evhttp_connection_reset_(evcon);
1429 * If we have no more requests that need completion
1430 * and we want to auto-free the connection when all
1431 * requests have been completed.
1433 if (TAILQ_FIRST(&evcon->requests) == NULL
1434 && (evcon->flags & EVHTTP_CON_OUTGOING)
1435 && (evcon->flags & EVHTTP_CON_AUTOFREE)) {
1436 evhttp_connection_free(evcon);
1441 if (what & BEV_EVENT_TIMEOUT) {
1442 evhttp_connection_fail_(evcon, EVREQ_HTTP_TIMEOUT);
1443 } else if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
1444 evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
1445 } else if (what == BEV_EVENT_CONNECTED) {
1447 evhttp_connection_fail_(evcon, EVREQ_HTTP_BUFFER_ERROR);
1452 * Event callback for asynchronous connection attempt.
1455 evhttp_connection_cb(struct bufferevent *bufev, short what, void *arg)
1457 struct evhttp_connection *evcon = arg;
1459 ev_socklen_t errsz = sizeof(error);
1461 if (evcon->fd == -1)
1462 evcon->fd = bufferevent_getfd(bufev);
1464 if (!(what & BEV_EVENT_CONNECTED)) {
1465 /* some operating systems return ECONNREFUSED immediately
1466 * when connecting to a local address. the cleanup is going
1467 * to reschedule this function call.
1470 if (errno == ECONNREFUSED)
1473 evhttp_error_cb(bufev, what, arg);
1477 if (evcon->fd == -1) {
1478 event_debug(("%s: bufferevent_getfd returned -1",
1483 /* Check if the connection completed */
1484 if (getsockopt(evcon->fd, SOL_SOCKET, SO_ERROR, (void*)&error,
1486 event_debug(("%s: getsockopt for \"%s:%d\" on "EV_SOCK_FMT,
1487 __func__, evcon->address, evcon->port,
1488 EV_SOCK_ARG(evcon->fd)));
1493 event_debug(("%s: connect failed for \"%s:%d\" on "
1495 __func__, evcon->address, evcon->port,
1496 EV_SOCK_ARG(evcon->fd),
1497 evutil_socket_error_to_string(error)));
1501 /* We are connected to the server now */
1502 event_debug(("%s: connected to \"%s:%d\" on "EV_SOCK_FMT"\n",
1503 __func__, evcon->address, evcon->port,
1504 EV_SOCK_ARG(evcon->fd)));
1506 /* Reset the retry count as we were successful in connecting */
1507 evcon->retry_cnt = 0;
1508 evcon->state = EVCON_IDLE;
1510 /* reset the bufferevent cbs */
1511 bufferevent_setcb(evcon->bufev,
1517 if (!evutil_timerisset(&evcon->timeout)) {
1518 const struct timeval read_tv = { HTTP_READ_TIMEOUT, 0 };
1519 const struct timeval write_tv = { HTTP_WRITE_TIMEOUT, 0 };
1520 bufferevent_set_timeouts(evcon->bufev, &read_tv, &write_tv);
1522 bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
1525 /* try to start requests that have queued up on this connection */
1526 evhttp_request_dispatch(evcon);
1530 evhttp_connection_cb_cleanup(evcon);
1534 * Check if we got a valid response code.
1538 evhttp_valid_response_code(int code)
1547 evhttp_parse_http_version(const char *version, struct evhttp_request *req)
1551 int n = sscanf(version, "HTTP/%d.%d%c", &major, &minor, &ch);
1552 if (n != 2 || major > 1) {
1553 event_debug(("%s: bad version %s on message %p from %s",
1554 __func__, version, req, req->remote_host));
1562 /* Parses the status line of a web server */
1565 evhttp_parse_response_line(struct evhttp_request *req, char *line)
1569 const char *readable = "";
1571 protocol = strsep(&line, " ");
1574 number = strsep(&line, " ");
1578 if (evhttp_parse_http_version(protocol, req) < 0)
1581 req->response_code = atoi(number);
1582 if (!evhttp_valid_response_code(req->response_code)) {
1583 event_debug(("%s: bad response code \"%s\"",
1588 if ((req->response_code_line = mm_strdup(readable)) == NULL) {
1589 event_warn("%s: strdup", __func__);
1596 /* Parse the first line of a HTTP request */
1599 evhttp_parse_request_line(struct evhttp_request *req, char *line)
1604 const char *hostname;
1607 enum evhttp_cmd_type type;
1609 /* Parse the request line */
1610 method = strsep(&line, " ");
1613 uri = strsep(&line, " ");
1616 version = strsep(&line, " ");
1620 method_len = (uri - method) - 1;
1621 type = EVHTTP_REQ_UNKNOWN_;
1624 switch (method_len) {
1626 /* The length of the method string is 3, meaning it can only be one of two methods: GET or PUT */
1628 /* Since both GET and PUT share the same character 'T' at the end,
1629 * if the string doesn't have 'T', we can immediately determine this
1630 * is an invalid HTTP method */
1632 if (method[2] != 'T') {
1638 /* This first byte is 'G', so make sure the next byte is
1639 * 'E', if it isn't then this isn't a valid method */
1641 if (method[1] == 'E') {
1642 type = EVHTTP_REQ_GET;
1647 /* First byte is P, check second byte for 'U', if not,
1648 * we know it's an invalid method */
1649 if (method[1] == 'U') {
1650 type = EVHTTP_REQ_PUT;
1658 /* The method length is 4 bytes, leaving only the methods "POST" and "HEAD" */
1661 if (method[3] == 'T' && method[2] == 'S' && method[1] == 'O') {
1662 type = EVHTTP_REQ_POST;
1666 if (method[3] == 'D' && method[2] == 'A' && method[1] == 'E') {
1667 type = EVHTTP_REQ_HEAD;
1675 /* Method length is 5 bytes, which can only encompass PATCH and TRACE */
1678 if (method[4] == 'H' && method[3] == 'C' && method[2] == 'T' && method[1] == 'A') {
1679 type = EVHTTP_REQ_PATCH;
1683 if (method[4] == 'E' && method[3] == 'C' && method[2] == 'A' && method[1] == 'R') {
1684 type = EVHTTP_REQ_TRACE;
1693 /* Method length is 6, only valid method 6 bytes in length is DELEte */
1695 /* If the first byte isn't 'D' then it's invalid */
1696 if (*method != 'D') {
1700 if (method[5] == 'E' && method[4] == 'T' && method[3] == 'E' && method[2] == 'L' && method[1] == 'E') {
1701 type = EVHTTP_REQ_DELETE;
1706 /* Method length is 7, only valid methods are "OPTIONS" and "CONNECT" */
1709 if (method[6] == 'S' && method[5] == 'N' && method[4] == 'O' &&
1710 method[3] == 'I' && method[2] == 'T' && method[1] == 'P') {
1711 type = EVHTTP_REQ_OPTIONS;
1716 if (method[6] == 'T' && method[5] == 'C' && method[4] == 'E' &&
1717 method[3] == 'N' && method[2] == 'N' && method[1] == 'O') {
1718 type = EVHTTP_REQ_CONNECT;
1728 if ((int)type == EVHTTP_REQ_UNKNOWN_) {
1729 event_debug(("%s: bad method %s on request %p from %s",
1730 __func__, method, req, req->remote_host));
1731 /* No error yet; we'll give a better error later when
1732 * we see that req->type is unsupported. */
1737 if (evhttp_parse_http_version(version, req) < 0)
1740 if ((req->uri = mm_strdup(uri)) == NULL) {
1741 event_debug(("%s: mm_strdup", __func__));
1745 if ((req->uri_elems = evhttp_uri_parse_with_flags(req->uri,
1746 EVHTTP_URI_NONCONFORMANT)) == NULL) {
1750 /* If we have an absolute-URI, check to see if it is an http request
1751 for a known vhost or server alias. If we don't know about this
1752 host, we consider it a proxy request. */
1753 scheme = evhttp_uri_get_scheme(req->uri_elems);
1754 hostname = evhttp_uri_get_host(req->uri_elems);
1755 if (scheme && (!evutil_ascii_strcasecmp(scheme, "http") ||
1756 !evutil_ascii_strcasecmp(scheme, "https")) &&
1758 !evhttp_find_vhost(req->evcon->http_server, NULL, hostname))
1759 req->flags |= EVHTTP_PROXY_REQUEST;
1765 evhttp_find_header(const struct evkeyvalq *headers, const char *key)
1767 struct evkeyval *header;
1769 TAILQ_FOREACH(header, headers, next) {
1770 if (evutil_ascii_strcasecmp(header->key, key) == 0)
1771 return (header->value);
1778 evhttp_clear_headers(struct evkeyvalq *headers)
1780 struct evkeyval *header;
1782 for (header = TAILQ_FIRST(headers);
1784 header = TAILQ_FIRST(headers)) {
1785 TAILQ_REMOVE(headers, header, next);
1786 mm_free(header->key);
1787 mm_free(header->value);
1793 * Returns 0, if the header was successfully removed.
1794 * Returns -1, if the header could not be found.
1798 evhttp_remove_header(struct evkeyvalq *headers, const char *key)
1800 struct evkeyval *header;
1802 TAILQ_FOREACH(header, headers, next) {
1803 if (evutil_ascii_strcasecmp(header->key, key) == 0)
1810 /* Free and remove the header that we found */
1811 TAILQ_REMOVE(headers, header, next);
1812 mm_free(header->key);
1813 mm_free(header->value);
1820 evhttp_header_is_valid_value(const char *value)
1822 const char *p = value;
1824 while ((p = strpbrk(p, "\r\n")) != NULL) {
1825 /* we really expect only one new line */
1826 p += strspn(p, "\r\n");
1827 /* we expect a space or tab for continuation */
1828 if (*p != ' ' && *p != '\t')
1835 evhttp_add_header(struct evkeyvalq *headers,
1836 const char *key, const char *value)
1838 event_debug(("%s: key: %s val: %s\n", __func__, key, value));
1840 if (strchr(key, '\r') != NULL || strchr(key, '\n') != NULL) {
1841 /* drop illegal headers */
1842 event_debug(("%s: dropping illegal header key\n", __func__));
1846 if (!evhttp_header_is_valid_value(value)) {
1847 event_debug(("%s: dropping illegal header value\n", __func__));
1851 return (evhttp_add_header_internal(headers, key, value));
1855 evhttp_add_header_internal(struct evkeyvalq *headers,
1856 const char *key, const char *value)
1858 struct evkeyval *header = mm_calloc(1, sizeof(struct evkeyval));
1859 if (header == NULL) {
1860 event_warn("%s: calloc", __func__);
1863 if ((header->key = mm_strdup(key)) == NULL) {
1865 event_warn("%s: strdup", __func__);
1868 if ((header->value = mm_strdup(value)) == NULL) {
1869 mm_free(header->key);
1871 event_warn("%s: strdup", __func__);
1875 TAILQ_INSERT_TAIL(headers, header, next);
1881 * Parses header lines from a request or a response into the specified
1882 * request object given an event buffer.
1885 * DATA_CORRUPTED on error
1886 * MORE_DATA_EXPECTED when we need to read more headers
1887 * ALL_DATA_READ when all headers have been read.
1890 enum message_read_status
1891 evhttp_parse_firstline_(struct evhttp_request *req, struct evbuffer *buffer)
1894 enum message_read_status status = ALL_DATA_READ;
1898 line = evbuffer_readln(buffer, &line_length, EVBUFFER_EOL_CRLF);
1900 if (req->evcon != NULL &&
1901 evbuffer_get_length(buffer) > req->evcon->max_headers_size)
1902 return (DATA_TOO_LONG);
1904 return (MORE_DATA_EXPECTED);
1907 if (req->evcon != NULL &&
1908 line_length > req->evcon->max_headers_size) {
1910 return (DATA_TOO_LONG);
1913 req->headers_size = line_length;
1915 switch (req->kind) {
1916 case EVHTTP_REQUEST:
1917 if (evhttp_parse_request_line(req, line) == -1)
1918 status = DATA_CORRUPTED;
1920 case EVHTTP_RESPONSE:
1921 if (evhttp_parse_response_line(req, line) == -1)
1922 status = DATA_CORRUPTED;
1925 status = DATA_CORRUPTED;
1933 evhttp_append_to_last_header(struct evkeyvalq *headers, char *line)
1935 struct evkeyval *header = TAILQ_LAST(headers, evkeyvalq);
1937 size_t old_len, line_len;
1942 old_len = strlen(header->value);
1944 /* Strip space from start and end of line. */
1945 while (*line == ' ' || *line == '\t')
1947 evutil_rtrim_lws_(line);
1949 line_len = strlen(line);
1951 newval = mm_realloc(header->value, old_len + line_len + 2);
1955 newval[old_len] = ' ';
1956 memcpy(newval + old_len + 1, line, line_len + 1);
1957 header->value = newval;
1962 enum message_read_status
1963 evhttp_parse_headers_(struct evhttp_request *req, struct evbuffer* buffer)
1965 enum message_read_status errcode = DATA_CORRUPTED;
1967 enum message_read_status status = MORE_DATA_EXPECTED;
1969 struct evkeyvalq* headers = req->input_headers;
1971 while ((line = evbuffer_readln(buffer, &line_length, EVBUFFER_EOL_CRLF))
1973 char *skey, *svalue;
1975 req->headers_size += line_length;
1977 if (req->evcon != NULL &&
1978 req->headers_size > req->evcon->max_headers_size) {
1979 errcode = DATA_TOO_LONG;
1983 if (*line == '\0') { /* Last header - Done */
1984 status = ALL_DATA_READ;
1989 /* Check if this is a continuation line */
1990 if (*line == ' ' || *line == '\t') {
1991 if (evhttp_append_to_last_header(headers, line) == -1)
1997 /* Processing of header lines */
1999 skey = strsep(&svalue, ":");
2003 svalue += strspn(svalue, " ");
2004 evutil_rtrim_lws_(svalue);
2006 if (evhttp_add_header(headers, skey, svalue) == -1)
2012 if (status == MORE_DATA_EXPECTED) {
2013 if (req->evcon != NULL &&
2014 req->headers_size + evbuffer_get_length(buffer) > req->evcon->max_headers_size)
2015 return (DATA_TOO_LONG);
2026 evhttp_get_body_length(struct evhttp_request *req)
2028 struct evkeyvalq *headers = req->input_headers;
2029 const char *content_length;
2030 const char *connection;
2032 content_length = evhttp_find_header(headers, "Content-Length");
2033 connection = evhttp_find_header(headers, "Connection");
2035 if (content_length == NULL && connection == NULL)
2037 else if (content_length == NULL &&
2038 evutil_ascii_strcasecmp(connection, "Close") != 0) {
2039 /* Bad combination, we don't know when it will end */
2040 event_warnx("%s: we got no content length, but the "
2041 "server wants to keep the connection open: %s.",
2042 __func__, connection);
2044 } else if (content_length == NULL) {
2048 ev_int64_t ntoread = evutil_strtoll(content_length, &endp, 10);
2049 if (*content_length == '\0' || *endp != '\0' || ntoread < 0) {
2050 event_debug(("%s: illegal content length: %s",
2051 __func__, content_length));
2054 req->ntoread = ntoread;
2057 event_debug(("%s: bytes to read: "EV_I64_FMT" (in buffer "EV_SIZE_FMT")\n",
2058 __func__, EV_I64_ARG(req->ntoread),
2059 EV_SIZE_ARG(evbuffer_get_length(bufferevent_get_input(req->evcon->bufev)))));
2065 evhttp_method_may_have_body(enum evhttp_cmd_type type)
2068 case EVHTTP_REQ_POST:
2069 case EVHTTP_REQ_PUT:
2070 case EVHTTP_REQ_PATCH:
2072 case EVHTTP_REQ_TRACE:
2074 /* XXX May any of the below methods have a body? */
2075 case EVHTTP_REQ_GET:
2076 case EVHTTP_REQ_HEAD:
2077 case EVHTTP_REQ_DELETE:
2078 case EVHTTP_REQ_OPTIONS:
2079 case EVHTTP_REQ_CONNECT:
2087 evhttp_get_body(struct evhttp_connection *evcon, struct evhttp_request *req)
2089 const char *xfer_enc;
2091 /* If this is a request without a body, then we are done */
2092 if (req->kind == EVHTTP_REQUEST &&
2093 !evhttp_method_may_have_body(req->type)) {
2094 evhttp_connection_done(evcon);
2097 evcon->state = EVCON_READING_BODY;
2098 xfer_enc = evhttp_find_header(req->input_headers, "Transfer-Encoding");
2099 if (xfer_enc != NULL && evutil_ascii_strcasecmp(xfer_enc, "chunked") == 0) {
2103 if (evhttp_get_body_length(req) == -1) {
2104 evhttp_connection_fail_(evcon,
2105 EVREQ_HTTP_INVALID_HEADER);
2108 if (req->kind == EVHTTP_REQUEST && req->ntoread < 1) {
2109 /* An incoming request with no content-length and no
2110 * transfer-encoding has no body. */
2111 evhttp_connection_done(evcon);
2116 /* Should we send a 100 Continue status line? */
2117 if (req->kind == EVHTTP_REQUEST && REQ_VERSION_ATLEAST(req, 1, 1)) {
2120 expect = evhttp_find_header(req->input_headers, "Expect");
2122 if (!evutil_ascii_strcasecmp(expect, "100-continue")) {
2123 /* XXX It would be nice to do some sanity
2124 checking here. Does the resource exist?
2125 Should the resource accept post requests? If
2126 no, we should respond with an error. For
2127 now, just optimistically tell the client to
2128 send their message body. */
2129 if (req->ntoread > 0) {
2130 /* ntoread is ev_int64_t, max_body_size is ev_uint64_t */
2131 if ((req->evcon->max_body_size <= EV_INT64_MAX) && (ev_uint64_t)req->ntoread > req->evcon->max_body_size) {
2132 evhttp_send_error(req, HTTP_ENTITYTOOLARGE, NULL);
2136 if (!evbuffer_get_length(bufferevent_get_input(evcon->bufev)))
2137 evhttp_send_continue(evcon, req);
2139 evhttp_send_error(req, HTTP_EXPECTATIONFAILED,
2146 evhttp_read_body(evcon, req);
2147 /* note the request may have been freed in evhttp_read_body */
2151 evhttp_read_firstline(struct evhttp_connection *evcon,
2152 struct evhttp_request *req)
2154 enum message_read_status res;
2156 res = evhttp_parse_firstline_(req, bufferevent_get_input(evcon->bufev));
2157 if (res == DATA_CORRUPTED || res == DATA_TOO_LONG) {
2158 /* Error while reading, terminate */
2159 event_debug(("%s: bad header lines on "EV_SOCK_FMT"\n",
2160 __func__, EV_SOCK_ARG(evcon->fd)));
2161 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2163 } else if (res == MORE_DATA_EXPECTED) {
2164 /* Need more header lines */
2168 evcon->state = EVCON_READING_HEADERS;
2169 evhttp_read_header(evcon, req);
2173 evhttp_read_header(struct evhttp_connection *evcon,
2174 struct evhttp_request *req)
2176 enum message_read_status res;
2177 evutil_socket_t fd = evcon->fd;
2179 res = evhttp_parse_headers_(req, bufferevent_get_input(evcon->bufev));
2180 if (res == DATA_CORRUPTED || res == DATA_TOO_LONG) {
2181 /* Error while reading, terminate */
2182 event_debug(("%s: bad header lines on "EV_SOCK_FMT"\n",
2183 __func__, EV_SOCK_ARG(fd)));
2184 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2186 } else if (res == MORE_DATA_EXPECTED) {
2187 /* Need more header lines */
2191 /* Callback can shut down connection with negative return value */
2192 if (req->header_cb != NULL) {
2193 if ((*req->header_cb)(req, req->cb_arg) < 0) {
2194 evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
2199 /* Done reading headers, do the real work */
2200 switch (req->kind) {
2201 case EVHTTP_REQUEST:
2202 event_debug(("%s: checking for post data on "EV_SOCK_FMT"\n",
2203 __func__, EV_SOCK_ARG(fd)));
2204 evhttp_get_body(evcon, req);
2205 /* note the request may have been freed in evhttp_get_body */
2208 case EVHTTP_RESPONSE:
2209 /* Start over if we got a 100 Continue response. */
2210 if (req->response_code == 100) {
2211 evhttp_start_read_(evcon);
2214 if (!evhttp_response_needs_body(req)) {
2215 event_debug(("%s: skipping body for code %d\n",
2216 __func__, req->response_code));
2217 evhttp_connection_done(evcon);
2219 event_debug(("%s: start of read body for %s on "
2221 __func__, req->remote_host, EV_SOCK_ARG(fd)));
2222 evhttp_get_body(evcon, req);
2223 /* note the request may have been freed in
2224 * evhttp_get_body */
2229 event_warnx("%s: bad header on "EV_SOCK_FMT, __func__,
2231 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2234 /* request may have been freed above */
2238 * Creates a TCP connection to the specified port and executes a callback
2239 * when finished. Failure or success is indicate by the passed connection
2242 * Although this interface accepts a hostname, it is intended to take
2243 * only numeric hostnames so that non-blocking DNS resolution can
2247 struct evhttp_connection *
2248 evhttp_connection_new(const char *address, unsigned short port)
2250 return (evhttp_connection_base_new(NULL, NULL, address, port));
2253 struct evhttp_connection *
2254 evhttp_connection_base_bufferevent_new(struct event_base *base, struct evdns_base *dnsbase, struct bufferevent* bev,
2255 const char *address, unsigned short port)
2257 struct evhttp_connection *evcon = NULL;
2259 event_debug(("Attempting connection to %s:%d\n", address, port));
2261 if ((evcon = mm_calloc(1, sizeof(struct evhttp_connection))) == NULL) {
2262 event_warn("%s: calloc failed", __func__);
2269 evcon->max_headers_size = EV_SIZE_MAX;
2270 evcon->max_body_size = EV_SIZE_MAX;
2272 evutil_timerclear(&evcon->timeout);
2273 evcon->retry_cnt = evcon->retry_max = 0;
2275 if ((evcon->address = mm_strdup(address)) == NULL) {
2276 event_warn("%s: strdup failed", __func__);
2281 if (!(bev = bufferevent_socket_new(base, -1, 0))) {
2282 event_warn("%s: bufferevent_socket_new failed", __func__);
2287 bufferevent_setcb(bev, evhttp_read_cb, evhttp_write_cb, evhttp_error_cb, evcon);
2290 evcon->state = EVCON_DISCONNECTED;
2291 TAILQ_INIT(&evcon->requests);
2293 evcon->initial_retry_timeout.tv_sec = 2;
2294 evcon->initial_retry_timeout.tv_usec = 0;
2298 if (bufferevent_get_base(bev) != base)
2299 bufferevent_base_set(base, evcon->bufev);
2302 event_deferred_cb_init_(
2303 &evcon->read_more_deferred_cb,
2304 bufferevent_get_priority(bev),
2305 evhttp_deferred_read_cb, evcon);
2307 evcon->dns_base = dnsbase;
2308 evcon->ai_family = AF_UNSPEC;
2314 evhttp_connection_free(evcon);
2318 struct bufferevent* evhttp_connection_get_bufferevent(struct evhttp_connection *evcon)
2320 return evcon->bufev;
2324 evhttp_connection_get_server(struct evhttp_connection *evcon)
2326 return evcon->http_server;
2329 struct evhttp_connection *
2330 evhttp_connection_base_new(struct event_base *base, struct evdns_base *dnsbase,
2331 const char *address, unsigned short port)
2333 return evhttp_connection_base_bufferevent_new(base, dnsbase, NULL, address, port);
2336 void evhttp_connection_set_family(struct evhttp_connection *evcon,
2339 evcon->ai_family = family;
2342 int evhttp_connection_set_flags(struct evhttp_connection *evcon,
2345 if (flags & ~(EVHTTP_CON_REUSE_CONNECTED_ADDR)) {
2349 evcon->flags &= ~(EVHTTP_CON_REUSE_CONNECTED_ADDR);
2351 evcon->flags |= EVHTTP_CON_REUSE_CONNECTED_ADDR;
2357 evhttp_connection_set_base(struct evhttp_connection *evcon,
2358 struct event_base *base)
2360 EVUTIL_ASSERT(evcon->base == NULL);
2361 EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED);
2363 bufferevent_base_set(base, evcon->bufev);
2367 evhttp_connection_set_timeout(struct evhttp_connection *evcon,
2368 int timeout_in_secs)
2370 if (timeout_in_secs == -1)
2371 evhttp_connection_set_timeout_tv(evcon, NULL);
2374 tv.tv_sec = timeout_in_secs;
2376 evhttp_connection_set_timeout_tv(evcon, &tv);
2381 evhttp_connection_set_timeout_tv(struct evhttp_connection *evcon,
2382 const struct timeval* tv)
2385 evcon->timeout = *tv;
2386 bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
2388 const struct timeval read_tv = { HTTP_READ_TIMEOUT, 0 };
2389 const struct timeval write_tv = { HTTP_WRITE_TIMEOUT, 0 };
2390 evutil_timerclear(&evcon->timeout);
2391 bufferevent_set_timeouts(evcon->bufev, &read_tv, &write_tv);
2396 evhttp_connection_set_initial_retry_tv(struct evhttp_connection *evcon,
2397 const struct timeval *tv)
2400 evcon->initial_retry_timeout = *tv;
2402 evutil_timerclear(&evcon->initial_retry_timeout);
2403 evcon->initial_retry_timeout.tv_sec = 2;
2408 evhttp_connection_set_retries(struct evhttp_connection *evcon,
2411 evcon->retry_max = retry_max;
2415 evhttp_connection_set_closecb(struct evhttp_connection *evcon,
2416 void (*cb)(struct evhttp_connection *, void *), void *cbarg)
2418 evcon->closecb = cb;
2419 evcon->closecb_arg = cbarg;
2423 evhttp_connection_get_peer(struct evhttp_connection *evcon,
2424 char **address, ev_uint16_t *port)
2426 *address = evcon->address;
2427 *port = evcon->port;
2430 const struct sockaddr*
2431 evhttp_connection_get_addr(struct evhttp_connection *evcon)
2433 return bufferevent_socket_get_conn_address_(evcon->bufev);
2437 evhttp_connection_connect_(struct evhttp_connection *evcon)
2439 int old_state = evcon->state;
2440 const char *address = evcon->address;
2441 const struct sockaddr *sa = evhttp_connection_get_addr(evcon);
2444 if (evcon->state == EVCON_CONNECTING)
2447 evhttp_connection_reset_(evcon);
2449 EVUTIL_ASSERT(!(evcon->flags & EVHTTP_CON_INCOMING));
2450 evcon->flags |= EVHTTP_CON_OUTGOING;
2452 if (evcon->bind_address || evcon->bind_port) {
2453 evcon->fd = bind_socket(
2454 evcon->bind_address, evcon->bind_port, 0 /*reuse*/);
2455 if (evcon->fd == -1) {
2456 event_debug(("%s: failed to bind to \"%s\"",
2457 __func__, evcon->bind_address));
2461 bufferevent_setfd(evcon->bufev, evcon->fd);
2463 bufferevent_setfd(evcon->bufev, -1);
2466 /* Set up a callback for successful connection setup */
2467 bufferevent_setcb(evcon->bufev,
2468 NULL /* evhttp_read_cb */,
2469 NULL /* evhttp_write_cb */,
2470 evhttp_connection_cb,
2472 if (!evutil_timerisset(&evcon->timeout)) {
2473 const struct timeval conn_tv = { HTTP_CONNECT_TIMEOUT, 0 };
2474 bufferevent_set_timeouts(evcon->bufev, &conn_tv, &conn_tv);
2476 bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
2478 /* make sure that we get a write callback */
2479 bufferevent_enable(evcon->bufev, EV_WRITE);
2481 evcon->state = EVCON_CONNECTING;
2483 if (evcon->flags & EVHTTP_CON_REUSE_CONNECTED_ADDR &&
2485 (sa->sa_family == AF_INET || sa->sa_family == AF_INET6)) {
2486 int socklen = sizeof(struct sockaddr_in);
2487 if (sa->sa_family == AF_INET6) {
2488 socklen = sizeof(struct sockaddr_in6);
2490 ret = bufferevent_socket_connect(evcon->bufev, sa, socklen);
2492 ret = bufferevent_socket_connect_hostname(evcon->bufev,
2493 evcon->dns_base, evcon->ai_family, address, evcon->port);
2497 evcon->state = old_state;
2498 event_sock_warn(evcon->fd, "%s: connection to \"%s\" failed",
2499 __func__, evcon->address);
2500 /* some operating systems return ECONNREFUSED immediately
2501 * when connecting to a local address. the cleanup is going
2502 * to reschedule this function call.
2504 evhttp_connection_cb_cleanup(evcon);
2512 * Starts an HTTP request on the provided evhttp_connection object.
2513 * If the connection object is not connected to the web server already,
2514 * this will start the connection.
2518 evhttp_make_request(struct evhttp_connection *evcon,
2519 struct evhttp_request *req,
2520 enum evhttp_cmd_type type, const char *uri)
2522 /* We are making a request */
2523 req->kind = EVHTTP_REQUEST;
2525 if (req->uri != NULL)
2527 if ((req->uri = mm_strdup(uri)) == NULL) {
2528 event_warn("%s: strdup", __func__);
2529 evhttp_request_free_auto(req);
2533 /* Set the protocol version if it is not supplied */
2534 if (!req->major && !req->minor) {
2539 EVUTIL_ASSERT(req->evcon == NULL);
2541 EVUTIL_ASSERT(!(req->flags & EVHTTP_REQ_OWN_CONNECTION));
2543 TAILQ_INSERT_TAIL(&evcon->requests, req, next);
2545 /* If the connection object is not connected; make it so */
2546 if (!evhttp_connected(evcon)) {
2547 int res = evhttp_connection_connect_(evcon);
2548 /* evhttp_connection_fail_(), which is called through
2549 * evhttp_connection_connect_(), assumes that req lies in
2550 * evcon->requests. Thus, enqueue the request in advance and
2551 * remove it in the error case. */
2553 TAILQ_REMOVE(&evcon->requests, req, next);
2559 * If it's connected already and we are the first in the queue,
2560 * then we can dispatch this request immediately. Otherwise, it
2561 * will be dispatched once the pending requests are completed.
2563 if (TAILQ_FIRST(&evcon->requests) == req)
2564 evhttp_request_dispatch(evcon);
2570 evhttp_cancel_request(struct evhttp_request *req)
2572 struct evhttp_connection *evcon = req->evcon;
2573 if (evcon != NULL) {
2574 /* We need to remove it from the connection */
2575 if (TAILQ_FIRST(&evcon->requests) == req) {
2576 /* it's currently being worked on, so reset
2579 evhttp_connection_fail_(evcon,
2580 EVREQ_HTTP_REQUEST_CANCEL);
2582 /* connection fail freed the request */
2585 /* otherwise, we can just remove it from the
2588 TAILQ_REMOVE(&evcon->requests, req, next);
2592 evhttp_request_free_auto(req);
2596 * Reads data from file descriptor into request structure
2597 * Request structure needs to be set up correctly.
2601 evhttp_start_read_(struct evhttp_connection *evcon)
2603 bufferevent_disable(evcon->bufev, EV_WRITE);
2604 bufferevent_enable(evcon->bufev, EV_READ);
2606 evcon->state = EVCON_READING_FIRSTLINE;
2607 /* Reset the bufferevent callbacks */
2608 bufferevent_setcb(evcon->bufev,
2614 /* If there's still data pending, process it next time through the
2615 * loop. Don't do it now; that could get recusive. */
2616 if (evbuffer_get_length(bufferevent_get_input(evcon->bufev))) {
2617 event_deferred_cb_schedule_(get_deferred_queue(evcon),
2618 &evcon->read_more_deferred_cb);
2623 evhttp_send_done(struct evhttp_connection *evcon, void *arg)
2626 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
2627 TAILQ_REMOVE(&evcon->requests, req, next);
2629 if (req->on_complete_cb != NULL) {
2630 req->on_complete_cb(req, req->on_complete_cb_arg);
2634 (REQ_VERSION_BEFORE(req, 1, 1) &&
2635 !evhttp_is_connection_keepalive(req->input_headers)) ||
2636 evhttp_is_request_connection_close(req);
2638 EVUTIL_ASSERT(req->flags & EVHTTP_REQ_OWN_CONNECTION);
2639 evhttp_request_free(req);
2642 evhttp_connection_free(evcon);
2646 /* we have a persistent connection; try to accept another request. */
2647 if (evhttp_associate_new_request_with_connection(evcon) == -1) {
2648 evhttp_connection_free(evcon);
2653 * Returns an error page.
2657 evhttp_send_error(struct evhttp_request *req, int error, const char *reason)
2660 #define ERR_FORMAT "<HTML><HEAD>\n" \
2661 "<TITLE>%d %s</TITLE>\n" \
2666 struct evbuffer *buf = evbuffer_new();
2668 /* if we cannot allocate memory; we just drop the connection */
2669 evhttp_connection_free(req->evcon);
2672 if (reason == NULL) {
2673 reason = evhttp_response_phrase_internal(error);
2676 evhttp_response_code_(req, error, reason);
2678 evbuffer_add_printf(buf, ERR_FORMAT, error, reason, reason);
2680 evhttp_send_page_(req, buf);
2686 /* Requires that headers and response code are already set up */
2689 evhttp_send(struct evhttp_request *req, struct evbuffer *databuf)
2691 struct evhttp_connection *evcon = req->evcon;
2693 if (evcon == NULL) {
2694 evhttp_request_free(req);
2698 EVUTIL_ASSERT(TAILQ_FIRST(&evcon->requests) == req);
2700 /* we expect no more calls form the user on this request */
2703 /* xxx: not sure if we really should expose the data buffer this way */
2704 if (databuf != NULL)
2705 evbuffer_add_buffer(req->output_buffer, databuf);
2707 /* Adds headers to the response */
2708 evhttp_make_header(evcon, req);
2710 evhttp_write_buffer(evcon, evhttp_send_done, NULL);
2714 evhttp_send_reply(struct evhttp_request *req, int code, const char *reason,
2715 struct evbuffer *databuf)
2717 evhttp_response_code_(req, code, reason);
2719 evhttp_send(req, databuf);
2723 evhttp_send_reply_start(struct evhttp_request *req, int code,
2726 evhttp_response_code_(req, code, reason);
2727 if (evhttp_find_header(req->output_headers, "Content-Length") == NULL &&
2728 REQ_VERSION_ATLEAST(req, 1, 1) &&
2729 evhttp_response_needs_body(req)) {
2731 * prefer HTTP/1.1 chunked encoding to closing the connection;
2732 * note RFC 2616 section 4.4 forbids it with Content-Length:
2733 * and it's not necessary then anyway.
2735 evhttp_add_header(req->output_headers, "Transfer-Encoding",
2741 evhttp_make_header(req->evcon, req);
2742 evhttp_write_buffer(req->evcon, NULL, NULL);
2746 evhttp_send_reply_chunk_with_cb(struct evhttp_request *req, struct evbuffer *databuf,
2747 void (*cb)(struct evhttp_connection *, void *), void *arg)
2749 struct evhttp_connection *evcon = req->evcon;
2750 struct evbuffer *output;
2755 output = bufferevent_get_output(evcon->bufev);
2757 if (evbuffer_get_length(databuf) == 0)
2759 if (!evhttp_response_needs_body(req))
2762 evbuffer_add_printf(output, "%x\r\n",
2763 (unsigned)evbuffer_get_length(databuf));
2765 evbuffer_add_buffer(output, databuf);
2767 evbuffer_add(output, "\r\n", 2);
2769 evhttp_write_buffer(evcon, cb, arg);
2773 evhttp_send_reply_chunk(struct evhttp_request *req, struct evbuffer *databuf)
2775 evhttp_send_reply_chunk_with_cb(req, databuf, NULL, NULL);
2778 evhttp_send_reply_end(struct evhttp_request *req)
2780 struct evhttp_connection *evcon = req->evcon;
2781 struct evbuffer *output;
2783 if (evcon == NULL) {
2784 evhttp_request_free(req);
2788 output = bufferevent_get_output(evcon->bufev);
2790 /* we expect no more calls form the user on this request */
2794 evbuffer_add(output, "0\r\n\r\n", 5);
2795 evhttp_write_buffer(req->evcon, evhttp_send_done, NULL);
2797 } else if (evbuffer_get_length(output) == 0) {
2798 /* let the connection know that we are done with the request */
2799 evhttp_send_done(evcon, NULL);
2801 /* make the callback execute after all data has been written */
2802 evcon->cb = evhttp_send_done;
2803 evcon->cb_arg = NULL;
2807 static const char *informational_phrases[] = {
2808 /* 100 */ "Continue",
2809 /* 101 */ "Switching Protocols"
2812 static const char *success_phrases[] = {
2814 /* 201 */ "Created",
2815 /* 202 */ "Accepted",
2816 /* 203 */ "Non-Authoritative Information",
2817 /* 204 */ "No Content",
2818 /* 205 */ "Reset Content",
2819 /* 206 */ "Partial Content"
2822 static const char *redirection_phrases[] = {
2823 /* 300 */ "Multiple Choices",
2824 /* 301 */ "Moved Permanently",
2826 /* 303 */ "See Other",
2827 /* 304 */ "Not Modified",
2828 /* 305 */ "Use Proxy",
2829 /* 307 */ "Temporary Redirect"
2832 static const char *client_error_phrases[] = {
2833 /* 400 */ "Bad Request",
2834 /* 401 */ "Unauthorized",
2835 /* 402 */ "Payment Required",
2836 /* 403 */ "Forbidden",
2837 /* 404 */ "Not Found",
2838 /* 405 */ "Method Not Allowed",
2839 /* 406 */ "Not Acceptable",
2840 /* 407 */ "Proxy Authentication Required",
2841 /* 408 */ "Request Time-out",
2842 /* 409 */ "Conflict",
2844 /* 411 */ "Length Required",
2845 /* 412 */ "Precondition Failed",
2846 /* 413 */ "Request Entity Too Large",
2847 /* 414 */ "Request-URI Too Large",
2848 /* 415 */ "Unsupported Media Type",
2849 /* 416 */ "Requested range not satisfiable",
2850 /* 417 */ "Expectation Failed"
2853 static const char *server_error_phrases[] = {
2854 /* 500 */ "Internal Server Error",
2855 /* 501 */ "Not Implemented",
2856 /* 502 */ "Bad Gateway",
2857 /* 503 */ "Service Unavailable",
2858 /* 504 */ "Gateway Time-out",
2859 /* 505 */ "HTTP Version not supported"
2862 struct response_class {
2864 size_t num_responses;
2865 const char **responses;
2869 #define MEMBERSOF(x) (sizeof(x)/sizeof(x[0]))
2872 static const struct response_class response_classes[] = {
2873 /* 1xx */ { "Informational", MEMBERSOF(informational_phrases), informational_phrases },
2874 /* 2xx */ { "Success", MEMBERSOF(success_phrases), success_phrases },
2875 /* 3xx */ { "Redirection", MEMBERSOF(redirection_phrases), redirection_phrases },
2876 /* 4xx */ { "Client Error", MEMBERSOF(client_error_phrases), client_error_phrases },
2877 /* 5xx */ { "Server Error", MEMBERSOF(server_error_phrases), server_error_phrases }
2881 evhttp_response_phrase_internal(int code)
2883 int klass = code / 100 - 1;
2884 int subcode = code % 100;
2886 /* Unknown class - can't do any better here */
2887 if (klass < 0 || klass >= (int) MEMBERSOF(response_classes))
2888 return "Unknown Status Class";
2890 /* Unknown sub-code, return class name at least */
2891 if (subcode >= (int) response_classes[klass].num_responses)
2892 return response_classes[klass].name;
2894 return response_classes[klass].responses[subcode];
2898 evhttp_response_code_(struct evhttp_request *req, int code, const char *reason)
2900 req->kind = EVHTTP_RESPONSE;
2901 req->response_code = code;
2902 if (req->response_code_line != NULL)
2903 mm_free(req->response_code_line);
2905 reason = evhttp_response_phrase_internal(code);
2906 req->response_code_line = mm_strdup(reason);
2907 if (req->response_code_line == NULL) {
2908 event_warn("%s: strdup", __func__);
2909 /* XXX what else can we do? */
2914 evhttp_send_page_(struct evhttp_request *req, struct evbuffer *databuf)
2916 if (!req->major || !req->minor) {
2921 if (req->kind != EVHTTP_RESPONSE)
2922 evhttp_response_code_(req, 200, "OK");
2924 evhttp_clear_headers(req->output_headers);
2925 evhttp_add_header(req->output_headers, "Content-Type", "text/html");
2926 evhttp_add_header(req->output_headers, "Connection", "close");
2928 evhttp_send(req, databuf);
2931 static const char uri_chars[256] = {
2933 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2934 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2935 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
2936 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
2938 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2939 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
2940 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2941 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0,
2943 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2944 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2945 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2946 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2948 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2949 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2950 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2951 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2954 #define CHAR_IS_UNRESERVED(c) \
2955 (uri_chars[(unsigned char)(c)])
2958 * Helper functions to encode/decode a string for inclusion in a URI.
2959 * The returned string must be freed by the caller.
2962 evhttp_uriencode(const char *uri, ev_ssize_t len, int space_as_plus)
2964 struct evbuffer *buf = evbuffer_new();
2965 const char *p, *end;
2974 end = uri+strlen(uri);
2976 for (p = uri; p < end; p++) {
2977 if (CHAR_IS_UNRESERVED(*p)) {
2978 evbuffer_add(buf, p, 1);
2979 } else if (*p == ' ' && space_as_plus) {
2980 evbuffer_add(buf, "+", 1);
2982 evbuffer_add_printf(buf, "%%%02X", (unsigned char)(*p));
2985 evbuffer_add(buf, "", 1); /* NUL-terminator. */
2986 result = mm_malloc(evbuffer_get_length(buf));
2988 evbuffer_remove(buf, result, evbuffer_get_length(buf));
2995 evhttp_encode_uri(const char *str)
2997 return evhttp_uriencode(str, -1, 0);
3001 * @param decode_plus_ctl: if 1, we decode plus into space. If 0, we don't.
3002 * If -1, when true we transform plus to space only after we've seen
3003 * a ?. -1 is deprecated.
3004 * @return the number of bytes written to 'ret'.
3007 evhttp_decode_uri_internal(
3008 const char *uri, size_t length, char *ret, int decode_plus_ctl)
3012 int decode_plus = (decode_plus_ctl == 1) ? 1: 0;
3015 for (i = j = 0; i < length; i++) {
3018 if (decode_plus_ctl < 0)
3020 } else if (c == '+' && decode_plus) {
3022 } else if ((i + 2) < length && c == '%' &&
3023 EVUTIL_ISXDIGIT_(uri[i+1]) && EVUTIL_ISXDIGIT_(uri[i+2])) {
3028 c = (char)strtol(tmp, NULL, 16);
3040 evhttp_decode_uri(const char *uri)
3044 if ((ret = mm_malloc(strlen(uri) + 1)) == NULL) {
3045 event_warn("%s: malloc(%lu)", __func__,
3046 (unsigned long)(strlen(uri) + 1));
3050 evhttp_decode_uri_internal(uri, strlen(uri),
3051 ret, -1 /*always_decode_plus*/);
3057 evhttp_uridecode(const char *uri, int decode_plus, size_t *size_out)
3062 if ((ret = mm_malloc(strlen(uri) + 1)) == NULL) {
3063 event_warn("%s: malloc(%lu)", __func__,
3064 (unsigned long)(strlen(uri) + 1));
3068 n = evhttp_decode_uri_internal(uri, strlen(uri),
3069 ret, !!decode_plus/*always_decode_plus*/);
3072 EVUTIL_ASSERT(n >= 0);
3073 *size_out = (size_t)n;
3080 * Helper function to parse out arguments in a query.
3081 * The arguments are separated by key and value.
3085 evhttp_parse_query_impl(const char *str, struct evkeyvalq *headers,
3091 const char *query_part;
3093 struct evhttp_uri *uri=NULL;
3095 TAILQ_INIT(headers);
3098 uri = evhttp_uri_parse(str);
3101 query_part = evhttp_uri_get_query(uri);
3106 /* No arguments - we are done */
3107 if (!query_part || !strlen(query_part)) {
3112 if ((line = mm_strdup(query_part)) == NULL) {
3113 event_warn("%s: strdup", __func__);
3117 p = argument = line;
3118 while (p != NULL && *p != '\0') {
3119 char *key, *value, *decoded_value;
3120 argument = strsep(&p, "&");
3123 key = strsep(&value, "=");
3124 if (value == NULL || *key == '\0') {
3128 if ((decoded_value = mm_malloc(strlen(value) + 1)) == NULL) {
3129 event_warn("%s: mm_malloc", __func__);
3132 evhttp_decode_uri_internal(value, strlen(value),
3133 decoded_value, 1 /*always_decode_plus*/);
3134 event_debug(("Query Param: %s -> %s\n", key, decoded_value));
3135 evhttp_add_header_internal(headers, key, decoded_value);
3136 mm_free(decoded_value);
3142 evhttp_clear_headers(headers);
3147 evhttp_uri_free(uri);
3152 evhttp_parse_query(const char *uri, struct evkeyvalq *headers)
3154 return evhttp_parse_query_impl(uri, headers, 1);
3157 evhttp_parse_query_str(const char *uri, struct evkeyvalq *headers)
3159 return evhttp_parse_query_impl(uri, headers, 0);
3162 static struct evhttp_cb *
3163 evhttp_dispatch_callback(struct httpcbq *callbacks, struct evhttp_request *req)
3165 struct evhttp_cb *cb;
3170 /* Test for different URLs */
3171 path = evhttp_uri_get_path(req->uri_elems);
3172 offset = strlen(path);
3173 if ((translated = mm_malloc(offset + 1)) == NULL)
3175 evhttp_decode_uri_internal(path, offset, translated,
3176 0 /* decode_plus */);
3178 TAILQ_FOREACH(cb, callbacks, next) {
3179 if (!strcmp(cb->what, translated)) {
3180 mm_free(translated);
3185 mm_free(translated);
3191 prefix_suffix_match(const char *pattern, const char *name, int ignorecase)
3196 switch (c = *pattern++) {
3198 return *name == '\0';
3201 while (*name != '\0') {
3202 if (prefix_suffix_match(pattern, name,
3211 EVUTIL_TOLOWER_(c) != EVUTIL_TOLOWER_(*name))
3221 Search the vhost hierarchy beginning with http for a server alias
3222 matching hostname. If a match is found, and outhttp is non-null,
3223 outhttp is set to the matching http object and 1 is returned.
3227 evhttp_find_alias(struct evhttp *http, struct evhttp **outhttp,
3228 const char *hostname)
3230 struct evhttp_server_alias *alias;
3231 struct evhttp *vhost;
3233 TAILQ_FOREACH(alias, &http->aliases, next) {
3234 /* XXX Do we need to handle IP addresses? */
3235 if (!evutil_ascii_strcasecmp(alias->alias, hostname)) {
3242 /* XXX It might be good to avoid recursion here, but I don't
3243 see a way to do that w/o a list. */
3244 TAILQ_FOREACH(vhost, &http->virtualhosts, next_vhost) {
3245 if (evhttp_find_alias(vhost, outhttp, hostname))
3253 Attempts to find the best http object to handle a request for a hostname.
3254 All aliases for the root http object and vhosts are searched for an exact
3255 match. Then, the vhost hierarchy is traversed again for a matching
3258 If an alias or vhost is matched, 1 is returned, and outhttp, if non-null,
3259 is set with the best matching http object. If there are no matches, the
3260 root http object is stored in outhttp and 0 is returned.
3264 evhttp_find_vhost(struct evhttp *http, struct evhttp **outhttp,
3265 const char *hostname)
3267 struct evhttp *vhost;
3268 struct evhttp *oldhttp;
3269 int match_found = 0;
3271 if (evhttp_find_alias(http, outhttp, hostname))
3276 TAILQ_FOREACH(vhost, &http->virtualhosts, next_vhost) {
3277 if (prefix_suffix_match(vhost->vhost_pattern,
3278 hostname, 1 /* ignorecase */)) {
3284 } while (oldhttp != http);
3293 evhttp_handle_request(struct evhttp_request *req, void *arg)
3295 struct evhttp *http = arg;
3296 struct evhttp_cb *cb = NULL;
3297 const char *hostname;
3299 /* we have a new request on which the user needs to take action */
3302 if (req->type == 0 || req->uri == NULL) {
3303 evhttp_send_error(req, HTTP_BADREQUEST, NULL);
3307 if ((http->allowed_methods & req->type) == 0) {
3308 event_debug(("Rejecting disallowed method %x (allowed: %x)\n",
3309 (unsigned)req->type, (unsigned)http->allowed_methods));
3310 evhttp_send_error(req, HTTP_NOTIMPLEMENTED, NULL);
3314 /* handle potential virtual hosts */
3315 hostname = evhttp_request_get_host(req);
3316 if (hostname != NULL) {
3317 evhttp_find_vhost(http, &http, hostname);
3320 if ((cb = evhttp_dispatch_callback(&http->callbacks, req)) != NULL) {
3321 (*cb->cb)(req, cb->cbarg);
3325 /* Generic call back */
3327 (*http->gencb)(req, http->gencbarg);
3330 /* We need to send a 404 here */
3331 #define ERR_FORMAT "<html><head>" \
3332 "<title>404 Not Found</title>" \
3334 "<h1>Not Found</h1>" \
3335 "<p>The requested URL %s was not found on this server.</p>"\
3339 struct evbuffer *buf;
3341 if ((escaped_html = evhttp_htmlescape(req->uri)) == NULL) {
3342 evhttp_connection_free(req->evcon);
3346 if ((buf = evbuffer_new()) == NULL) {
3347 mm_free(escaped_html);
3348 evhttp_connection_free(req->evcon);
3352 evhttp_response_code_(req, HTTP_NOTFOUND, "Not Found");
3354 evbuffer_add_printf(buf, ERR_FORMAT, escaped_html);
3356 mm_free(escaped_html);
3358 evhttp_send_page_(req, buf);
3365 /* Listener callback when a connection arrives at a server. */
3367 accept_socket_cb(struct evconnlistener *listener, evutil_socket_t nfd, struct sockaddr *peer_sa, int peer_socklen, void *arg)
3369 struct evhttp *http = arg;
3371 evhttp_get_request(http, nfd, peer_sa, peer_socklen);
3375 evhttp_bind_socket(struct evhttp *http, const char *address, ev_uint16_t port)
3377 struct evhttp_bound_socket *bound =
3378 evhttp_bind_socket_with_handle(http, address, port);
3384 struct evhttp_bound_socket *
3385 evhttp_bind_socket_with_handle(struct evhttp *http, const char *address, ev_uint16_t port)
3388 struct evhttp_bound_socket *bound;
3390 if ((fd = bind_socket(address, port, 1 /*reuse*/)) == -1)
3393 if (listen(fd, 128) == -1) {
3394 event_sock_warn(fd, "%s: listen", __func__);
3395 evutil_closesocket(fd);
3399 bound = evhttp_accept_socket_with_handle(http, fd);
3401 if (bound != NULL) {
3402 event_debug(("Bound to port %d - Awaiting connections ... ",
3411 evhttp_accept_socket(struct evhttp *http, evutil_socket_t fd)
3413 struct evhttp_bound_socket *bound =
3414 evhttp_accept_socket_with_handle(http, fd);
3421 evhttp_foreach_bound_socket(struct evhttp *http,
3422 evhttp_bound_socket_foreach_fn *function,
3425 struct evhttp_bound_socket *bound;
3427 TAILQ_FOREACH(bound, &http->sockets, next)
3428 function(bound, argument);
3431 struct evhttp_bound_socket *
3432 evhttp_accept_socket_with_handle(struct evhttp *http, evutil_socket_t fd)
3434 struct evhttp_bound_socket *bound;
3435 struct evconnlistener *listener;
3437 LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_EXEC|LEV_OPT_CLOSE_ON_FREE;
3439 listener = evconnlistener_new(http->base, NULL, NULL,
3441 0, /* Backlog is '0' because we already said 'listen' */
3446 bound = evhttp_bind_listener(http, listener);
3448 evconnlistener_free(listener);
3454 struct evhttp_bound_socket *
3455 evhttp_bind_listener(struct evhttp *http, struct evconnlistener *listener)
3457 struct evhttp_bound_socket *bound;
3459 bound = mm_malloc(sizeof(struct evhttp_bound_socket));
3463 bound->listener = listener;
3464 TAILQ_INSERT_TAIL(&http->sockets, bound, next);
3466 evconnlistener_set_cb(listener, accept_socket_cb, http);
3471 evhttp_bound_socket_get_fd(struct evhttp_bound_socket *bound)
3473 return evconnlistener_get_fd(bound->listener);
3476 struct evconnlistener *
3477 evhttp_bound_socket_get_listener(struct evhttp_bound_socket *bound)
3479 return bound->listener;
3483 evhttp_del_accept_socket(struct evhttp *http, struct evhttp_bound_socket *bound)
3485 TAILQ_REMOVE(&http->sockets, bound, next);
3486 evconnlistener_free(bound->listener);
3490 static struct evhttp*
3491 evhttp_new_object(void)
3493 struct evhttp *http = NULL;
3495 if ((http = mm_calloc(1, sizeof(struct evhttp))) == NULL) {
3496 event_warn("%s: calloc", __func__);
3500 evutil_timerclear(&http->timeout);
3501 evhttp_set_max_headers_size(http, EV_SIZE_MAX);
3502 evhttp_set_max_body_size(http, EV_SIZE_MAX);
3503 evhttp_set_default_content_type(http, "text/html; charset=ISO-8859-1");
3504 evhttp_set_allowed_methods(http,
3511 TAILQ_INIT(&http->sockets);
3512 TAILQ_INIT(&http->callbacks);
3513 TAILQ_INIT(&http->connections);
3514 TAILQ_INIT(&http->virtualhosts);
3515 TAILQ_INIT(&http->aliases);
3521 evhttp_new(struct event_base *base)
3523 struct evhttp *http = NULL;
3525 http = evhttp_new_object();
3534 * Start a web server on the specified address and port.
3538 evhttp_start(const char *address, unsigned short port)
3540 struct evhttp *http = NULL;
3542 http = evhttp_new_object();
3545 if (evhttp_bind_socket(http, address, port) == -1) {
3554 evhttp_free(struct evhttp* http)
3556 struct evhttp_cb *http_cb;
3557 struct evhttp_connection *evcon;
3558 struct evhttp_bound_socket *bound;
3559 struct evhttp* vhost;
3560 struct evhttp_server_alias *alias;
3562 /* Remove the accepting part */
3563 while ((bound = TAILQ_FIRST(&http->sockets)) != NULL) {
3564 TAILQ_REMOVE(&http->sockets, bound, next);
3566 evconnlistener_free(bound->listener);
3571 while ((evcon = TAILQ_FIRST(&http->connections)) != NULL) {
3572 /* evhttp_connection_free removes the connection */
3573 evhttp_connection_free(evcon);
3576 while ((http_cb = TAILQ_FIRST(&http->callbacks)) != NULL) {
3577 TAILQ_REMOVE(&http->callbacks, http_cb, next);
3578 mm_free(http_cb->what);
3582 while ((vhost = TAILQ_FIRST(&http->virtualhosts)) != NULL) {
3583 TAILQ_REMOVE(&http->virtualhosts, vhost, next_vhost);
3588 if (http->vhost_pattern != NULL)
3589 mm_free(http->vhost_pattern);
3591 while ((alias = TAILQ_FIRST(&http->aliases)) != NULL) {
3592 TAILQ_REMOVE(&http->aliases, alias, next);
3593 mm_free(alias->alias);
3601 evhttp_add_virtual_host(struct evhttp* http, const char *pattern,
3602 struct evhttp* vhost)
3604 /* a vhost can only be a vhost once and should not have bound sockets */
3605 if (vhost->vhost_pattern != NULL ||
3606 TAILQ_FIRST(&vhost->sockets) != NULL)
3609 vhost->vhost_pattern = mm_strdup(pattern);
3610 if (vhost->vhost_pattern == NULL)
3613 TAILQ_INSERT_TAIL(&http->virtualhosts, vhost, next_vhost);
3619 evhttp_remove_virtual_host(struct evhttp* http, struct evhttp* vhost)
3621 if (vhost->vhost_pattern == NULL)
3624 TAILQ_REMOVE(&http->virtualhosts, vhost, next_vhost);
3626 mm_free(vhost->vhost_pattern);
3627 vhost->vhost_pattern = NULL;
3633 evhttp_add_server_alias(struct evhttp *http, const char *alias)
3635 struct evhttp_server_alias *evalias;
3637 evalias = mm_calloc(1, sizeof(*evalias));
3641 evalias->alias = mm_strdup(alias);
3642 if (!evalias->alias) {
3647 TAILQ_INSERT_TAIL(&http->aliases, evalias, next);
3653 evhttp_remove_server_alias(struct evhttp *http, const char *alias)
3655 struct evhttp_server_alias *evalias;
3657 TAILQ_FOREACH(evalias, &http->aliases, next) {
3658 if (evutil_ascii_strcasecmp(evalias->alias, alias) == 0) {
3659 TAILQ_REMOVE(&http->aliases, evalias, next);
3660 mm_free(evalias->alias);
3670 evhttp_set_timeout(struct evhttp* http, int timeout_in_secs)
3672 if (timeout_in_secs == -1) {
3673 evhttp_set_timeout_tv(http, NULL);
3676 tv.tv_sec = timeout_in_secs;
3678 evhttp_set_timeout_tv(http, &tv);
3683 evhttp_set_timeout_tv(struct evhttp* http, const struct timeval* tv)
3686 http->timeout = *tv;
3688 evutil_timerclear(&http->timeout);
3693 evhttp_set_max_headers_size(struct evhttp* http, ev_ssize_t max_headers_size)
3695 if (max_headers_size < 0)
3696 http->default_max_headers_size = EV_SIZE_MAX;
3698 http->default_max_headers_size = max_headers_size;
3702 evhttp_set_max_body_size(struct evhttp* http, ev_ssize_t max_body_size)
3704 if (max_body_size < 0)
3705 http->default_max_body_size = EV_UINT64_MAX;
3707 http->default_max_body_size = max_body_size;
3711 evhttp_set_default_content_type(struct evhttp *http,
3712 const char *content_type) {
3713 http->default_content_type = content_type;
3717 evhttp_set_allowed_methods(struct evhttp* http, ev_uint16_t methods)
3719 http->allowed_methods = methods;
3723 evhttp_set_cb(struct evhttp *http, const char *uri,
3724 void (*cb)(struct evhttp_request *, void *), void *cbarg)
3726 struct evhttp_cb *http_cb;
3728 TAILQ_FOREACH(http_cb, &http->callbacks, next) {
3729 if (strcmp(http_cb->what, uri) == 0)
3733 if ((http_cb = mm_calloc(1, sizeof(struct evhttp_cb))) == NULL) {
3734 event_warn("%s: calloc", __func__);
3738 http_cb->what = mm_strdup(uri);
3739 if (http_cb->what == NULL) {
3740 event_warn("%s: strdup", __func__);
3745 http_cb->cbarg = cbarg;
3747 TAILQ_INSERT_TAIL(&http->callbacks, http_cb, next);
3753 evhttp_del_cb(struct evhttp *http, const char *uri)
3755 struct evhttp_cb *http_cb;
3757 TAILQ_FOREACH(http_cb, &http->callbacks, next) {
3758 if (strcmp(http_cb->what, uri) == 0)
3761 if (http_cb == NULL)
3764 TAILQ_REMOVE(&http->callbacks, http_cb, next);
3765 mm_free(http_cb->what);
3772 evhttp_set_gencb(struct evhttp *http,
3773 void (*cb)(struct evhttp_request *, void *), void *cbarg)
3776 http->gencbarg = cbarg;
3780 evhttp_set_bevcb(struct evhttp *http,
3781 struct bufferevent* (*cb)(struct event_base *, void *), void *cbarg)
3784 http->bevcbarg = cbarg;
3788 * Request related functions
3791 struct evhttp_request *
3792 evhttp_request_new(void (*cb)(struct evhttp_request *, void *), void *arg)
3794 struct evhttp_request *req = NULL;
3796 /* Allocate request structure */
3797 if ((req = mm_calloc(1, sizeof(struct evhttp_request))) == NULL) {
3798 event_warn("%s: calloc", __func__);
3802 req->headers_size = 0;
3805 req->kind = EVHTTP_RESPONSE;
3806 req->input_headers = mm_calloc(1, sizeof(struct evkeyvalq));
3807 if (req->input_headers == NULL) {
3808 event_warn("%s: calloc", __func__);
3811 TAILQ_INIT(req->input_headers);
3813 req->output_headers = mm_calloc(1, sizeof(struct evkeyvalq));
3814 if (req->output_headers == NULL) {
3815 event_warn("%s: calloc", __func__);
3818 TAILQ_INIT(req->output_headers);
3820 if ((req->input_buffer = evbuffer_new()) == NULL) {
3821 event_warn("%s: evbuffer_new", __func__);
3825 if ((req->output_buffer = evbuffer_new()) == NULL) {
3826 event_warn("%s: evbuffer_new", __func__);
3837 evhttp_request_free(req);
3842 evhttp_request_free(struct evhttp_request *req)
3844 if ((req->flags & EVHTTP_REQ_DEFER_FREE) != 0) {
3845 req->flags |= EVHTTP_REQ_NEEDS_FREE;
3849 if (req->remote_host != NULL)
3850 mm_free(req->remote_host);
3851 if (req->uri != NULL)
3853 if (req->uri_elems != NULL)
3854 evhttp_uri_free(req->uri_elems);
3855 if (req->response_code_line != NULL)
3856 mm_free(req->response_code_line);
3857 if (req->host_cache != NULL)
3858 mm_free(req->host_cache);
3860 evhttp_clear_headers(req->input_headers);
3861 mm_free(req->input_headers);
3863 evhttp_clear_headers(req->output_headers);
3864 mm_free(req->output_headers);
3866 if (req->input_buffer != NULL)
3867 evbuffer_free(req->input_buffer);
3869 if (req->output_buffer != NULL)
3870 evbuffer_free(req->output_buffer);
3876 evhttp_request_own(struct evhttp_request *req)
3878 req->flags |= EVHTTP_USER_OWNED;
3882 evhttp_request_is_owned(struct evhttp_request *req)
3884 return (req->flags & EVHTTP_USER_OWNED) != 0;
3887 struct evhttp_connection *
3888 evhttp_request_get_connection(struct evhttp_request *req)
3894 evhttp_connection_get_base(struct evhttp_connection *conn)
3900 evhttp_request_set_chunked_cb(struct evhttp_request *req,
3901 void (*cb)(struct evhttp_request *, void *))
3907 evhttp_request_set_header_cb(struct evhttp_request *req,
3908 int (*cb)(struct evhttp_request *, void *))
3910 req->header_cb = cb;
3914 evhttp_request_set_error_cb(struct evhttp_request *req,
3915 void (*cb)(enum evhttp_request_error, void *))
3921 evhttp_request_set_on_complete_cb(struct evhttp_request *req,
3922 void (*cb)(struct evhttp_request *, void *), void *cb_arg)
3924 req->on_complete_cb = cb;
3925 req->on_complete_cb_arg = cb_arg;
3929 * Allows for inspection of the request URI
3933 evhttp_request_get_uri(const struct evhttp_request *req) {
3934 if (req->uri == NULL)
3935 event_debug(("%s: request %p has no uri\n", __func__, req));
3939 const struct evhttp_uri *
3940 evhttp_request_get_evhttp_uri(const struct evhttp_request *req) {
3941 if (req->uri_elems == NULL)
3942 event_debug(("%s: request %p has no uri elems\n",
3944 return (req->uri_elems);
3948 evhttp_request_get_host(struct evhttp_request *req)
3950 const char *host = NULL;
3952 if (req->host_cache)
3953 return req->host_cache;
3956 host = evhttp_uri_get_host(req->uri_elems);
3957 if (!host && req->input_headers) {
3961 host = evhttp_find_header(req->input_headers, "Host");
3962 /* The Host: header may include a port. Remove it here
3963 to be consistent with uri_elems case above. */
3965 p = host + strlen(host) - 1;
3966 while (p > host && EVUTIL_ISDIGIT_(*p))
3968 if (p > host && *p == ':') {
3970 req->host_cache = mm_malloc(len + 1);
3971 if (!req->host_cache) {
3972 event_warn("%s: malloc", __func__);
3975 memcpy(req->host_cache, host, len);
3976 req->host_cache[len] = '\0';
3977 host = req->host_cache;
3985 enum evhttp_cmd_type
3986 evhttp_request_get_command(const struct evhttp_request *req) {
3991 evhttp_request_get_response_code(const struct evhttp_request *req)
3993 return req->response_code;
3997 evhttp_request_get_response_code_line(const struct evhttp_request *req)
3999 return req->response_code_line;
4002 /** Returns the input headers */
4003 struct evkeyvalq *evhttp_request_get_input_headers(struct evhttp_request *req)
4005 return (req->input_headers);
4008 /** Returns the output headers */
4009 struct evkeyvalq *evhttp_request_get_output_headers(struct evhttp_request *req)
4011 return (req->output_headers);
4014 /** Returns the input buffer */
4015 struct evbuffer *evhttp_request_get_input_buffer(struct evhttp_request *req)
4017 return (req->input_buffer);
4020 /** Returns the output buffer */
4021 struct evbuffer *evhttp_request_get_output_buffer(struct evhttp_request *req)
4023 return (req->output_buffer);
4028 * Takes a file descriptor to read a request from.
4029 * The callback is executed once the whole request has been read.
4032 static struct evhttp_connection*
4033 evhttp_get_request_connection(
4034 struct evhttp* http,
4035 evutil_socket_t fd, struct sockaddr *sa, ev_socklen_t salen)
4037 struct evhttp_connection *evcon;
4038 char *hostname = NULL, *portname = NULL;
4039 struct bufferevent* bev = NULL;
4041 name_from_addr(sa, salen, &hostname, &portname);
4042 if (hostname == NULL || portname == NULL) {
4043 if (hostname) mm_free(hostname);
4044 if (portname) mm_free(portname);
4048 event_debug(("%s: new request from %s:%s on "EV_SOCK_FMT"\n",
4049 __func__, hostname, portname, EV_SOCK_ARG(fd)));
4051 /* we need a connection object to put the http request on */
4052 if (http->bevcb != NULL) {
4053 bev = (*http->bevcb)(http->base, http->bevcbarg);
4055 evcon = evhttp_connection_base_bufferevent_new(
4056 http->base, NULL, bev, hostname, atoi(portname));
4062 evcon->max_headers_size = http->default_max_headers_size;
4063 evcon->max_body_size = http->default_max_body_size;
4065 evcon->flags |= EVHTTP_CON_INCOMING;
4066 evcon->state = EVCON_READING_FIRSTLINE;
4070 bufferevent_enable(evcon->bufev, EV_READ);
4071 bufferevent_disable(evcon->bufev, EV_WRITE);
4072 bufferevent_setfd(evcon->bufev, fd);
4078 evhttp_associate_new_request_with_connection(struct evhttp_connection *evcon)
4080 struct evhttp *http = evcon->http_server;
4081 struct evhttp_request *req;
4082 if ((req = evhttp_request_new(evhttp_handle_request, http)) == NULL)
4085 if ((req->remote_host = mm_strdup(evcon->address)) == NULL) {
4086 event_warn("%s: strdup", __func__);
4087 evhttp_request_free(req);
4090 req->remote_port = evcon->port;
4092 req->evcon = evcon; /* the request ends up owning the connection */
4093 req->flags |= EVHTTP_REQ_OWN_CONNECTION;
4095 /* We did not present the request to the user user yet, so treat it as
4096 * if the user was done with the request. This allows us to free the
4097 * request on a persistent connection if the client drops it without
4098 * sending a request.
4102 TAILQ_INSERT_TAIL(&evcon->requests, req, next);
4104 req->kind = EVHTTP_REQUEST;
4107 evhttp_start_read_(evcon);
4113 evhttp_get_request(struct evhttp *http, evutil_socket_t fd,
4114 struct sockaddr *sa, ev_socklen_t salen)
4116 struct evhttp_connection *evcon;
4118 evcon = evhttp_get_request_connection(http, fd, sa, salen);
4119 if (evcon == NULL) {
4120 event_sock_warn(fd, "%s: cannot get connection on "EV_SOCK_FMT,
4121 __func__, EV_SOCK_ARG(fd));
4122 evutil_closesocket(fd);
4126 /* the timeout can be used by the server to close idle connections */
4127 if (evutil_timerisset(&http->timeout))
4128 evhttp_connection_set_timeout_tv(evcon, &http->timeout);
4131 * if we want to accept more than one request on a connection,
4132 * we need to know which http server it belongs to.
4134 evcon->http_server = http;
4135 TAILQ_INSERT_TAIL(&http->connections, evcon, next);
4137 if (evhttp_associate_new_request_with_connection(evcon) == -1)
4138 evhttp_connection_free(evcon);
4143 * Network helper functions that we do not want to export to the rest of
4148 name_from_addr(struct sockaddr *sa, ev_socklen_t salen,
4149 char **phost, char **pport)
4151 char ntop[NI_MAXHOST];
4152 char strport[NI_MAXSERV];
4155 #ifdef EVENT__HAVE_GETNAMEINFO
4156 ni_result = getnameinfo(sa, salen,
4157 ntop, sizeof(ntop), strport, sizeof(strport),
4158 NI_NUMERICHOST|NI_NUMERICSERV);
4160 if (ni_result != 0) {
4162 /* Windows doesn't have an EAI_SYSTEM. */
4163 if (ni_result == EAI_SYSTEM)
4164 event_err(1, "getnameinfo failed");
4167 event_errx(1, "getnameinfo failed: %s", gai_strerror(ni_result));
4171 ni_result = fake_getnameinfo(sa, salen,
4172 ntop, sizeof(ntop), strport, sizeof(strport),
4173 NI_NUMERICHOST|NI_NUMERICSERV);
4178 *phost = mm_strdup(ntop);
4179 *pport = mm_strdup(strport);
4182 /* Create a non-blocking socket and bind it */
4183 /* todo: rename this function */
4184 static evutil_socket_t
4185 bind_socket_ai(struct evutil_addrinfo *ai, int reuse)
4192 /* Create listen socket */
4193 fd = evutil_socket_(ai ? ai->ai_family : AF_INET,
4194 SOCK_STREAM|EVUTIL_SOCK_NONBLOCK|EVUTIL_SOCK_CLOEXEC, 0);
4196 event_sock_warn(-1, "socket");
4200 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on))<0)
4203 if (evutil_make_listen_socket_reuseable(fd) < 0)
4208 r = bind(fd, ai->ai_addr, (ev_socklen_t)ai->ai_addrlen);
4216 serrno = EVUTIL_SOCKET_ERROR();
4217 evutil_closesocket(fd);
4218 EVUTIL_SET_SOCKET_ERROR(serrno);
4222 static struct evutil_addrinfo *
4223 make_addrinfo(const char *address, ev_uint16_t port)
4225 struct evutil_addrinfo *ai = NULL;
4227 struct evutil_addrinfo hints;
4228 char strport[NI_MAXSERV];
4231 memset(&hints, 0, sizeof(hints));
4232 hints.ai_family = AF_UNSPEC;
4233 hints.ai_socktype = SOCK_STREAM;
4234 /* turn NULL hostname into INADDR_ANY, and skip looking up any address
4235 * types we don't have an interface to connect to. */
4236 hints.ai_flags = EVUTIL_AI_PASSIVE|EVUTIL_AI_ADDRCONFIG;
4237 evutil_snprintf(strport, sizeof(strport), "%d", port);
4238 if ((ai_result = evutil_getaddrinfo(address, strport, &hints, &ai))
4240 if (ai_result == EVUTIL_EAI_SYSTEM)
4241 event_warn("getaddrinfo");
4243 event_warnx("getaddrinfo: %s",
4244 evutil_gai_strerror(ai_result));
4251 static evutil_socket_t
4252 bind_socket(const char *address, ev_uint16_t port, int reuse)
4255 struct evutil_addrinfo *aitop = NULL;
4257 /* just create an unbound socket */
4258 if (address == NULL && port == 0)
4259 return bind_socket_ai(NULL, 0);
4261 aitop = make_addrinfo(address, port);
4266 fd = bind_socket_ai(aitop, reuse);
4268 evutil_freeaddrinfo(aitop);
4275 char *scheme; /* scheme; e.g http, ftp etc */
4276 char *userinfo; /* userinfo (typically username:pass), or NULL */
4277 char *host; /* hostname, IP address, or NULL */
4278 int port; /* port, or zero */
4279 char *path; /* path, or "". */
4280 char *query; /* query, or NULL */
4281 char *fragment; /* fragment or NULL */
4285 evhttp_uri_new(void)
4287 struct evhttp_uri *uri = mm_calloc(sizeof(struct evhttp_uri), 1);
4294 evhttp_uri_set_flags(struct evhttp_uri *uri, unsigned flags)
4299 /* Return true if the string starting at s and ending immediately before eos
4300 * is a valid URI scheme according to RFC3986
4303 scheme_ok(const char *s, const char *eos)
4305 /* scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */
4306 EVUTIL_ASSERT(eos >= s);
4309 if (!EVUTIL_ISALPHA_(*s))
4312 if (! EVUTIL_ISALNUM_(*s) &&
4313 *s != '+' && *s != '-' && *s != '.')
4319 #define SUBDELIMS "!$&'()*+,;="
4321 /* Return true iff [s..eos) is a valid userinfo */
4323 userinfo_ok(const char *s, const char *eos)
4326 if (CHAR_IS_UNRESERVED(*s) ||
4327 strchr(SUBDELIMS, *s) ||
4330 else if (*s == '%' && s+2 < eos &&
4331 EVUTIL_ISXDIGIT_(s[1]) &&
4332 EVUTIL_ISXDIGIT_(s[2]))
4341 regname_ok(const char *s, const char *eos)
4343 while (s && s<eos) {
4344 if (CHAR_IS_UNRESERVED(*s) ||
4345 strchr(SUBDELIMS, *s))
4347 else if (*s == '%' &&
4348 EVUTIL_ISXDIGIT_(s[1]) &&
4349 EVUTIL_ISXDIGIT_(s[2]))
4358 parse_port(const char *s, const char *eos)
4362 if (! EVUTIL_ISDIGIT_(*s))
4364 portnum = (portnum * 10) + (*s - '0');
4367 if (portnum > 65535)
4374 /* returns 0 for bad, 1 for ipv6, 2 for IPvFuture */
4376 bracket_addr_ok(const char *s, const char *eos)
4378 if (s + 3 > eos || *s != '[' || *(eos-1) != ']')
4381 /* IPvFuture, or junk.
4382 "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
4384 s += 2; /* skip [v */
4386 if (!EVUTIL_ISXDIGIT_(*s)) /*require at least one*/
4388 while (s < eos && *s != '.') {
4389 if (EVUTIL_ISXDIGIT_(*s))
4398 if (CHAR_IS_UNRESERVED(*s) ||
4399 strchr(SUBDELIMS, *s) ||
4409 ev_ssize_t n_chars = eos-s-2;
4410 struct in6_addr in6;
4411 if (n_chars >= 64) /* way too long */
4413 memcpy(buf, s+1, n_chars);
4415 return (evutil_inet_pton(AF_INET6,buf,&in6)==1) ? 1 : 0;
4420 parse_authority(struct evhttp_uri *uri, char *s, char *eos)
4425 uri->host = mm_strdup("");
4426 if (uri->host == NULL) {
4427 event_warn("%s: strdup", __func__);
4433 /* Optionally, we start with "userinfo@" */
4435 cp = strchr(s, '@');
4436 if (cp && cp < eos) {
4437 if (! userinfo_ok(s,cp))
4440 uri->userinfo = mm_strdup(s);
4441 if (uri->userinfo == NULL) {
4442 event_warn("%s: strdup", __func__);
4448 /* Optionally, we end with ":port" */
4449 for (port=eos-1; port >= cp && EVUTIL_ISDIGIT_(*port); --port)
4451 if (port >= cp && *port == ':') {
4452 if (port+1 == eos) /* Leave port unspecified; the RFC allows a
4455 else if ((uri->port = parse_port(port+1, eos))<0)
4459 /* Now, cp..eos holds the "host" port, which can be an IPv4Address,
4460 * an IP-Literal, or a reg-name */
4461 EVUTIL_ASSERT(eos >= cp);
4462 if (*cp == '[' && eos >= cp+2 && *(eos-1) == ']') {
4463 /* IPv6address, IP-Literal, or junk. */
4464 if (! bracket_addr_ok(cp, eos))
4467 /* Make sure the host part is ok. */
4468 if (! regname_ok(cp,eos)) /* Match IPv4Address or reg-name */
4471 uri->host = mm_malloc(eos-cp+1);
4472 if (uri->host == NULL) {
4473 event_warn("%s: malloc", __func__);
4476 memcpy(uri->host, cp, eos-cp);
4477 uri->host[eos-cp] = '\0';
4483 end_of_authority(char *cp)
4486 if (*cp == '?' || *cp == '#' || *cp == '/')
4499 /* Return the character after the longest prefix of 'cp' that matches...
4500 * *pchar / "/" if allow_qchars is false, or
4501 * *(pchar / "/" / "?") if allow_qchars is true.
4504 end_of_path(char *cp, enum uri_part part, unsigned flags)
4506 if (flags & EVHTTP_URI_NONCONFORMANT) {
4507 /* If NONCONFORMANT:
4508 * Path is everything up to a # or ? or nul.
4509 * Query is everything up a # or nul
4510 * Fragment is everything up to a nul.
4514 while (*cp && *cp != '#' && *cp != '?')
4518 while (*cp && *cp != '#')
4529 if (CHAR_IS_UNRESERVED(*cp) ||
4530 strchr(SUBDELIMS, *cp) ||
4531 *cp == ':' || *cp == '@' || *cp == '/')
4533 else if (*cp == '%' && EVUTIL_ISXDIGIT_(cp[1]) &&
4534 EVUTIL_ISXDIGIT_(cp[2]))
4536 else if (*cp == '?' && part != PART_PATH)
4545 path_matches_noscheme(const char *cp)
4550 else if (*cp == '/')
4558 evhttp_uri_parse(const char *source_uri)
4560 return evhttp_uri_parse_with_flags(source_uri, 0);
4564 evhttp_uri_parse_with_flags(const char *source_uri, unsigned flags)
4566 char *readbuf = NULL, *readp = NULL, *token = NULL, *query = NULL;
4567 char *path = NULL, *fragment = NULL;
4568 int got_authority = 0;
4570 struct evhttp_uri *uri = mm_calloc(1, sizeof(struct evhttp_uri));
4572 event_warn("%s: calloc", __func__);
4578 readbuf = mm_strdup(source_uri);
4579 if (readbuf == NULL) {
4580 event_warn("%s: strdup", __func__);
4587 /* We try to follow RFC3986 here as much as we can, and match
4590 URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
4592 relative-ref = relative-part [ "?" query ] [ "#" fragment ]
4596 token = strchr(readp, ':');
4597 if (token && scheme_ok(readp,token)) {
4599 uri->scheme = mm_strdup(readp);
4600 if (uri->scheme == NULL) {
4601 event_warn("%s: strdup", __func__);
4604 readp = token+1; /* eat : */
4607 /* 2. Optionally, "//" then an 'authority' part. */
4608 if (readp[0]=='/' && readp[1] == '/') {
4612 path = end_of_authority(readp);
4613 if (parse_authority(uri, authority, path) < 0)
4619 /* 3. Query: path-abempty, path-absolute, path-rootless, or path-empty
4622 readp = end_of_path(path, PART_PATH, flags);
4625 if (*readp == '?') {
4629 readp = end_of_path(readp, PART_QUERY, flags);
4632 if (*readp == '#') {
4636 readp = end_of_path(readp, PART_FRAGMENT, flags);
4638 if (*readp != '\0') {
4642 /* These next two cases may be unreachable; I'm leaving them
4643 * in to be defensive. */
4644 /* If you didn't get an authority, the path can't begin with "//" */
4645 if (!got_authority && path[0]=='/' && path[1]=='/')
4647 /* If you did get an authority, the path must begin with "/" or be
4649 if (got_authority && path[0] != '/' && path[0] != '\0')
4651 /* (End of maybe-unreachable cases) */
4653 /* If there was no scheme, the first part of the path (if any) must
4654 * have no colon in it. */
4655 if (! uri->scheme && !path_matches_noscheme(path))
4658 EVUTIL_ASSERT(path);
4659 uri->path = mm_strdup(path);
4660 if (uri->path == NULL) {
4661 event_warn("%s: strdup", __func__);
4666 uri->query = mm_strdup(query);
4667 if (uri->query == NULL) {
4668 event_warn("%s: strdup", __func__);
4673 uri->fragment = mm_strdup(fragment);
4674 if (uri->fragment == NULL) {
4675 event_warn("%s: strdup", __func__);
4685 evhttp_uri_free(uri);
4692 evhttp_uri_free(struct evhttp_uri *uri)
4694 #define URI_FREE_STR_(f) \
4699 URI_FREE_STR_(scheme);
4700 URI_FREE_STR_(userinfo);
4701 URI_FREE_STR_(host);
4702 URI_FREE_STR_(path);
4703 URI_FREE_STR_(query);
4704 URI_FREE_STR_(fragment);
4707 #undef URI_FREE_STR_
4711 evhttp_uri_join(struct evhttp_uri *uri, char *buf, size_t limit)
4713 struct evbuffer *tmp = 0;
4714 size_t joined_size = 0;
4715 char *output = NULL;
4717 #define URI_ADD_(f) evbuffer_add(tmp, uri->f, strlen(uri->f))
4719 if (!uri || !buf || !limit)
4722 tmp = evbuffer_new();
4728 evbuffer_add(tmp, ":", 1);
4731 evbuffer_add(tmp, "//", 2);
4733 evbuffer_add_printf(tmp,"%s@", uri->userinfo);
4736 evbuffer_add_printf(tmp,":%d", uri->port);
4738 if (uri->path && uri->path[0] != '/' && uri->path[0] != '\0')
4746 evbuffer_add(tmp, "?", 1);
4750 if (uri->fragment) {
4751 evbuffer_add(tmp, "#", 1);
4755 evbuffer_add(tmp, "\0", 1); /* NUL */
4757 joined_size = evbuffer_get_length(tmp);
4759 if (joined_size > limit) {
4760 /* It doesn't fit. */
4764 evbuffer_remove(tmp, buf, joined_size);
4775 evhttp_uri_get_scheme(const struct evhttp_uri *uri)
4780 evhttp_uri_get_userinfo(const struct evhttp_uri *uri)
4782 return uri->userinfo;
4785 evhttp_uri_get_host(const struct evhttp_uri *uri)
4790 evhttp_uri_get_port(const struct evhttp_uri *uri)
4795 evhttp_uri_get_path(const struct evhttp_uri *uri)
4800 evhttp_uri_get_query(const struct evhttp_uri *uri)
4805 evhttp_uri_get_fragment(const struct evhttp_uri *uri)
4807 return uri->fragment;
4810 #define URI_SET_STR_(f) do { \
4814 if ((uri->f = mm_strdup(f)) == NULL) { \
4815 event_warn("%s: strdup()", __func__); \
4824 evhttp_uri_set_scheme(struct evhttp_uri *uri, const char *scheme)
4826 if (scheme && !scheme_ok(scheme, scheme+strlen(scheme)))
4829 URI_SET_STR_(scheme);
4833 evhttp_uri_set_userinfo(struct evhttp_uri *uri, const char *userinfo)
4835 if (userinfo && !userinfo_ok(userinfo, userinfo+strlen(userinfo)))
4837 URI_SET_STR_(userinfo);
4841 evhttp_uri_set_host(struct evhttp_uri *uri, const char *host)
4844 if (host[0] == '[') {
4845 if (! bracket_addr_ok(host, host+strlen(host)))
4848 if (! regname_ok(host, host+strlen(host)))
4857 evhttp_uri_set_port(struct evhttp_uri *uri, int port)
4864 #define end_of_cpath(cp,p,f) \
4865 ((const char*)(end_of_path(((char*)(cp)), (p), (f))))
4868 evhttp_uri_set_path(struct evhttp_uri *uri, const char *path)
4870 if (path && end_of_cpath(path, PART_PATH, uri->flags) != path+strlen(path))
4877 evhttp_uri_set_query(struct evhttp_uri *uri, const char *query)
4879 if (query && end_of_cpath(query, PART_QUERY, uri->flags) != query+strlen(query))
4881 URI_SET_STR_(query);
4885 evhttp_uri_set_fragment(struct evhttp_uri *uri, const char *fragment)
4887 if (fragment && end_of_cpath(fragment, PART_FRAGMENT, uri->flags) != fragment+strlen(fragment))
4889 URI_SET_STR_(fragment);