mirror of
https://github.com/owntone/owntone-server.git
synced 2025-02-26 04:49:18 -05:00
Merge branch 'cors' (includes modified gzip and daap cache)
This commit is contained in:
commit
2f8c061c11
22
src/cache.c
22
src/cache.c
@ -38,6 +38,7 @@
|
||||
|
||||
#include "conffile.h"
|
||||
#include "logger.h"
|
||||
#include "httpd.h"
|
||||
#include "httpd_daap.h"
|
||||
#include "db.h"
|
||||
#include "cache.h"
|
||||
@ -680,7 +681,8 @@ cache_daap_query_add(void *arg, int *retval)
|
||||
#undef Q_TMPL
|
||||
}
|
||||
|
||||
/* Gets a reply from the cache */
|
||||
// Gets a reply from the cache.
|
||||
// cmdarg->evbuf will be filled with the reply (gzipped)
|
||||
static enum command_state
|
||||
cache_daap_query_get(void *arg, int *retval)
|
||||
{
|
||||
@ -783,6 +785,7 @@ cache_daap_update_cb(int fd, short what, void *arg)
|
||||
{
|
||||
sqlite3_stmt *stmt;
|
||||
struct evbuffer *evbuf;
|
||||
struct evbuffer *gzbuf;
|
||||
char *errmsg;
|
||||
char *query;
|
||||
int ret;
|
||||
@ -818,10 +821,23 @@ cache_daap_update_cb(int fd, short what, void *arg)
|
||||
continue;
|
||||
}
|
||||
|
||||
cache_daap_reply_add(query, evbuf);
|
||||
gzbuf = httpd_gzip_deflate(evbuf);
|
||||
if (!gzbuf)
|
||||
{
|
||||
DPRINTF(E_LOG, L_CACHE, "Error gzipping DAAP reply for query: %s\n", query);
|
||||
cache_daap_query_delete(sqlite3_column_int(stmt, 0));
|
||||
free(query);
|
||||
evbuffer_free(evbuf);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
evbuffer_free(evbuf);
|
||||
|
||||
cache_daap_reply_add(query, gzbuf);
|
||||
|
||||
free(query);
|
||||
evbuffer_free(evbuf);
|
||||
evbuffer_free(gzbuf);
|
||||
}
|
||||
|
||||
if (ret != SQLITE_DONE)
|
||||
|
@ -56,7 +56,7 @@ static cfg_opt_t sec_general[] =
|
||||
CFG_STR("cache_path", STATEDIR "/cache/" PACKAGE "/cache.db", CFGF_NONE),
|
||||
CFG_INT("cache_daap_threshold", 1000, CFGF_NONE),
|
||||
CFG_BOOL("speaker_autoselect", cfg_true, CFGF_NONE),
|
||||
CFG_STR("allow_origin", NULL, CFGF_NONE),
|
||||
CFG_STR("allow_origin", "*", CFGF_NONE),
|
||||
CFG_END()
|
||||
};
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
#include "db.h"
|
||||
#include "misc.h"
|
||||
#include "httpd.h"
|
||||
#include "logger.h"
|
||||
#include "dmap_common.h"
|
||||
|
||||
@ -355,7 +356,7 @@ dmap_send_error(struct evhttp_request *req, const char *container, const char *e
|
||||
{
|
||||
DPRINTF(E_LOG, L_DMAP, "Could not allocate evbuffer for DMAP error\n");
|
||||
|
||||
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
|
||||
httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -366,7 +367,7 @@ dmap_send_error(struct evhttp_request *req, const char *container, const char *e
|
||||
{
|
||||
DPRINTF(E_LOG, L_DMAP, "Could not expand evbuffer for DMAP error\n");
|
||||
|
||||
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
|
||||
httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
|
||||
|
||||
evbuffer_free(evbuf);
|
||||
return;
|
||||
@ -376,7 +377,7 @@ dmap_send_error(struct evhttp_request *req, const char *container, const char *e
|
||||
dmap_add_int(evbuf, "mstt", 500);
|
||||
dmap_add_string(evbuf, "msts", errmsg);
|
||||
|
||||
evhttp_send_reply(req, HTTP_OK, "OK", evbuf);
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf, HTTPD_SEND_NO_GZIP);
|
||||
|
||||
evbuffer_free(evbuf);
|
||||
}
|
||||
|
297
src/httpd.c
297
src/httpd.c
@ -86,6 +86,11 @@
|
||||
|
||||
#define STREAM_CHUNK_SIZE (64 * 1024)
|
||||
#define WEBFACE_ROOT DATADIR "/webface/"
|
||||
#define ERR_PAGE "<html>\n<head>\n" \
|
||||
"<title>%d %s</title>\n" \
|
||||
"</head>\n<body>\n" \
|
||||
"<h1>%s</h1>\n" \
|
||||
"</body>\n</html>\n"
|
||||
|
||||
struct content_type_map {
|
||||
char *ext;
|
||||
@ -134,6 +139,8 @@ static struct event *exitev;
|
||||
static struct evhttp *evhttpd;
|
||||
static pthread_t tid_httpd;
|
||||
|
||||
static char *allow_origin;
|
||||
|
||||
#ifdef HAVE_LIBEVENT2_OLD
|
||||
struct stream_ctx *g_st;
|
||||
#endif
|
||||
@ -693,135 +700,141 @@ httpd_stream_file(struct evhttp_request *req, int id)
|
||||
free_mfi(mfi, 0);
|
||||
}
|
||||
|
||||
/* Thread: httpd */
|
||||
void
|
||||
httpd_send_reply(struct evhttp_request *req, int code, const char *reason, struct evbuffer *evbuf)
|
||||
struct evbuffer *
|
||||
httpd_gzip_deflate(struct evbuffer *in)
|
||||
{
|
||||
unsigned char outbuf[128 * 1024];
|
||||
struct evbuffer *out;
|
||||
struct evbuffer_iovec iovec[1];
|
||||
z_stream strm;
|
||||
struct evbuffer *gzbuf;
|
||||
struct evkeyvalq *headers;
|
||||
const char *param;
|
||||
int flush;
|
||||
int zret;
|
||||
int ret;
|
||||
char *origin;
|
||||
|
||||
if (!req)
|
||||
return;
|
||||
|
||||
if (!evbuf || (evbuffer_get_length(evbuf) == 0))
|
||||
{
|
||||
DPRINTF(E_DBG, L_HTTPD, "Not gzipping body-less reply\n");
|
||||
|
||||
goto no_gzip;
|
||||
}
|
||||
|
||||
headers = evhttp_request_get_input_headers(req);
|
||||
|
||||
param = evhttp_find_header(headers, "Accept-Encoding");
|
||||
if (!param)
|
||||
{
|
||||
DPRINTF(E_DBG, L_HTTPD, "Not gzipping; no Accept-Encoding header\n");
|
||||
|
||||
goto no_gzip;
|
||||
}
|
||||
else if (!strstr(param, "gzip") && !strstr(param, "*"))
|
||||
{
|
||||
DPRINTF(E_DBG, L_HTTPD, "Not gzipping; gzip not in Accept-Encoding (%s)\n", param);
|
||||
|
||||
goto no_gzip;
|
||||
}
|
||||
|
||||
gzbuf = evbuffer_new();
|
||||
if (!gzbuf)
|
||||
{
|
||||
DPRINTF(E_LOG, L_HTTPD, "Could not allocate evbuffer for gzipped reply\n");
|
||||
|
||||
goto no_gzip;
|
||||
}
|
||||
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
|
||||
/* Set up a gzip stream (the "+ 16" in 15 + 16), instead of a zlib stream (default) */
|
||||
zret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY);
|
||||
if (zret != Z_OK)
|
||||
// Set up a gzip stream (the "+ 16" in 15 + 16), instead of a zlib stream (default)
|
||||
ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY);
|
||||
if (ret != Z_OK)
|
||||
{
|
||||
DPRINTF(E_DBG, L_HTTPD, "zlib setup failed: %s\n", zError(zret));
|
||||
|
||||
goto out_fail_init;
|
||||
DPRINTF(E_LOG, L_HTTPD, "zlib setup failed: %s\n", zError(ret));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strm.next_in = evbuffer_pullup(evbuf, -1);
|
||||
strm.avail_in = evbuffer_get_length(evbuf);
|
||||
strm.next_in = evbuffer_pullup(in, -1);
|
||||
strm.avail_in = evbuffer_get_length(in);
|
||||
|
||||
flush = Z_NO_FLUSH;
|
||||
|
||||
/* 2 iterations: Z_NO_FLUSH until input is consumed, then Z_FINISH */
|
||||
for (;;)
|
||||
out = evbuffer_new();
|
||||
if (!out)
|
||||
{
|
||||
do
|
||||
{
|
||||
strm.next_out = outbuf;
|
||||
strm.avail_out = sizeof(outbuf);
|
||||
|
||||
zret = deflate(&strm, flush);
|
||||
if (zret == Z_STREAM_ERROR)
|
||||
{
|
||||
DPRINTF(E_LOG, L_HTTPD, "Could not deflate data: %s\n", strm.msg);
|
||||
|
||||
goto out_fail_gz;
|
||||
}
|
||||
|
||||
ret = evbuffer_add(gzbuf, outbuf, sizeof(outbuf) - strm.avail_out);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_HTTPD, "Out of memory adding gzipped data to evbuffer\n");
|
||||
|
||||
goto out_fail_gz;
|
||||
}
|
||||
}
|
||||
while (strm.avail_out == 0);
|
||||
|
||||
if (flush == Z_FINISH)
|
||||
break;
|
||||
|
||||
flush = Z_FINISH;
|
||||
DPRINTF(E_LOG, L_HTTPD, "Could not allocate evbuffer for gzipped reply\n");
|
||||
goto out_deflate_end;
|
||||
}
|
||||
|
||||
if (zret != Z_STREAM_END)
|
||||
// We use this to avoid a memcpy. The 512 is an arbitrary padding to make sure
|
||||
// there is enough space, even if the compressed output should be slightly
|
||||
// larger than input (could happen with small inputs).
|
||||
ret = evbuffer_reserve_space(out, strm.avail_in + 512, iovec, 1);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_HTTPD, "Compressed data not finalized!\n");
|
||||
|
||||
goto out_fail_gz;
|
||||
DPRINTF(E_LOG, L_HTTPD, "Could not reserve memory for gzipped reply\n");
|
||||
goto out_evbuf_free;
|
||||
}
|
||||
|
||||
strm.next_out = iovec[0].iov_base;
|
||||
strm.avail_out = iovec[0].iov_len;
|
||||
|
||||
ret = deflate(&strm, Z_FINISH);
|
||||
if (ret != Z_STREAM_END)
|
||||
goto out_evbuf_free;
|
||||
|
||||
iovec[0].iov_len -= strm.avail_out;
|
||||
|
||||
evbuffer_commit_space(out, iovec, 1);
|
||||
deflateEnd(&strm);
|
||||
|
||||
headers = evhttp_request_get_output_headers(req);
|
||||
return out;
|
||||
|
||||
origin = cfg_getstr(cfg_getsec(cfg, "general"), "allow_origin");
|
||||
if (origin && strlen(origin))
|
||||
evhttp_add_header(headers, "Access-Control-Allow-Origin", origin);
|
||||
out_evbuf_free:
|
||||
evbuffer_free(out);
|
||||
|
||||
evhttp_add_header(headers, "Content-Encoding", "gzip");
|
||||
evhttp_send_reply(req, code, reason, gzbuf);
|
||||
|
||||
evbuffer_free(gzbuf);
|
||||
|
||||
/* Drain original buffer, as would be after evhttp_send_reply() */
|
||||
evbuffer_drain(evbuf, evbuffer_get_length(evbuf));
|
||||
|
||||
return;
|
||||
|
||||
out_fail_gz:
|
||||
out_deflate_end:
|
||||
deflateEnd(&strm);
|
||||
out_fail_init:
|
||||
evbuffer_free(gzbuf);
|
||||
no_gzip:
|
||||
evhttp_send_reply(req, code, reason, evbuf);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
httpd_send_reply(struct evhttp_request *req, int code, const char *reason, struct evbuffer *evbuf, enum httpd_send_flags flags)
|
||||
{
|
||||
struct evbuffer *gzbuf;
|
||||
struct evkeyvalq *input_headers;
|
||||
struct evkeyvalq *output_headers;
|
||||
const char *param;
|
||||
int do_gzip;
|
||||
|
||||
if (!req)
|
||||
return;
|
||||
|
||||
input_headers = evhttp_request_get_input_headers(req);
|
||||
output_headers = evhttp_request_get_output_headers(req);
|
||||
|
||||
do_gzip = ( (!(flags & HTTPD_SEND_NO_GZIP)) &&
|
||||
evbuf && (evbuffer_get_length(evbuf) > 512) &&
|
||||
(param = evhttp_find_header(input_headers, "Accept-Encoding")) &&
|
||||
(strstr(param, "gzip") || strstr(param, "*"))
|
||||
);
|
||||
|
||||
if (allow_origin)
|
||||
evhttp_add_header(output_headers, "Access-Control-Allow-Origin", allow_origin);
|
||||
|
||||
if (do_gzip && (gzbuf = httpd_gzip_deflate(evbuf)))
|
||||
{
|
||||
DPRINTF(E_DBG, L_HTTPD, "Gzipping response\n");
|
||||
|
||||
evhttp_add_header(output_headers, "Content-Encoding", "gzip");
|
||||
evhttp_send_reply(req, code, reason, gzbuf);
|
||||
evbuffer_free(gzbuf);
|
||||
|
||||
// Drain original buffer, as would be after evhttp_send_reply()
|
||||
evbuffer_drain(evbuf, evbuffer_get_length(evbuf));
|
||||
}
|
||||
else
|
||||
{
|
||||
evhttp_send_reply(req, code, reason, evbuf);
|
||||
}
|
||||
}
|
||||
|
||||
// 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 */
|
||||
@ -847,14 +860,14 @@ redirect_to_index(struct evhttp_request *req, char *uri)
|
||||
{
|
||||
DPRINTF(E_LOG, L_HTTPD, "Redirection URL exceeds buffer length\n");
|
||||
|
||||
evhttp_send_error(req, HTTP_NOTFOUND, "Not Found");
|
||||
httpd_send_error(req, HTTP_NOTFOUND, "Not Found");
|
||||
return;
|
||||
}
|
||||
|
||||
headers = evhttp_request_get_output_headers(req);
|
||||
|
||||
evhttp_add_header(headers, "Location", buf);
|
||||
evhttp_send_reply(req, HTTP_MOVETEMP, "Moved", NULL);
|
||||
|
||||
httpd_send_reply(req, HTTP_MOVETEMP, "Moved", NULL, HTTPD_SEND_NO_GZIP);
|
||||
}
|
||||
|
||||
/* Thread: httpd */
|
||||
@ -894,7 +907,7 @@ serve_file(struct evhttp_request *req, char *uri)
|
||||
{
|
||||
DPRINTF(E_LOG, L_HTTPD, "Remote web interface request denied; no password set\n");
|
||||
|
||||
evhttp_send_error(req, 403, "Forbidden");
|
||||
httpd_send_error(req, 403, "Forbidden");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -904,7 +917,7 @@ serve_file(struct evhttp_request *req, char *uri)
|
||||
{
|
||||
DPRINTF(E_LOG, L_HTTPD, "Request exceeds PATH_MAX: %s\n", uri);
|
||||
|
||||
evhttp_send_error(req, HTTP_NOTFOUND, "Not Found");
|
||||
httpd_send_error(req, HTTP_NOTFOUND, "Not Found");
|
||||
|
||||
return;
|
||||
}
|
||||
@ -914,7 +927,7 @@ serve_file(struct evhttp_request *req, char *uri)
|
||||
{
|
||||
DPRINTF(E_LOG, L_HTTPD, "Could not lstat() %s: %s\n", path, strerror(errno));
|
||||
|
||||
evhttp_send_error(req, HTTP_NOTFOUND, "Not Found");
|
||||
httpd_send_error(req, HTTP_NOTFOUND, "Not Found");
|
||||
|
||||
return;
|
||||
}
|
||||
@ -932,7 +945,7 @@ serve_file(struct evhttp_request *req, char *uri)
|
||||
{
|
||||
DPRINTF(E_LOG, L_HTTPD, "Could not dereference %s: %s\n", path, strerror(errno));
|
||||
|
||||
evhttp_send_error(req, HTTP_NOTFOUND, "Not Found");
|
||||
httpd_send_error(req, HTTP_NOTFOUND, "Not Found");
|
||||
|
||||
return;
|
||||
}
|
||||
@ -941,7 +954,7 @@ serve_file(struct evhttp_request *req, char *uri)
|
||||
{
|
||||
DPRINTF(E_LOG, L_HTTPD, "Dereferenced path exceeds PATH_MAX: %s\n", path);
|
||||
|
||||
evhttp_send_error(req, HTTP_NOTFOUND, "Not Found");
|
||||
httpd_send_error(req, HTTP_NOTFOUND, "Not Found");
|
||||
|
||||
free(deref);
|
||||
return;
|
||||
@ -955,7 +968,7 @@ serve_file(struct evhttp_request *req, char *uri)
|
||||
{
|
||||
DPRINTF(E_LOG, L_HTTPD, "Could not stat() %s: %s\n", path, strerror(errno));
|
||||
|
||||
evhttp_send_error(req, HTTP_NOTFOUND, "Not Found");
|
||||
httpd_send_error(req, HTTP_NOTFOUND, "Not Found");
|
||||
|
||||
return;
|
||||
}
|
||||
@ -970,7 +983,7 @@ serve_file(struct evhttp_request *req, char *uri)
|
||||
|
||||
if (path_is_legal(path) != 0)
|
||||
{
|
||||
evhttp_send_error(req, 403, "Forbidden");
|
||||
httpd_send_error(req, 403, "Forbidden");
|
||||
|
||||
return;
|
||||
}
|
||||
@ -980,7 +993,7 @@ serve_file(struct evhttp_request *req, char *uri)
|
||||
{
|
||||
DPRINTF(E_LOG, L_HTTPD, "Could not create evbuffer\n");
|
||||
|
||||
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal error");
|
||||
httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal error");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -989,7 +1002,7 @@ serve_file(struct evhttp_request *req, char *uri)
|
||||
{
|
||||
DPRINTF(E_LOG, L_HTTPD, "Could not open %s: %s\n", path, strerror(errno));
|
||||
|
||||
evhttp_send_error(req, HTTP_NOTFOUND, "Not Found");
|
||||
httpd_send_error(req, HTTP_NOTFOUND, "Not Found");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1002,7 +1015,7 @@ serve_file(struct evhttp_request *req, char *uri)
|
||||
{
|
||||
DPRINTF(E_LOG, L_HTTPD, "Could not read file into evbuffer\n");
|
||||
|
||||
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal error");
|
||||
httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal error");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1021,9 +1034,9 @@ serve_file(struct evhttp_request *req, char *uri)
|
||||
}
|
||||
|
||||
headers = evhttp_request_get_output_headers(req);
|
||||
|
||||
evhttp_add_header(headers, "Content-Type", ctype);
|
||||
evhttp_send_reply(req, HTTP_OK, "OK", evbuf);
|
||||
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf, HTTPD_SEND_NO_GZIP);
|
||||
|
||||
evbuffer_free(evbuf);
|
||||
}
|
||||
@ -1032,10 +1045,32 @@ serve_file(struct evhttp_request *req, char *uri)
|
||||
static void
|
||||
httpd_gen_cb(struct evhttp_request *req, void *arg)
|
||||
{
|
||||
struct evkeyvalq *input_headers;
|
||||
struct evkeyvalq *output_headers;
|
||||
const char *req_uri;
|
||||
char *uri;
|
||||
char *ptr;
|
||||
|
||||
// Did we get a CORS preflight request?
|
||||
input_headers = evhttp_request_get_input_headers(req);
|
||||
if ( input_headers && allow_origin &&
|
||||
(evhttp_request_get_command(req) == EVHTTP_REQ_OPTIONS) &&
|
||||
evhttp_find_header(input_headers, "Origin") &&
|
||||
evhttp_find_header(input_headers, "Access-Control-Request-Method") )
|
||||
{
|
||||
output_headers = evhttp_request_get_output_headers(req);
|
||||
|
||||
evhttp_add_header(output_headers, "Access-Control-Allow-Origin", allow_origin);
|
||||
|
||||
// Allow only GET method and authorization header in cross origin requests
|
||||
evhttp_add_header(output_headers, "Access-Control-Allow-Method", "GET");
|
||||
evhttp_add_header(output_headers, "Access-Control-Allow-Headers", "authorization");
|
||||
|
||||
// In this case there is no reason to go through httpd_send_reply
|
||||
evhttp_send_reply(req, HTTP_OK, "OK", NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
req_uri = evhttp_request_get_uri(req);
|
||||
if (!req_uri)
|
||||
{
|
||||
@ -1286,28 +1321,30 @@ httpd_basic_auth(struct evhttp_request *req, char *user, char *passwd, char *rea
|
||||
header = (char *)malloc(len);
|
||||
if (!header)
|
||||
{
|
||||
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
|
||||
httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = snprintf(header, len, "Basic realm=\"%s\"", realm);
|
||||
if ((ret < 0) || (ret >= len))
|
||||
{
|
||||
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
|
||||
httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
evbuf = evbuffer_new();
|
||||
if (!evbuf)
|
||||
{
|
||||
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
|
||||
httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
headers = evhttp_request_get_output_headers(req);
|
||||
evhttp_add_header(headers, "WWW-Authenticate", header);
|
||||
|
||||
evbuffer_add(evbuf, http_reply_401, strlen(http_reply_401));
|
||||
evhttp_send_reply(req, 401, "Unauthorized", evbuf);
|
||||
|
||||
httpd_send_reply(req, 401, "Unauthorized", evbuf, HTTPD_SEND_NO_GZIP);
|
||||
|
||||
free(header);
|
||||
evbuffer_free(evbuf);
|
||||
@ -1403,6 +1440,16 @@ httpd_init(void)
|
||||
v6enabled = cfg_getbool(cfg_getsec(cfg, "general"), "ipv6");
|
||||
port = cfg_getint(cfg_getsec(cfg, "library"), "port");
|
||||
|
||||
// For CORS headers
|
||||
allow_origin = cfg_getstr(cfg_getsec(cfg, "general"), "allow_origin");
|
||||
if (allow_origin)
|
||||
{
|
||||
if (strlen(allow_origin) != 0)
|
||||
evhttp_set_allowed_methods(evhttpd, EVHTTP_REQ_GET | EVHTTP_REQ_POST | EVHTTP_REQ_HEAD | EVHTTP_REQ_OPTIONS);
|
||||
else
|
||||
allow_origin = NULL;
|
||||
}
|
||||
|
||||
if (v6enabled)
|
||||
{
|
||||
ret = evhttp_bind_socket(evhttpd, "::", port);
|
||||
|
43
src/httpd.h
43
src/httpd.h
@ -5,11 +5,52 @@
|
||||
#include <event2/http.h>
|
||||
#include <event2/buffer.h>
|
||||
|
||||
enum httpd_send_flags
|
||||
{
|
||||
HTTPD_SEND_NO_GZIP = (1 << 0),
|
||||
};
|
||||
|
||||
void
|
||||
httpd_stream_file(struct evhttp_request *req, int id);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
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);
|
||||
|
@ -282,7 +282,7 @@ daap_session_find(struct evhttp_request *req, struct evkeyvalq *query, struct ev
|
||||
return s;
|
||||
|
||||
invalid:
|
||||
evhttp_send_error(req, 403, "Forbidden");
|
||||
httpd_send_error(req, 403, "Forbidden");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -355,7 +355,7 @@ update_refresh_cb(int fd, short event, void *arg)
|
||||
evcon = evhttp_request_get_connection(ur->req);
|
||||
evhttp_connection_set_closecb(evcon, NULL, NULL);
|
||||
|
||||
httpd_send_reply(ur->req, HTTP_OK, "OK", evbuf);
|
||||
httpd_send_reply(ur->req, HTTP_OK, "OK", evbuf, 0);
|
||||
|
||||
update_remove(ur);
|
||||
}
|
||||
@ -882,7 +882,7 @@ daap_reply_server_info(struct evhttp_request *req, struct evbuffer *evbuf, char
|
||||
evbuffer_add_buffer(evbuf, content);
|
||||
evbuffer_free(content);
|
||||
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf);
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -924,7 +924,7 @@ daap_reply_content_codes(struct evhttp_request *req, struct evbuffer *evbuf, cha
|
||||
dmap_add_short(evbuf, "mcty", dmap_fields[i].type); /* 10 */
|
||||
}
|
||||
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf);
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -954,7 +954,7 @@ daap_reply_login(struct evhttp_request *req, struct evbuffer *evbuf, char **uri,
|
||||
{
|
||||
DPRINTF(E_LOG, L_DAAP, "Login attempt with U-A: Remote and no pairing-guid\n");
|
||||
|
||||
evhttp_send_error(req, 403, "Forbidden");
|
||||
httpd_send_error(req, 403, "Forbidden");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -967,7 +967,7 @@ daap_reply_login(struct evhttp_request *req, struct evbuffer *evbuf, char **uri,
|
||||
DPRINTF(E_LOG, L_DAAP, "Login attempt with invalid pairing-guid\n");
|
||||
|
||||
free_pi(&pi, 1);
|
||||
evhttp_send_error(req, 403, "Forbidden");
|
||||
httpd_send_error(req, 403, "Forbidden");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -999,7 +999,7 @@ daap_reply_login(struct evhttp_request *req, struct evbuffer *evbuf, char **uri,
|
||||
dmap_add_int(evbuf, "mstt", 200); /* 12 */
|
||||
dmap_add_int(evbuf, "mlid", s->id); /* 12 */
|
||||
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf);
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1015,7 +1015,7 @@ daap_reply_logout(struct evhttp_request *req, struct evbuffer *evbuf, char **uri
|
||||
|
||||
daap_session_remove(s);
|
||||
|
||||
httpd_send_reply(req, 204, "Logout Successful", evbuf);
|
||||
httpd_send_reply(req, 204, "Logout Successful", evbuf, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1068,7 +1068,7 @@ daap_reply_update(struct evhttp_request *req, struct evbuffer *evbuf, char **uri
|
||||
dmap_add_int(evbuf, "mstt", 200); /* 12 */
|
||||
dmap_add_int(evbuf, "musr", current_rev); /* 12 */
|
||||
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf);
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1122,7 +1122,7 @@ static int
|
||||
daap_reply_activity(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, struct evkeyvalq *query, const char *ua)
|
||||
{
|
||||
/* That's so nice, thanks for letting us know */
|
||||
evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf);
|
||||
httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1222,7 +1222,7 @@ daap_reply_dblist(struct evhttp_request *req, struct evbuffer *evbuf, char **uri
|
||||
evbuffer_add_buffer(evbuf, content);
|
||||
evbuffer_free(content);
|
||||
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf);
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1510,7 +1510,7 @@ daap_reply_songlist_generic(struct evhttp_request *req, struct evbuffer *evbuf,
|
||||
}
|
||||
}
|
||||
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf);
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0);
|
||||
|
||||
return 0;
|
||||
|
||||
@ -1821,7 +1821,7 @@ daap_reply_playlists(struct evhttp_request *req, struct evbuffer *evbuf, char **
|
||||
return -1;
|
||||
}
|
||||
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf);
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0);
|
||||
|
||||
return 0;
|
||||
|
||||
@ -2132,7 +2132,7 @@ daap_reply_groups(struct evhttp_request *req, struct evbuffer *evbuf, char **uri
|
||||
}
|
||||
}
|
||||
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf);
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0);
|
||||
|
||||
return 0;
|
||||
|
||||
@ -2338,7 +2338,7 @@ daap_reply_browse(struct evhttp_request *req, struct evbuffer *evbuf, char **uri
|
||||
}
|
||||
}
|
||||
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf);
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0);
|
||||
|
||||
ret = 0;
|
||||
|
||||
@ -2378,7 +2378,7 @@ daap_reply_extra_data(struct evhttp_request *req, struct evbuffer *evbuf, char *
|
||||
ret = safe_atoi32(uri[3], &id);
|
||||
if (ret < 0)
|
||||
{
|
||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -2390,7 +2390,7 @@ daap_reply_extra_data(struct evhttp_request *req, struct evbuffer *evbuf, char *
|
||||
{
|
||||
DPRINTF(E_LOG, L_DAAP, "Could not convert mw parameter to integer\n");
|
||||
|
||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -2400,7 +2400,7 @@ daap_reply_extra_data(struct evhttp_request *req, struct evbuffer *evbuf, char *
|
||||
{
|
||||
DPRINTF(E_LOG, L_DAAP, "Could not convert mh parameter to integer\n");
|
||||
|
||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -2442,12 +2442,11 @@ daap_reply_extra_data(struct evhttp_request *req, struct evbuffer *evbuf, char *
|
||||
snprintf(clen, sizeof(clen), "%ld", (long)len);
|
||||
evhttp_add_header(headers, "Content-Length", clen);
|
||||
|
||||
/* No gzip compression for artwork */
|
||||
evhttp_send_reply(req, HTTP_OK, "OK", evbuf);
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf, HTTPD_SEND_NO_GZIP);
|
||||
return 0;
|
||||
|
||||
no_artwork:
|
||||
evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf);
|
||||
httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -2459,7 +2458,7 @@ daap_stream(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, stru
|
||||
|
||||
ret = safe_atoi32(uri[3], &id);
|
||||
if (ret < 0)
|
||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
else
|
||||
httpd_stream_file(req, id);
|
||||
|
||||
@ -2602,7 +2601,7 @@ daap_reply_dmap_test(struct evhttp_request *req, struct evbuffer *evbuf, char **
|
||||
return -1;
|
||||
}
|
||||
|
||||
evhttp_send_reply(req, HTTP_OK, "OK", evbuf);
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf, HTTPD_SEND_NO_GZIP);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2711,7 +2710,7 @@ daap_request(struct evhttp_request *req)
|
||||
full_uri = httpd_fixup_uri(req);
|
||||
if (!full_uri)
|
||||
{
|
||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2719,7 +2718,7 @@ daap_request(struct evhttp_request *req)
|
||||
if (!ptr)
|
||||
{
|
||||
free(full_uri);
|
||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2730,7 +2729,7 @@ daap_request(struct evhttp_request *req)
|
||||
|
||||
if (!uri)
|
||||
{
|
||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2741,7 +2740,7 @@ daap_request(struct evhttp_request *req)
|
||||
if (!uri)
|
||||
{
|
||||
free(full_uri);
|
||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2762,7 +2761,7 @@ daap_request(struct evhttp_request *req)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DAAP, "Unrecognized DAAP request\n");
|
||||
|
||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
|
||||
free(uri);
|
||||
free(full_uri);
|
||||
@ -2820,7 +2819,7 @@ daap_request(struct evhttp_request *req)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DAAP, "DAAP URI has too many/few components (%d)\n", (uri_parts[0]) ? i : 0);
|
||||
|
||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
|
||||
free(uri);
|
||||
free(full_uri);
|
||||
@ -2842,7 +2841,7 @@ daap_request(struct evhttp_request *req)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DAAP, "Could not allocate evbuffer for DAAP reply\n");
|
||||
|
||||
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
|
||||
httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
|
||||
|
||||
free(uri);
|
||||
free(full_uri);
|
||||
@ -2853,7 +2852,9 @@ daap_request(struct evhttp_request *req)
|
||||
ret = cache_daap_get(full_uri, evbuf);
|
||||
if (ret == 0)
|
||||
{
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf); // TODO not all want this reply
|
||||
// The cache will return the data gzipped, so httpd_send_reply won't need to do it
|
||||
evhttp_add_header(headers, "Content-Encoding", "gzip");
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf, HTTPD_SEND_NO_GZIP); // TODO not all want this reply
|
||||
|
||||
evbuffer_free(evbuf);
|
||||
free(uri);
|
||||
|
@ -368,10 +368,10 @@ playstatusupdate_cb(int fd, short what, void *arg)
|
||||
{
|
||||
buf = evbuffer_pullup(update, -1);
|
||||
evbuffer_add(evbuf, buf, len);
|
||||
httpd_send_reply(ur->req, HTTP_OK, "OK", evbuf);
|
||||
httpd_send_reply(ur->req, HTTP_OK, "OK", evbuf, 0);
|
||||
}
|
||||
else
|
||||
httpd_send_reply(ur->req, HTTP_OK, "OK", update);
|
||||
httpd_send_reply(ur->req, HTTP_OK, "OK", update, 0);
|
||||
|
||||
free(ur);
|
||||
}
|
||||
@ -774,7 +774,7 @@ dacp_reply_ctrlint(struct evhttp_request *req, struct evbuffer *evbuf, char **ur
|
||||
dmap_add_char(evbuf, "cmrl", 1); /* 9, unknown */
|
||||
dmap_add_long(evbuf, "ceSX", (1 << 1 | 1)); /* 16, unknown dacp - lowest bit announces support for playqueue-contents/-edit */
|
||||
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf);
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1103,7 +1103,7 @@ dacp_reply_cue_play(struct evhttp_request *req, struct evbuffer *evbuf, char **u
|
||||
dmap_add_int(evbuf, "mstt", 200); /* 12 */
|
||||
dmap_add_int(evbuf, "miid", id); /* 12 */
|
||||
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf);
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1119,7 +1119,7 @@ dacp_reply_cue_clear(struct evhttp_request *req, struct evbuffer *evbuf, char **
|
||||
dmap_add_int(evbuf, "mstt", 200); /* 12 */
|
||||
dmap_add_int(evbuf, "miid", 0); /* 12 */
|
||||
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf);
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1282,11 +1282,11 @@ dacp_reply_playspec(struct evhttp_request *req, struct evbuffer *evbuf, char **u
|
||||
}
|
||||
|
||||
/* 204 No Content is the canonical reply */
|
||||
evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf);
|
||||
httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP);
|
||||
return;
|
||||
|
||||
out_fail:
|
||||
evhttp_send_error(req, 500, "Internal Server Error");
|
||||
httpd_send_error(req, 500, "Internal Server Error");
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1301,7 +1301,7 @@ dacp_reply_pause(struct evhttp_request *req, struct evbuffer *evbuf, char **uri,
|
||||
player_playback_pause();
|
||||
|
||||
/* 204 No Content is the canonical reply */
|
||||
evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf);
|
||||
httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1328,13 +1328,13 @@ dacp_reply_playpause(struct evhttp_request *req, struct evbuffer *evbuf, char **
|
||||
{
|
||||
DPRINTF(E_LOG, L_DACP, "Player returned an error for start after pause\n");
|
||||
|
||||
evhttp_send_error(req, 500, "Internal Server Error");
|
||||
httpd_send_error(req, 500, "Internal Server Error");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* 204 No Content is the canonical reply */
|
||||
evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf);
|
||||
httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1352,7 +1352,7 @@ dacp_reply_nextitem(struct evhttp_request *req, struct evbuffer *evbuf, char **u
|
||||
{
|
||||
DPRINTF(E_LOG, L_DACP, "Player returned an error for nextitem\n");
|
||||
|
||||
evhttp_send_error(req, 500, "Internal Server Error");
|
||||
httpd_send_error(req, 500, "Internal Server Error");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1361,12 +1361,12 @@ dacp_reply_nextitem(struct evhttp_request *req, struct evbuffer *evbuf, char **u
|
||||
{
|
||||
DPRINTF(E_LOG, L_DACP, "Player returned an error for start after nextitem\n");
|
||||
|
||||
evhttp_send_error(req, 500, "Internal Server Error");
|
||||
httpd_send_error(req, 500, "Internal Server Error");
|
||||
return;
|
||||
}
|
||||
|
||||
/* 204 No Content is the canonical reply */
|
||||
evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf);
|
||||
httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1384,7 +1384,7 @@ dacp_reply_previtem(struct evhttp_request *req, struct evbuffer *evbuf, char **u
|
||||
{
|
||||
DPRINTF(E_LOG, L_DACP, "Player returned an error for previtem\n");
|
||||
|
||||
evhttp_send_error(req, 500, "Internal Server Error");
|
||||
httpd_send_error(req, 500, "Internal Server Error");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1393,12 +1393,12 @@ dacp_reply_previtem(struct evhttp_request *req, struct evbuffer *evbuf, char **u
|
||||
{
|
||||
DPRINTF(E_LOG, L_DACP, "Player returned an error for start after previtem\n");
|
||||
|
||||
evhttp_send_error(req, 500, "Internal Server Error");
|
||||
httpd_send_error(req, 500, "Internal Server Error");
|
||||
return;
|
||||
}
|
||||
|
||||
/* 204 No Content is the canonical reply */
|
||||
evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf);
|
||||
httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1413,7 +1413,7 @@ dacp_reply_beginff(struct evhttp_request *req, struct evbuffer *evbuf, char **ur
|
||||
/* TODO */
|
||||
|
||||
/* 204 No Content is the canonical reply */
|
||||
evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf);
|
||||
httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1428,7 +1428,7 @@ dacp_reply_beginrew(struct evhttp_request *req, struct evbuffer *evbuf, char **u
|
||||
/* TODO */
|
||||
|
||||
/* 204 No Content is the canonical reply */
|
||||
evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf);
|
||||
httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1443,7 +1443,7 @@ dacp_reply_playresume(struct evhttp_request *req, struct evbuffer *evbuf, char *
|
||||
/* TODO */
|
||||
|
||||
/* 204 No Content is the canonical reply */
|
||||
evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf);
|
||||
httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1673,7 +1673,7 @@ dacp_reply_playqueuecontents(struct evhttp_request *req, struct evbuffer *evbuf,
|
||||
dmap_add_char(evbuf, "apsm", status.shuffle); /* 9, daap.playlistshufflemode - not part of mlcl container */
|
||||
dmap_add_char(evbuf, "aprm", status.repeat); /* 9, daap.playlistrepeatmode - not part of mlcl container */
|
||||
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf);
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1697,7 +1697,7 @@ dacp_reply_playqueueedit_clear(struct evhttp_request *req, struct evbuffer *evbu
|
||||
dmap_add_int(evbuf, "mstt", 200); /* 12 */
|
||||
dmap_add_int(evbuf, "miid", 0); /* 12 */
|
||||
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf);
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1826,7 +1826,7 @@ dacp_reply_playqueueedit_add(struct evhttp_request *req, struct evbuffer *evbuf,
|
||||
}
|
||||
|
||||
/* 204 No Content is the canonical reply */
|
||||
evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf);
|
||||
httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1871,7 +1871,7 @@ dacp_reply_playqueueedit_move(struct evhttp_request *req, struct evbuffer *evbuf
|
||||
}
|
||||
|
||||
/* 204 No Content is the canonical reply */
|
||||
evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf);
|
||||
httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1903,7 +1903,7 @@ dacp_reply_playqueueedit_remove(struct evhttp_request *req, struct evbuffer *evb
|
||||
}
|
||||
|
||||
/* 204 No Content is the canonical reply */
|
||||
evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf);
|
||||
httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2023,9 +2023,9 @@ dacp_reply_playstatusupdate(struct evhttp_request *req, struct evbuffer *evbuf,
|
||||
{
|
||||
ret = make_playstatusupdate(evbuf);
|
||||
if (ret < 0)
|
||||
evhttp_send_error(req, 500, "Internal Server Error");
|
||||
httpd_send_error(req, 500, "Internal Server Error");
|
||||
else
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf);
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -2076,7 +2076,7 @@ dacp_reply_nowplayingartwork(struct evhttp_request *req, struct evbuffer *evbuf,
|
||||
{
|
||||
DPRINTF(E_LOG, L_DACP, "Request for artwork without mw parameter\n");
|
||||
|
||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2085,7 +2085,7 @@ dacp_reply_nowplayingartwork(struct evhttp_request *req, struct evbuffer *evbuf,
|
||||
{
|
||||
DPRINTF(E_LOG, L_DACP, "Could not convert mw parameter to integer\n");
|
||||
|
||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2094,7 +2094,7 @@ dacp_reply_nowplayingartwork(struct evhttp_request *req, struct evbuffer *evbuf,
|
||||
{
|
||||
DPRINTF(E_LOG, L_DACP, "Request for artwork without mh parameter\n");
|
||||
|
||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2103,7 +2103,7 @@ dacp_reply_nowplayingartwork(struct evhttp_request *req, struct evbuffer *evbuf,
|
||||
{
|
||||
DPRINTF(E_LOG, L_DACP, "Could not convert mh parameter to integer\n");
|
||||
|
||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2137,12 +2137,11 @@ dacp_reply_nowplayingartwork(struct evhttp_request *req, struct evbuffer *evbuf,
|
||||
snprintf(clen, sizeof(clen), "%ld", (long)len);
|
||||
evhttp_add_header(headers, "Content-Length", clen);
|
||||
|
||||
/* No gzip compression for artwork */
|
||||
evhttp_send_reply(req, HTTP_OK, "OK", evbuf);
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf, HTTPD_SEND_NO_GZIP);
|
||||
return;
|
||||
|
||||
no_artwork:
|
||||
evhttp_send_error(req, HTTP_NOTFOUND, "Not Found");
|
||||
httpd_send_error(req, HTTP_NOTFOUND, "Not Found");
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2243,7 +2242,7 @@ dacp_reply_getproperty(struct evhttp_request *req, struct evbuffer *evbuf, char
|
||||
return;
|
||||
}
|
||||
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf);
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0);
|
||||
|
||||
return;
|
||||
|
||||
@ -2291,7 +2290,7 @@ dacp_reply_setproperty(struct evhttp_request *req, struct evbuffer *evbuf, char
|
||||
}
|
||||
|
||||
/* 204 No Content is the canonical reply */
|
||||
evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf);
|
||||
httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2354,7 +2353,7 @@ dacp_reply_getspeakers(struct evhttp_request *req, struct evbuffer *evbuf, char
|
||||
|
||||
evbuffer_free(spklist);
|
||||
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf);
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2377,7 +2376,7 @@ dacp_reply_setspeakers(struct evhttp_request *req, struct evbuffer *evbuf, char
|
||||
{
|
||||
DPRINTF(E_LOG, L_DACP, "Missing speaker-id parameter in DACP setspeakers request\n");
|
||||
|
||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2397,7 +2396,7 @@ dacp_reply_setspeakers(struct evhttp_request *req, struct evbuffer *evbuf, char
|
||||
{
|
||||
DPRINTF(E_LOG, L_DACP, "Out of memory for speaker ids\n");
|
||||
|
||||
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
|
||||
httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2437,15 +2436,15 @@ dacp_reply_setspeakers(struct evhttp_request *req, struct evbuffer *evbuf, char
|
||||
|
||||
/* Password problem */
|
||||
if (ret == -2)
|
||||
evhttp_send_error(req, 902, "");
|
||||
httpd_send_error(req, 902, "");
|
||||
else
|
||||
evhttp_send_error(req, 500, "Internal Server Error");
|
||||
httpd_send_error(req, 500, "Internal Server Error");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* 204 No Content is the canonical reply */
|
||||
evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf);
|
||||
httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP);
|
||||
}
|
||||
|
||||
|
||||
@ -2548,7 +2547,7 @@ dacp_request(struct evhttp_request *req)
|
||||
full_uri = httpd_fixup_uri(req);
|
||||
if (!full_uri)
|
||||
{
|
||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2560,7 +2559,7 @@ dacp_request(struct evhttp_request *req)
|
||||
if (!uri)
|
||||
{
|
||||
free(full_uri);
|
||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2588,7 +2587,7 @@ dacp_request(struct evhttp_request *req)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DACP, "Unrecognized DACP request\n");
|
||||
|
||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
|
||||
free(uri);
|
||||
free(full_uri);
|
||||
@ -2609,7 +2608,7 @@ dacp_request(struct evhttp_request *req)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DACP, "DACP URI has too many/few components (%d)\n", (uri_parts[0]) ? i : 0);
|
||||
|
||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
|
||||
free(uri);
|
||||
free(full_uri);
|
||||
@ -2621,7 +2620,7 @@ dacp_request(struct evhttp_request *req)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DACP, "Could not allocate evbuffer for DACP reply\n");
|
||||
|
||||
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
|
||||
httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
|
||||
|
||||
free(uri);
|
||||
free(full_uri);
|
||||
|
@ -251,7 +251,7 @@ rsp_send_error(struct evhttp_request *req, char *errmsg)
|
||||
|
||||
if (!evbuf)
|
||||
{
|
||||
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
|
||||
httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
|
||||
|
||||
return;
|
||||
}
|
||||
@ -259,7 +259,8 @@ rsp_send_error(struct evhttp_request *req, char *errmsg)
|
||||
headers = evhttp_request_get_output_headers(req);
|
||||
evhttp_add_header(headers, "Content-Type", "text/xml; charset=utf-8");
|
||||
evhttp_add_header(headers, "Connection", "close");
|
||||
evhttp_send_reply(req, HTTP_OK, "OK", evbuf);
|
||||
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf, HTTPD_SEND_NO_GZIP);
|
||||
|
||||
evbuffer_free(evbuf);
|
||||
}
|
||||
@ -283,7 +284,8 @@ rsp_send_reply(struct evhttp_request *req, mxml_node_t *reply)
|
||||
headers = evhttp_request_get_output_headers(req);
|
||||
evhttp_add_header(headers, "Content-Type", "text/xml; charset=utf-8");
|
||||
evhttp_add_header(headers, "Connection", "close");
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf);
|
||||
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0);
|
||||
|
||||
evbuffer_free(evbuf);
|
||||
}
|
||||
@ -745,7 +747,7 @@ rsp_stream(struct evhttp_request *req, char **uri, struct evkeyvalq *query)
|
||||
|
||||
ret = safe_atoi32(uri[2], &id);
|
||||
if (ret < 0)
|
||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
else
|
||||
httpd_stream_file(req, id);
|
||||
}
|
||||
|
18
src/mpd.c
18
src/mpd.c
@ -55,6 +55,7 @@
|
||||
#include "logger.h"
|
||||
#include "db.h"
|
||||
#include "conffile.h"
|
||||
#include "httpd.h"
|
||||
#include "misc.h"
|
||||
#include "listener.h"
|
||||
#include "artwork.h"
|
||||
@ -4534,7 +4535,7 @@ artwork_cb(struct evhttp_request *req, void *arg)
|
||||
if (evhttp_request_get_command(req) != EVHTTP_REQ_GET)
|
||||
{
|
||||
DPRINTF(E_LOG, L_MPD, "Unsupported request type for artwork\n");
|
||||
evhttp_send_error(req, HTTP_BADMETHOD, "Method not allowed");
|
||||
httpd_send_error(req, HTTP_BADMETHOD, "Method not allowed");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -4545,7 +4546,7 @@ artwork_cb(struct evhttp_request *req, void *arg)
|
||||
if (!decoded)
|
||||
{
|
||||
DPRINTF(E_LOG, L_MPD, "Bad artwork request with uri '%s'\n", uri);
|
||||
evhttp_send_error(req, HTTP_BADREQUEST, 0);
|
||||
httpd_send_error(req, HTTP_BADREQUEST, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -4553,7 +4554,7 @@ artwork_cb(struct evhttp_request *req, void *arg)
|
||||
if (!path)
|
||||
{
|
||||
DPRINTF(E_LOG, L_MPD, "Invalid path from artwork request with uri '%s'\n", uri);
|
||||
evhttp_send_error(req, HTTP_BADREQUEST, 0);
|
||||
httpd_send_error(req, HTTP_BADREQUEST, 0);
|
||||
evhttp_uri_free(decoded);
|
||||
return;
|
||||
}
|
||||
@ -4562,7 +4563,7 @@ artwork_cb(struct evhttp_request *req, void *arg)
|
||||
if (!decoded_path)
|
||||
{
|
||||
DPRINTF(E_LOG, L_MPD, "Error decoding path from artwork request with uri '%s'\n", uri);
|
||||
evhttp_send_error(req, HTTP_BADREQUEST, 0);
|
||||
httpd_send_error(req, HTTP_BADREQUEST, 0);
|
||||
evhttp_uri_free(decoded);
|
||||
return;
|
||||
}
|
||||
@ -4577,7 +4578,7 @@ artwork_cb(struct evhttp_request *req, void *arg)
|
||||
if (!itemid)
|
||||
{
|
||||
DPRINTF(E_WARN, L_MPD, "No item found for path '%s' from request uri '%s'\n", decoded_path, uri);
|
||||
evhttp_send_error(req, HTTP_NOTFOUND, "Document was not found");
|
||||
httpd_send_error(req, HTTP_NOTFOUND, "Document was not found");
|
||||
evhttp_uri_free(decoded);
|
||||
free(decoded_path);
|
||||
return;
|
||||
@ -4587,7 +4588,7 @@ artwork_cb(struct evhttp_request *req, void *arg)
|
||||
if (!evbuffer)
|
||||
{
|
||||
DPRINTF(E_LOG, L_MPD, "Could not allocate an evbuffer for artwork request\n");
|
||||
evhttp_send_error(req, HTTP_INTERNAL, "Document was not found");
|
||||
httpd_send_error(req, HTTP_INTERNAL, "Document was not found");
|
||||
evhttp_uri_free(decoded);
|
||||
free(decoded_path);
|
||||
return;
|
||||
@ -4596,7 +4597,7 @@ artwork_cb(struct evhttp_request *req, void *arg)
|
||||
format = artwork_get_item(evbuffer, itemid, 600, 600);
|
||||
if (format < 0)
|
||||
{
|
||||
evhttp_send_error(req, HTTP_NOTFOUND, "Document was not found");
|
||||
httpd_send_error(req, HTTP_NOTFOUND, "Document was not found");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -4610,7 +4611,8 @@ artwork_cb(struct evhttp_request *req, void *arg)
|
||||
evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "image/jpeg");
|
||||
break;
|
||||
}
|
||||
evhttp_send_reply(req, HTTP_OK, "OK", evbuffer);
|
||||
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuffer, HTTPD_SEND_NO_GZIP);
|
||||
}
|
||||
|
||||
evbuffer_free(evbuffer);
|
||||
|
Loading…
x
Reference in New Issue
Block a user