mirror of
https://github.com/owntone/owntone-server.git
synced 2025-02-26 12:59:19 -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 "conffile.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
#include "httpd.h"
|
||||||
#include "httpd_daap.h"
|
#include "httpd_daap.h"
|
||||||
#include "db.h"
|
#include "db.h"
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
@ -680,7 +681,8 @@ cache_daap_query_add(void *arg, int *retval)
|
|||||||
#undef Q_TMPL
|
#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
|
static enum command_state
|
||||||
cache_daap_query_get(void *arg, int *retval)
|
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;
|
sqlite3_stmt *stmt;
|
||||||
struct evbuffer *evbuf;
|
struct evbuffer *evbuf;
|
||||||
|
struct evbuffer *gzbuf;
|
||||||
char *errmsg;
|
char *errmsg;
|
||||||
char *query;
|
char *query;
|
||||||
int ret;
|
int ret;
|
||||||
@ -818,10 +821,23 @@ cache_daap_update_cb(int fd, short what, void *arg)
|
|||||||
continue;
|
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);
|
free(query);
|
||||||
evbuffer_free(evbuf);
|
evbuffer_free(evbuf);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
evbuffer_free(evbuf);
|
||||||
|
|
||||||
|
cache_daap_reply_add(query, gzbuf);
|
||||||
|
|
||||||
|
free(query);
|
||||||
|
evbuffer_free(gzbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret != SQLITE_DONE)
|
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_STR("cache_path", STATEDIR "/cache/" PACKAGE "/cache.db", CFGF_NONE),
|
||||||
CFG_INT("cache_daap_threshold", 1000, CFGF_NONE),
|
CFG_INT("cache_daap_threshold", 1000, CFGF_NONE),
|
||||||
CFG_BOOL("speaker_autoselect", cfg_true, 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()
|
CFG_END()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "db.h"
|
#include "db.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
#include "httpd.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "dmap_common.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");
|
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;
|
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");
|
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);
|
evbuffer_free(evbuf);
|
||||||
return;
|
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_int(evbuf, "mstt", 500);
|
||||||
dmap_add_string(evbuf, "msts", errmsg);
|
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);
|
evbuffer_free(evbuf);
|
||||||
}
|
}
|
||||||
|
279
src/httpd.c
279
src/httpd.c
@ -86,6 +86,11 @@
|
|||||||
|
|
||||||
#define STREAM_CHUNK_SIZE (64 * 1024)
|
#define STREAM_CHUNK_SIZE (64 * 1024)
|
||||||
#define WEBFACE_ROOT DATADIR "/webface/"
|
#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 {
|
struct content_type_map {
|
||||||
char *ext;
|
char *ext;
|
||||||
@ -134,6 +139,8 @@ static struct event *exitev;
|
|||||||
static struct evhttp *evhttpd;
|
static struct evhttp *evhttpd;
|
||||||
static pthread_t tid_httpd;
|
static pthread_t tid_httpd;
|
||||||
|
|
||||||
|
static char *allow_origin;
|
||||||
|
|
||||||
#ifdef HAVE_LIBEVENT2_OLD
|
#ifdef HAVE_LIBEVENT2_OLD
|
||||||
struct stream_ctx *g_st;
|
struct stream_ctx *g_st;
|
||||||
#endif
|
#endif
|
||||||
@ -693,136 +700,142 @@ httpd_stream_file(struct evhttp_request *req, int id)
|
|||||||
free_mfi(mfi, 0);
|
free_mfi(mfi, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Thread: httpd */
|
struct evbuffer *
|
||||||
void
|
httpd_gzip_deflate(struct evbuffer *in)
|
||||||
httpd_send_reply(struct evhttp_request *req, int code, const char *reason, struct evbuffer *evbuf)
|
|
||||||
{
|
{
|
||||||
unsigned char outbuf[128 * 1024];
|
struct evbuffer *out;
|
||||||
|
struct evbuffer_iovec iovec[1];
|
||||||
z_stream strm;
|
z_stream strm;
|
||||||
struct evbuffer *gzbuf;
|
|
||||||
struct evkeyvalq *headers;
|
|
||||||
const char *param;
|
|
||||||
int flush;
|
|
||||||
int zret;
|
|
||||||
int ret;
|
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.zalloc = Z_NULL;
|
||||||
strm.zfree = Z_NULL;
|
strm.zfree = Z_NULL;
|
||||||
strm.opaque = Z_NULL;
|
strm.opaque = Z_NULL;
|
||||||
|
|
||||||
/* Set up a gzip stream (the "+ 16" in 15 + 16), instead of a zlib stream (default) */
|
// 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);
|
ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY);
|
||||||
if (zret != Z_OK)
|
if (ret != Z_OK)
|
||||||
{
|
{
|
||||||
DPRINTF(E_DBG, L_HTTPD, "zlib setup failed: %s\n", zError(zret));
|
DPRINTF(E_LOG, L_HTTPD, "zlib setup failed: %s\n", zError(ret));
|
||||||
|
return NULL;
|
||||||
goto out_fail_init;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
strm.next_in = evbuffer_pullup(evbuf, -1);
|
strm.next_in = evbuffer_pullup(in, -1);
|
||||||
strm.avail_in = evbuffer_get_length(evbuf);
|
strm.avail_in = evbuffer_get_length(in);
|
||||||
|
|
||||||
flush = Z_NO_FLUSH;
|
out = evbuffer_new();
|
||||||
|
if (!out)
|
||||||
/* 2 iterations: Z_NO_FLUSH until input is consumed, then Z_FINISH */
|
|
||||||
for (;;)
|
|
||||||
{
|
{
|
||||||
do
|
DPRINTF(E_LOG, L_HTTPD, "Could not allocate evbuffer for gzipped reply\n");
|
||||||
{
|
goto out_deflate_end;
|
||||||
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);
|
// 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)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_HTTPD, "Out of memory adding gzipped data to evbuffer\n");
|
DPRINTF(E_LOG, L_HTTPD, "Could not reserve memory for gzipped reply\n");
|
||||||
|
goto out_evbuf_free;
|
||||||
goto out_fail_gz;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (strm.avail_out == 0);
|
|
||||||
|
|
||||||
if (flush == Z_FINISH)
|
|
||||||
break;
|
|
||||||
|
|
||||||
flush = Z_FINISH;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zret != Z_STREAM_END)
|
strm.next_out = iovec[0].iov_base;
|
||||||
{
|
strm.avail_out = iovec[0].iov_len;
|
||||||
DPRINTF(E_LOG, L_HTTPD, "Compressed data not finalized!\n");
|
|
||||||
|
|
||||||
goto out_fail_gz;
|
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);
|
deflateEnd(&strm);
|
||||||
|
|
||||||
headers = evhttp_request_get_output_headers(req);
|
return out;
|
||||||
|
|
||||||
origin = cfg_getstr(cfg_getsec(cfg, "general"), "allow_origin");
|
out_evbuf_free:
|
||||||
if (origin && strlen(origin))
|
evbuffer_free(out);
|
||||||
evhttp_add_header(headers, "Access-Control-Allow-Origin", origin);
|
|
||||||
|
|
||||||
evhttp_add_header(headers, "Content-Encoding", "gzip");
|
out_deflate_end:
|
||||||
evhttp_send_reply(req, code, reason, gzbuf);
|
deflateEnd(&strm);
|
||||||
|
|
||||||
evbuffer_free(gzbuf);
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Drain original buffer, as would be after evhttp_send_reply() */
|
void
|
||||||
evbuffer_drain(evbuf, evbuffer_get_length(evbuf));
|
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;
|
return;
|
||||||
|
|
||||||
out_fail_gz:
|
input_headers = evhttp_request_get_input_headers(req);
|
||||||
deflateEnd(&strm);
|
output_headers = evhttp_request_get_output_headers(req);
|
||||||
out_fail_init:
|
|
||||||
|
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);
|
evbuffer_free(gzbuf);
|
||||||
no_gzip:
|
|
||||||
|
// 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);
|
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 */
|
/* Thread: httpd */
|
||||||
static int
|
static int
|
||||||
@ -847,14 +860,14 @@ redirect_to_index(struct evhttp_request *req, char *uri)
|
|||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_HTTPD, "Redirection URL exceeds buffer length\n");
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
headers = evhttp_request_get_output_headers(req);
|
headers = evhttp_request_get_output_headers(req);
|
||||||
|
|
||||||
evhttp_add_header(headers, "Location", buf);
|
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 */
|
/* 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");
|
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;
|
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);
|
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;
|
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));
|
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;
|
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));
|
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;
|
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);
|
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);
|
free(deref);
|
||||||
return;
|
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));
|
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;
|
return;
|
||||||
}
|
}
|
||||||
@ -970,7 +983,7 @@ serve_file(struct evhttp_request *req, char *uri)
|
|||||||
|
|
||||||
if (path_is_legal(path) != 0)
|
if (path_is_legal(path) != 0)
|
||||||
{
|
{
|
||||||
evhttp_send_error(req, 403, "Forbidden");
|
httpd_send_error(req, 403, "Forbidden");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -980,7 +993,7 @@ serve_file(struct evhttp_request *req, char *uri)
|
|||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_HTTPD, "Could not create evbuffer\n");
|
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;
|
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));
|
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;
|
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");
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1021,9 +1034,9 @@ serve_file(struct evhttp_request *req, char *uri)
|
|||||||
}
|
}
|
||||||
|
|
||||||
headers = evhttp_request_get_output_headers(req);
|
headers = evhttp_request_get_output_headers(req);
|
||||||
|
|
||||||
evhttp_add_header(headers, "Content-Type", ctype);
|
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);
|
evbuffer_free(evbuf);
|
||||||
}
|
}
|
||||||
@ -1032,10 +1045,32 @@ serve_file(struct evhttp_request *req, char *uri)
|
|||||||
static void
|
static void
|
||||||
httpd_gen_cb(struct evhttp_request *req, void *arg)
|
httpd_gen_cb(struct evhttp_request *req, void *arg)
|
||||||
{
|
{
|
||||||
|
struct evkeyvalq *input_headers;
|
||||||
|
struct evkeyvalq *output_headers;
|
||||||
const char *req_uri;
|
const char *req_uri;
|
||||||
char *uri;
|
char *uri;
|
||||||
char *ptr;
|
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);
|
req_uri = evhttp_request_get_uri(req);
|
||||||
if (!req_uri)
|
if (!req_uri)
|
||||||
{
|
{
|
||||||
@ -1286,28 +1321,30 @@ httpd_basic_auth(struct evhttp_request *req, char *user, char *passwd, char *rea
|
|||||||
header = (char *)malloc(len);
|
header = (char *)malloc(len);
|
||||||
if (!header)
|
if (!header)
|
||||||
{
|
{
|
||||||
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
|
httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = snprintf(header, len, "Basic realm=\"%s\"", realm);
|
ret = snprintf(header, len, "Basic realm=\"%s\"", realm);
|
||||||
if ((ret < 0) || (ret >= len))
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
evbuf = evbuffer_new();
|
evbuf = evbuffer_new();
|
||||||
if (!evbuf)
|
if (!evbuf)
|
||||||
{
|
{
|
||||||
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
|
httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
headers = evhttp_request_get_output_headers(req);
|
headers = evhttp_request_get_output_headers(req);
|
||||||
evhttp_add_header(headers, "WWW-Authenticate", header);
|
evhttp_add_header(headers, "WWW-Authenticate", header);
|
||||||
|
|
||||||
evbuffer_add(evbuf, http_reply_401, strlen(http_reply_401));
|
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);
|
free(header);
|
||||||
evbuffer_free(evbuf);
|
evbuffer_free(evbuf);
|
||||||
@ -1403,6 +1440,16 @@ httpd_init(void)
|
|||||||
v6enabled = cfg_getbool(cfg_getsec(cfg, "general"), "ipv6");
|
v6enabled = cfg_getbool(cfg_getsec(cfg, "general"), "ipv6");
|
||||||
port = cfg_getint(cfg_getsec(cfg, "library"), "port");
|
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)
|
if (v6enabled)
|
||||||
{
|
{
|
||||||
ret = evhttp_bind_socket(evhttpd, "::", port);
|
ret = evhttp_bind_socket(evhttpd, "::", port);
|
||||||
|
43
src/httpd.h
43
src/httpd.h
@ -5,11 +5,52 @@
|
|||||||
#include <event2/http.h>
|
#include <event2/http.h>
|
||||||
#include <event2/buffer.h>
|
#include <event2/buffer.h>
|
||||||
|
|
||||||
|
enum httpd_send_flags
|
||||||
|
{
|
||||||
|
HTTPD_SEND_NO_GZIP = (1 << 0),
|
||||||
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
httpd_stream_file(struct evhttp_request *req, int id);
|
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
|
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 *
|
char *
|
||||||
httpd_fixup_uri(struct evhttp_request *req);
|
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;
|
return s;
|
||||||
|
|
||||||
invalid:
|
invalid:
|
||||||
evhttp_send_error(req, 403, "Forbidden");
|
httpd_send_error(req, 403, "Forbidden");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -355,7 +355,7 @@ update_refresh_cb(int fd, short event, void *arg)
|
|||||||
evcon = evhttp_request_get_connection(ur->req);
|
evcon = evhttp_request_get_connection(ur->req);
|
||||||
evhttp_connection_set_closecb(evcon, NULL, NULL);
|
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);
|
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_add_buffer(evbuf, content);
|
||||||
evbuffer_free(content);
|
evbuffer_free(content);
|
||||||
|
|
||||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf);
|
httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0);
|
||||||
|
|
||||||
return 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 */
|
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;
|
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");
|
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;
|
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");
|
DPRINTF(E_LOG, L_DAAP, "Login attempt with invalid pairing-guid\n");
|
||||||
|
|
||||||
free_pi(&pi, 1);
|
free_pi(&pi, 1);
|
||||||
evhttp_send_error(req, 403, "Forbidden");
|
httpd_send_error(req, 403, "Forbidden");
|
||||||
return -1;
|
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, "mstt", 200); /* 12 */
|
||||||
dmap_add_int(evbuf, "mlid", s->id); /* 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;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1015,7 +1015,7 @@ daap_reply_logout(struct evhttp_request *req, struct evbuffer *evbuf, char **uri
|
|||||||
|
|
||||||
daap_session_remove(s);
|
daap_session_remove(s);
|
||||||
|
|
||||||
httpd_send_reply(req, 204, "Logout Successful", evbuf);
|
httpd_send_reply(req, 204, "Logout Successful", evbuf, 0);
|
||||||
|
|
||||||
return 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, "mstt", 200); /* 12 */
|
||||||
dmap_add_int(evbuf, "musr", current_rev); /* 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;
|
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)
|
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 */
|
/* 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;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1222,7 +1222,7 @@ daap_reply_dblist(struct evhttp_request *req, struct evbuffer *evbuf, char **uri
|
|||||||
evbuffer_add_buffer(evbuf, content);
|
evbuffer_add_buffer(evbuf, content);
|
||||||
evbuffer_free(content);
|
evbuffer_free(content);
|
||||||
|
|
||||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf);
|
httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0);
|
||||||
|
|
||||||
return 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;
|
return 0;
|
||||||
|
|
||||||
@ -1821,7 +1821,7 @@ daap_reply_playlists(struct evhttp_request *req, struct evbuffer *evbuf, char **
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf);
|
httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0);
|
||||||
|
|
||||||
return 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;
|
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;
|
ret = 0;
|
||||||
|
|
||||||
@ -2378,7 +2378,7 @@ daap_reply_extra_data(struct evhttp_request *req, struct evbuffer *evbuf, char *
|
|||||||
ret = safe_atoi32(uri[3], &id);
|
ret = safe_atoi32(uri[3], &id);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||||
return -1;
|
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");
|
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;
|
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");
|
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;
|
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);
|
snprintf(clen, sizeof(clen), "%ld", (long)len);
|
||||||
evhttp_add_header(headers, "Content-Length", clen);
|
evhttp_add_header(headers, "Content-Length", clen);
|
||||||
|
|
||||||
/* No gzip compression for artwork */
|
httpd_send_reply(req, HTTP_OK, "OK", evbuf, HTTPD_SEND_NO_GZIP);
|
||||||
evhttp_send_reply(req, HTTP_OK, "OK", evbuf);
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
no_artwork:
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2459,7 +2458,7 @@ daap_stream(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, stru
|
|||||||
|
|
||||||
ret = safe_atoi32(uri[3], &id);
|
ret = safe_atoi32(uri[3], &id);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||||
else
|
else
|
||||||
httpd_stream_file(req, id);
|
httpd_stream_file(req, id);
|
||||||
|
|
||||||
@ -2602,7 +2601,7 @@ daap_reply_dmap_test(struct evhttp_request *req, struct evbuffer *evbuf, char **
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
evhttp_send_reply(req, HTTP_OK, "OK", evbuf);
|
httpd_send_reply(req, HTTP_OK, "OK", evbuf, HTTPD_SEND_NO_GZIP);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2711,7 +2710,7 @@ daap_request(struct evhttp_request *req)
|
|||||||
full_uri = httpd_fixup_uri(req);
|
full_uri = httpd_fixup_uri(req);
|
||||||
if (!full_uri)
|
if (!full_uri)
|
||||||
{
|
{
|
||||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2719,7 +2718,7 @@ daap_request(struct evhttp_request *req)
|
|||||||
if (!ptr)
|
if (!ptr)
|
||||||
{
|
{
|
||||||
free(full_uri);
|
free(full_uri);
|
||||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2730,7 +2729,7 @@ daap_request(struct evhttp_request *req)
|
|||||||
|
|
||||||
if (!uri)
|
if (!uri)
|
||||||
{
|
{
|
||||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2741,7 +2740,7 @@ daap_request(struct evhttp_request *req)
|
|||||||
if (!uri)
|
if (!uri)
|
||||||
{
|
{
|
||||||
free(full_uri);
|
free(full_uri);
|
||||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2762,7 +2761,7 @@ daap_request(struct evhttp_request *req)
|
|||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_DAAP, "Unrecognized DAAP request\n");
|
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(uri);
|
||||||
free(full_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);
|
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(uri);
|
||||||
free(full_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");
|
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(uri);
|
||||||
free(full_uri);
|
free(full_uri);
|
||||||
@ -2853,7 +2852,9 @@ daap_request(struct evhttp_request *req)
|
|||||||
ret = cache_daap_get(full_uri, evbuf);
|
ret = cache_daap_get(full_uri, evbuf);
|
||||||
if (ret == 0)
|
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);
|
evbuffer_free(evbuf);
|
||||||
free(uri);
|
free(uri);
|
||||||
|
@ -368,10 +368,10 @@ playstatusupdate_cb(int fd, short what, void *arg)
|
|||||||
{
|
{
|
||||||
buf = evbuffer_pullup(update, -1);
|
buf = evbuffer_pullup(update, -1);
|
||||||
evbuffer_add(evbuf, buf, len);
|
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
|
else
|
||||||
httpd_send_reply(ur->req, HTTP_OK, "OK", update);
|
httpd_send_reply(ur->req, HTTP_OK, "OK", update, 0);
|
||||||
|
|
||||||
free(ur);
|
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_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 */
|
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
|
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, "mstt", 200); /* 12 */
|
||||||
dmap_add_int(evbuf, "miid", id); /* 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
|
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, "mstt", 200); /* 12 */
|
||||||
dmap_add_int(evbuf, "miid", 0); /* 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
|
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 */
|
/* 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;
|
return;
|
||||||
|
|
||||||
out_fail:
|
out_fail:
|
||||||
evhttp_send_error(req, 500, "Internal Server Error");
|
httpd_send_error(req, 500, "Internal Server Error");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1301,7 +1301,7 @@ dacp_reply_pause(struct evhttp_request *req, struct evbuffer *evbuf, char **uri,
|
|||||||
player_playback_pause();
|
player_playback_pause();
|
||||||
|
|
||||||
/* 204 No Content is the canonical reply */
|
/* 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
|
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");
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 204 No Content is the canonical reply */
|
/* 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
|
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");
|
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;
|
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");
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 204 No Content is the canonical reply */
|
/* 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
|
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");
|
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;
|
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");
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 204 No Content is the canonical reply */
|
/* 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
|
static void
|
||||||
@ -1413,7 +1413,7 @@ dacp_reply_beginff(struct evhttp_request *req, struct evbuffer *evbuf, char **ur
|
|||||||
/* TODO */
|
/* TODO */
|
||||||
|
|
||||||
/* 204 No Content is the canonical reply */
|
/* 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
|
static void
|
||||||
@ -1428,7 +1428,7 @@ dacp_reply_beginrew(struct evhttp_request *req, struct evbuffer *evbuf, char **u
|
|||||||
/* TODO */
|
/* TODO */
|
||||||
|
|
||||||
/* 204 No Content is the canonical reply */
|
/* 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
|
static void
|
||||||
@ -1443,7 +1443,7 @@ dacp_reply_playresume(struct evhttp_request *req, struct evbuffer *evbuf, char *
|
|||||||
/* TODO */
|
/* TODO */
|
||||||
|
|
||||||
/* 204 No Content is the canonical reply */
|
/* 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
|
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, "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 */
|
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
|
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, "mstt", 200); /* 12 */
|
||||||
dmap_add_int(evbuf, "miid", 0); /* 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
|
static void
|
||||||
@ -1826,7 +1826,7 @@ dacp_reply_playqueueedit_add(struct evhttp_request *req, struct evbuffer *evbuf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 204 No Content is the canonical reply */
|
/* 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
|
static void
|
||||||
@ -1871,7 +1871,7 @@ dacp_reply_playqueueedit_move(struct evhttp_request *req, struct evbuffer *evbuf
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 204 No Content is the canonical reply */
|
/* 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
|
static void
|
||||||
@ -1903,7 +1903,7 @@ dacp_reply_playqueueedit_remove(struct evhttp_request *req, struct evbuffer *evb
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 204 No Content is the canonical reply */
|
/* 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
|
static void
|
||||||
@ -2023,9 +2023,9 @@ dacp_reply_playstatusupdate(struct evhttp_request *req, struct evbuffer *evbuf,
|
|||||||
{
|
{
|
||||||
ret = make_playstatusupdate(evbuf);
|
ret = make_playstatusupdate(evbuf);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
evhttp_send_error(req, 500, "Internal Server Error");
|
httpd_send_error(req, 500, "Internal Server Error");
|
||||||
else
|
else
|
||||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf);
|
httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0);
|
||||||
|
|
||||||
return;
|
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");
|
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;
|
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");
|
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;
|
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");
|
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;
|
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");
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2137,12 +2137,11 @@ dacp_reply_nowplayingartwork(struct evhttp_request *req, struct evbuffer *evbuf,
|
|||||||
snprintf(clen, sizeof(clen), "%ld", (long)len);
|
snprintf(clen, sizeof(clen), "%ld", (long)len);
|
||||||
evhttp_add_header(headers, "Content-Length", clen);
|
evhttp_add_header(headers, "Content-Length", clen);
|
||||||
|
|
||||||
/* No gzip compression for artwork */
|
httpd_send_reply(req, HTTP_OK, "OK", evbuf, HTTPD_SEND_NO_GZIP);
|
||||||
evhttp_send_reply(req, HTTP_OK, "OK", evbuf);
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
no_artwork:
|
no_artwork:
|
||||||
evhttp_send_error(req, HTTP_NOTFOUND, "Not Found");
|
httpd_send_error(req, HTTP_NOTFOUND, "Not Found");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -2243,7 +2242,7 @@ dacp_reply_getproperty(struct evhttp_request *req, struct evbuffer *evbuf, char
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf);
|
httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -2291,7 +2290,7 @@ dacp_reply_setproperty(struct evhttp_request *req, struct evbuffer *evbuf, char
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 204 No Content is the canonical reply */
|
/* 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
|
static void
|
||||||
@ -2354,7 +2353,7 @@ dacp_reply_getspeakers(struct evhttp_request *req, struct evbuffer *evbuf, char
|
|||||||
|
|
||||||
evbuffer_free(spklist);
|
evbuffer_free(spklist);
|
||||||
|
|
||||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf);
|
httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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");
|
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;
|
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");
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2437,15 +2436,15 @@ dacp_reply_setspeakers(struct evhttp_request *req, struct evbuffer *evbuf, char
|
|||||||
|
|
||||||
/* Password problem */
|
/* Password problem */
|
||||||
if (ret == -2)
|
if (ret == -2)
|
||||||
evhttp_send_error(req, 902, "");
|
httpd_send_error(req, 902, "");
|
||||||
else
|
else
|
||||||
evhttp_send_error(req, 500, "Internal Server Error");
|
httpd_send_error(req, 500, "Internal Server Error");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 204 No Content is the canonical reply */
|
/* 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);
|
full_uri = httpd_fixup_uri(req);
|
||||||
if (!full_uri)
|
if (!full_uri)
|
||||||
{
|
{
|
||||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2560,7 +2559,7 @@ dacp_request(struct evhttp_request *req)
|
|||||||
if (!uri)
|
if (!uri)
|
||||||
{
|
{
|
||||||
free(full_uri);
|
free(full_uri);
|
||||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2588,7 +2587,7 @@ dacp_request(struct evhttp_request *req)
|
|||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_DACP, "Unrecognized DACP request\n");
|
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(uri);
|
||||||
free(full_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);
|
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(uri);
|
||||||
free(full_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");
|
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(uri);
|
||||||
free(full_uri);
|
free(full_uri);
|
||||||
|
@ -251,7 +251,7 @@ rsp_send_error(struct evhttp_request *req, char *errmsg)
|
|||||||
|
|
||||||
if (!evbuf)
|
if (!evbuf)
|
||||||
{
|
{
|
||||||
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
|
httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -259,7 +259,8 @@ rsp_send_error(struct evhttp_request *req, char *errmsg)
|
|||||||
headers = evhttp_request_get_output_headers(req);
|
headers = evhttp_request_get_output_headers(req);
|
||||||
evhttp_add_header(headers, "Content-Type", "text/xml; charset=utf-8");
|
evhttp_add_header(headers, "Content-Type", "text/xml; charset=utf-8");
|
||||||
evhttp_add_header(headers, "Connection", "close");
|
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);
|
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);
|
headers = evhttp_request_get_output_headers(req);
|
||||||
evhttp_add_header(headers, "Content-Type", "text/xml; charset=utf-8");
|
evhttp_add_header(headers, "Content-Type", "text/xml; charset=utf-8");
|
||||||
evhttp_add_header(headers, "Connection", "close");
|
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);
|
evbuffer_free(evbuf);
|
||||||
}
|
}
|
||||||
@ -745,7 +747,7 @@ rsp_stream(struct evhttp_request *req, char **uri, struct evkeyvalq *query)
|
|||||||
|
|
||||||
ret = safe_atoi32(uri[2], &id);
|
ret = safe_atoi32(uri[2], &id);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||||
else
|
else
|
||||||
httpd_stream_file(req, id);
|
httpd_stream_file(req, id);
|
||||||
}
|
}
|
||||||
|
18
src/mpd.c
18
src/mpd.c
@ -55,6 +55,7 @@
|
|||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "db.h"
|
#include "db.h"
|
||||||
#include "conffile.h"
|
#include "conffile.h"
|
||||||
|
#include "httpd.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "listener.h"
|
#include "listener.h"
|
||||||
#include "artwork.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)
|
if (evhttp_request_get_command(req) != EVHTTP_REQ_GET)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_MPD, "Unsupported request type for artwork\n");
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4545,7 +4546,7 @@ artwork_cb(struct evhttp_request *req, void *arg)
|
|||||||
if (!decoded)
|
if (!decoded)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_MPD, "Bad artwork request with uri '%s'\n", uri);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4553,7 +4554,7 @@ artwork_cb(struct evhttp_request *req, void *arg)
|
|||||||
if (!path)
|
if (!path)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_MPD, "Invalid path from artwork request with uri '%s'\n", uri);
|
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);
|
evhttp_uri_free(decoded);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -4562,7 +4563,7 @@ artwork_cb(struct evhttp_request *req, void *arg)
|
|||||||
if (!decoded_path)
|
if (!decoded_path)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_MPD, "Error decoding path from artwork request with uri '%s'\n", uri);
|
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);
|
evhttp_uri_free(decoded);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -4577,7 +4578,7 @@ artwork_cb(struct evhttp_request *req, void *arg)
|
|||||||
if (!itemid)
|
if (!itemid)
|
||||||
{
|
{
|
||||||
DPRINTF(E_WARN, L_MPD, "No item found for path '%s' from request uri '%s'\n", decoded_path, uri);
|
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);
|
evhttp_uri_free(decoded);
|
||||||
free(decoded_path);
|
free(decoded_path);
|
||||||
return;
|
return;
|
||||||
@ -4587,7 +4588,7 @@ artwork_cb(struct evhttp_request *req, void *arg)
|
|||||||
if (!evbuffer)
|
if (!evbuffer)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_MPD, "Could not allocate an evbuffer for artwork request\n");
|
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);
|
evhttp_uri_free(decoded);
|
||||||
free(decoded_path);
|
free(decoded_path);
|
||||||
return;
|
return;
|
||||||
@ -4596,7 +4597,7 @@ artwork_cb(struct evhttp_request *req, void *arg)
|
|||||||
format = artwork_get_item(evbuffer, itemid, 600, 600);
|
format = artwork_get_item(evbuffer, itemid, 600, 600);
|
||||||
if (format < 0)
|
if (format < 0)
|
||||||
{
|
{
|
||||||
evhttp_send_error(req, HTTP_NOTFOUND, "Document was not found");
|
httpd_send_error(req, HTTP_NOTFOUND, "Document was not found");
|
||||||
}
|
}
|
||||||
else
|
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");
|
evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "image/jpeg");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
evhttp_send_reply(req, HTTP_OK, "OK", evbuffer);
|
|
||||||
|
httpd_send_reply(req, HTTP_OK, "OK", evbuffer, HTTPD_SEND_NO_GZIP);
|
||||||
}
|
}
|
||||||
|
|
||||||
evbuffer_free(evbuffer);
|
evbuffer_free(evbuffer);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user