diff --git a/src/httpd.c b/src/httpd.c
index 8a7573fa..899dce1c 100644
--- a/src/httpd.c
+++ b/src/httpd.c
@@ -86,6 +86,11 @@
#define STREAM_CHUNK_SIZE (64 * 1024)
#define WEBFACE_ROOT DATADIR "/webface/"
+#define ERR_PAGE "\n
\n" \
+ "%d %s\n" \
+ "\n\n" \
+ "%s
\n" \
+ "\n\n"
struct content_type_map {
char *ext;
@@ -758,7 +763,6 @@ httpd_gzip_deflate(struct evbuffer *in)
return NULL;
}
-/* Thread: httpd */
void
httpd_send_reply(struct evhttp_request *req, int code, const char *reason, struct evbuffer *evbuf, enum httpd_send_flags flags)
{
@@ -800,6 +804,39 @@ httpd_send_reply(struct evhttp_request *req, int code, const char *reason, struc
}
}
+// This is a modified version of evhttp_send_error (credit libevent)
+void
+httpd_send_error(struct evhttp_request* req, int error, const char* reason)
+{
+ struct evkeyvalq *output_headers;
+ struct evbuffer *evbuf;
+
+ if (!allow_origin)
+ {
+ evhttp_send_error(req, error, reason);
+ return;
+ }
+
+ output_headers = evhttp_request_get_output_headers(req);
+
+ evhttp_clear_headers(output_headers);
+
+ evhttp_add_header(output_headers, "Access-Control-Allow-Origin", allow_origin);
+ evhttp_add_header(output_headers, "Content-Type", "text/html");
+ evhttp_add_header(output_headers, "Connection", "close");
+
+ evbuf = evbuffer_new();
+ if (!evbuf)
+ DPRINTF(E_LOG, L_HTTPD, "Could not allocate evbuffer for error page\n");
+ else
+ evbuffer_add_printf(evbuf, ERR_PAGE, error, reason, reason);
+
+ evhttp_send_reply(req, error, reason, evbuf);
+
+ if (evbuf)
+ evbuffer_free(evbuf);
+}
+
/* Thread: httpd */
static int
path_is_legal(char *path)
diff --git a/src/httpd.h b/src/httpd.h
index 3cb5c490..7cd0f8fd 100644
--- a/src/httpd.h
+++ b/src/httpd.h
@@ -13,13 +13,45 @@ enum httpd_send_flags
void
httpd_stream_file(struct evhttp_request *req, int id);
-// Returns a pointer to an evbuffer with gzipped. Must be freed by caller.
+/*
+ * Gzips an evbuffer
+ *
+ * @in in Data to be compressed
+ * @return Compressed data - must be freed by caller
+ */
struct evbuffer *
httpd_gzip_deflate(struct evbuffer *in);
+/*
+ * This wrapper around evhttp_send_reply should be used whenever a request may
+ * come from a browser. It will automatically gzip if feasible, but the caller
+ * may direct it not to. It will set CORS headers as appropriate. Should be
+ * thread safe.
+ *
+ * @in req The evhttp request struct
+ * @in code HTTP code, e.g. 200
+ * @in reason A brief explanation of the error - if NULL the standard meaning
+ of the error code will be used
+ * @in evbuf Data for the response body
+ * @in flags See flags above
+ */
void
httpd_send_reply(struct evhttp_request *req, int code, const char *reason, struct evbuffer *evbuf, enum httpd_send_flags flags);
+/*
+ * This is a substitute for evhttp_send_error that should be used whenever an
+ * error may be returned to a browser. It will set CORS headers as appropriate,
+ * which is not possible with evhttp_send_error, because it clears the headers.
+ * Should be thread safe.
+ *
+ * @in req The evhttp request struct
+ * @in error HTTP code, e.g. 200
+ * @in reason A brief explanation of the error - if NULL the standard meaning
+ of the error code will be used
+ */
+void
+httpd_send_error(struct evhttp_request *req, int error, const char *reason);
+
char *
httpd_fixup_uri(struct evhttp_request *req);