aboutsummaryrefslogtreecommitdiff
path: root/server_http.c
diff options
context:
space:
mode:
Diffstat (limited to 'server_http.c')
-rw-r--r--server_http.c117
1 files changed, 113 insertions, 4 deletions
diff --git a/server_http.c b/server_http.c
index 674e92b..ad2add8 100644
--- a/server_http.c
+++ b/server_http.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server_http.c,v 1.3 2014/07/13 09:46:19 beck Exp $ */
+/* $OpenBSD: server_http.c,v 1.7 2014/07/14 09:03:08 reyk Exp $ */
/*
* Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -321,9 +321,8 @@ server_read_http(struct bufferevent *bev, void *arg)
if (clt->clt_toread <= 0) {
if (server_response(env, clt) == -1)
return;
+ clt->clt_done = 0;
}
-
- server_reset_http(clt);
}
if (clt->clt_done) {
server_close(clt, "done");
@@ -513,6 +512,12 @@ server_reset_http(struct client *clt)
clt->clt_headerlen = 0;
clt->clt_line = 0;
clt->clt_done = 0;
+ clt->clt_toread = TOREAD_HTTP_HEADER;
+ clt->clt_bev->readcb = server_read_http;
+ if (clt->clt_fd != -1) {
+ close(clt->clt_fd);
+ clt->clt_fd = -1;
+ }
}
void
@@ -609,6 +614,111 @@ server_close_http(struct client *clt)
}
int
+server_response(struct httpd *httpd, struct client *clt)
+{
+ struct http_descriptor *desc = clt->clt_desc;
+ struct kv *kv, key;
+ int ret;
+
+ if (desc->http_path == NULL)
+ goto fail;
+
+ if (strcmp(desc->http_version, "HTTP/1.1") == 0) {
+ /* Host header is mandatory */
+ key.kv_key = "Host";
+ if ((kv = kv_find(&desc->http_headers, &key)) == NULL)
+ goto fail;
+
+ /* Is the connection persistent? */
+ key.kv_key = "Connection";
+ if ((kv = kv_find(&desc->http_headers, &key)) != NULL &&
+ strcasecmp("close", kv->kv_value) == 0)
+ clt->clt_persist = 0;
+ else
+ clt->clt_persist++;
+ } else {
+ /* Is the connection persistent? */
+ key.kv_key = "Connection";
+ if ((kv = kv_find(&desc->http_headers, &key)) != NULL &&
+ strcasecmp("keep-alive", kv->kv_value) == 0)
+ clt->clt_persist++;
+ else
+ clt->clt_persist = 0;
+ }
+
+ if ((ret = server_file(httpd, clt)) == -1)
+ return (-1);
+
+ return (ret);
+ fail:
+ server_abort_http(clt, 400, "bad request");
+ return (-1);
+}
+
+int
+server_response_http(struct client *clt, u_int code,
+ struct media_type *media, size_t size)
+{
+ struct http_descriptor *desc = clt->clt_desc;
+ const char *error;
+ struct kv *ct, *cl;
+
+ if (desc == NULL || (error = server_httperror_byid(code)) == NULL)
+ return (-1);
+
+ kv_purge(&desc->http_headers);
+
+ /* Add error codes */
+ if (kv_setkey(&desc->http_pathquery, "%lu", code) == -1 ||
+ kv_set(&desc->http_pathquery, "%s", error) == -1)
+ return (-1);
+
+ /* Add headers */
+ if (kv_add(&desc->http_headers, "Server", HTTPD_SERVERNAME) == NULL)
+ return (-1);
+
+ /* Is it a persistent connection? */
+ if (clt->clt_persist) {
+ if (kv_add(&desc->http_headers,
+ "Connection", "keep-alive") == NULL)
+ return (-1);
+ } else if (kv_add(&desc->http_headers, "Connection", "close") == NULL)
+ return (-1);
+
+ /* Set media type */
+ if ((ct = kv_add(&desc->http_headers, "Content-Type", NULL)) == NULL ||
+ kv_set(ct, "%s/%s",
+ media == NULL ? "application" : media->media_type,
+ media == NULL ? "octet-stream" : media->media_subtype) == -1)
+ return (-1);
+
+ /* Set content length, if specified */
+ if (size && ((cl =
+ kv_add(&desc->http_headers, "Content-Length", NULL)) == NULL ||
+ kv_set(cl, "%ld", size) == -1))
+ return (-1);
+
+ /* Write completed header */
+ if (server_writeresponse_http(clt) == -1 ||
+ server_bufferevent_print(clt, "\r\n") == -1 ||
+ server_writeheader_http(clt) == -1 ||
+ server_bufferevent_print(clt, "\r\n") == -1)
+ return (-1);
+
+ if (desc->http_method == HTTP_METHOD_HEAD) {
+ bufferevent_enable(clt->clt_bev, EV_READ|EV_WRITE);
+ if (clt->clt_persist)
+ clt->clt_toread = TOREAD_HTTP_HEADER;
+ else
+ clt->clt_toread = TOREAD_HTTP_NONE;
+ clt->clt_done = 0;
+ return (0);
+ }
+
+ return (1);
+}
+
+int
server_writeresponse_http(struct client *clt)
{
struct http_descriptor *desc = (struct http_descriptor *)clt->clt_desc;
@@ -642,7 +752,6 @@ server_writeheader_kv(struct client *clt, struct kv *hdr)
key = hdr->kv_key;
ptr = hdr->kv_value;
- DPRINTF("%s: ptr %s", __func__, ptr);
if (server_bufferevent_print(clt, key) == -1 ||
(ptr != NULL &&
(server_bufferevent_print(clt, ": ") == -1 ||