From e17da71a704759316912d4f2b7eb46d95a828798 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 25 Oct 2013 00:32:48 +0200 Subject: output/httpd: support HEAD requests --- NEWS | 1 + src/output/HttpdClient.cxx | 29 ++++++++++++++++++++++++----- src/output/HttpdClient.hxx | 5 +++++ 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index 9b9535d40..7e7cd5ff8 100644 --- a/NEWS +++ b/NEWS @@ -28,6 +28,7 @@ ver 0.18 (2012/??/??) - new option "tags" may be used to disable sending tags to output - alsa: workaround for noise after manual song change - ffado: remove broken plugin + - httpd: support HEAD requests - mvp: remove obsolete plugin * improved decoder/output error reporting * eliminate timer wakeup on idle MPD diff --git a/src/output/HttpdClient.cxx b/src/output/HttpdClient.cxx index 9b4b6b8ca..206062d2c 100644 --- a/src/output/HttpdClient.cxx +++ b/src/output/HttpdClient.cxx @@ -66,7 +66,8 @@ HttpdClient::BeginResponse() state = RESPONSE; current_page = nullptr; - httpd->SendHeader(*this); + if (!head_method) + httpd->SendHeader(*this); } /** @@ -78,16 +79,25 @@ HttpdClient::HandleLine(const char *line) assert(state != RESPONSE); if (state == REQUEST) { - if (memcmp(line, "GET /", 5) != 0) { + if (memcmp(line, "HEAD /", 6) == 0) { + line += 6; + head_method = true; + } else if (memcmp(line, "GET /", 5) == 0) { + line += 5; + } else { /* only GET is supported */ LogWarning(httpd_output_domain, "malformed request line from client"); return false; } - line = strchr(line + 5, ' '); + line = strchr(line, ' '); if (line == nullptr || memcmp(line + 1, "HTTP/", 5) != 0) { /* HTTP/0.9 without request headers */ + + if (head_method) + return false; + BeginResponse(); return true; } @@ -98,6 +108,7 @@ HttpdClient::HandleLine(const char *line) } else { if (*line == 0) { /* empty line: request is finished */ + BeginResponse(); return true; } @@ -185,6 +196,7 @@ HttpdClient::HttpdClient(HttpdOutput *_httpd, int _fd, EventLoop &_loop, :BufferedSocket(_fd, _loop), httpd(_httpd), state(REQUEST), + head_method(false), dlna_streaming_requested(false), metadata_supported(_metadata_supported), metadata_requested(false), metadata_sent(true), @@ -427,8 +439,15 @@ HttpdClient::OnSocketInput(void *data, size_t length) return InputResult::CLOSED; } - if (state == RESPONSE && !SendResponse()) - return InputResult::CLOSED; + if (state == RESPONSE) { + if (!SendResponse()) + return InputResult::CLOSED; + + if (head_method) { + LockClose(); + return InputResult::CLOSED; + } + } return InputResult::AGAIN; } diff --git a/src/output/HttpdClient.hxx b/src/output/HttpdClient.hxx index 90295fdf7..66a819232 100644 --- a/src/output/HttpdClient.hxx +++ b/src/output/HttpdClient.hxx @@ -66,6 +66,11 @@ class HttpdClient final : public BufferedSocket { */ size_t current_position; + /** + * Is this a HEAD request? + */ + bool head_method; + /** * If DLNA streaming was an option. */ -- cgit v1.2.3