output/httpd/Client: pass std::string_view to HandleLine()
This commit is contained in:
parent
1e5c37ee78
commit
91ca502e10
@ -3,19 +3,19 @@
|
|||||||
|
|
||||||
#include "HttpdClient.hxx"
|
#include "HttpdClient.hxx"
|
||||||
#include "HttpdInternal.hxx"
|
#include "HttpdInternal.hxx"
|
||||||
#include "util/ASCII.hxx"
|
|
||||||
#include "util/AllocatedString.hxx"
|
#include "util/AllocatedString.hxx"
|
||||||
#include "Page.hxx"
|
#include "Page.hxx"
|
||||||
#include "IcyMetaDataServer.hxx"
|
#include "IcyMetaDataServer.hxx"
|
||||||
#include "net/SocketError.hxx"
|
#include "net/SocketError.hxx"
|
||||||
#include "net/UniqueSocketDescriptor.hxx"
|
#include "net/UniqueSocketDescriptor.hxx"
|
||||||
#include "util/SpanCast.hxx"
|
#include "util/SpanCast.hxx"
|
||||||
|
#include "util/StringCompare.hxx"
|
||||||
|
#include "util/StringSplit.hxx"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
|
|
||||||
#include <fmt/core.h>
|
#include <fmt/core.h>
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
using std::string_view_literals::operator""sv;
|
using std::string_view_literals::operator""sv;
|
||||||
|
|
||||||
@ -51,36 +51,31 @@ HttpdClient::BeginResponse() noexcept
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
HttpdClient::HandleLine(const char *line) noexcept
|
HttpdClient::HandleLine(std::string_view line) noexcept
|
||||||
{
|
{
|
||||||
assert(state != State::RESPONSE);
|
assert(state != State::RESPONSE);
|
||||||
|
|
||||||
if (state == State::REQUEST) {
|
if (state == State::REQUEST) {
|
||||||
if (strncmp(line, "HEAD /", 6) == 0) {
|
if (SkipPrefix(line, "HEAD /"sv)) {
|
||||||
line += 6;
|
|
||||||
head_method = true;
|
head_method = true;
|
||||||
} else if (strncmp(line, "GET /", 5) == 0) {
|
} else if (!SkipPrefix(line, "GET /"sv)) {
|
||||||
line += 5;
|
|
||||||
} else {
|
|
||||||
/* only GET is supported */
|
/* only GET is supported */
|
||||||
LogWarning(httpd_output_domain,
|
LogWarning(httpd_output_domain,
|
||||||
"malformed request line from client");
|
"malformed request line from client");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto [uri, rest] = Split(line, ' ');
|
||||||
|
|
||||||
/* blacklist some well-known request paths */
|
/* blacklist some well-known request paths */
|
||||||
if ((strncmp(line, "favicon.ico", 11) == 0 &&
|
if (uri == "favicon.ico"sv ||
|
||||||
(line[11] == '\0' || line[11] == ' ')) ||
|
uri == "robots.txt"sv ||
|
||||||
(strncmp(line, "robots.txt", 10) == 0 &&
|
uri == "sitemap.xml"sv ||
|
||||||
(line[10] == '\0' || line[10] == ' ')) ||
|
uri.starts_with(".well-known/"sv)) {
|
||||||
(strncmp(line, "sitemap.xml", 11) == 0 &&
|
|
||||||
(line[11] == '\0' || line[11] == ' ')) ||
|
|
||||||
(strncmp(line, ".well-known/", 12) == 0)) {
|
|
||||||
should_reject = true;
|
should_reject = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
line = std::strchr(line, ' ');
|
if (!rest.starts_with("HTTP/"sv)) {
|
||||||
if (line == nullptr || strncmp(line + 1, "HTTP/", 5) != 0) {
|
|
||||||
/* HTTP/0.9 without request headers */
|
/* HTTP/0.9 without request headers */
|
||||||
|
|
||||||
if (head_method)
|
if (head_method)
|
||||||
@ -94,15 +89,15 @@ HttpdClient::HandleLine(const char *line) noexcept
|
|||||||
state = State::HEADERS;
|
state = State::HEADERS;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
if (*line == 0) {
|
if (line.empty()) {
|
||||||
/* empty line: request is finished */
|
/* empty line: request is finished */
|
||||||
|
|
||||||
BeginResponse();
|
BeginResponse();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringEqualsCaseASCII(line, "Icy-MetaData: 1", 15) ||
|
if (StringIsEqualIgnoreCase(line, "Icy-MetaData: 1"sv) ||
|
||||||
StringEqualsCaseASCII(line, "Icy-MetaData:1", 14)) {
|
StringIsEqualIgnoreCase(line, "Icy-MetaData:1"sv)) {
|
||||||
/* Send icy metadata */
|
/* Send icy metadata */
|
||||||
metadata_requested = metadata_supported;
|
metadata_requested = metadata_supported;
|
||||||
return true;
|
return true;
|
||||||
@ -379,7 +374,7 @@ HttpdClient::OnSocketReady(unsigned flags) noexcept
|
|||||||
}
|
}
|
||||||
|
|
||||||
BufferedSocket::InputResult
|
BufferedSocket::InputResult
|
||||||
HttpdClient::OnSocketInput(std::span<std::byte> src) noexcept
|
HttpdClient::OnSocketInput(std::span<std::byte> _src) noexcept
|
||||||
{
|
{
|
||||||
if (state == State::RESPONSE) {
|
if (state == State::RESPONSE) {
|
||||||
LogWarning(httpd_output_domain,
|
LogWarning(httpd_output_domain,
|
||||||
@ -388,18 +383,15 @@ HttpdClient::OnSocketInput(std::span<std::byte> src) noexcept
|
|||||||
return InputResult::CLOSED;
|
return InputResult::CLOSED;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *line = (char *)src.data();
|
const auto src = ToStringView(_src);
|
||||||
char *newline = (char *)std::memchr(line, '\n', src.size());
|
auto [line, rest] = Split(src, '\n');
|
||||||
if (newline == nullptr)
|
if (rest.data() == nullptr)
|
||||||
return InputResult::MORE;
|
return InputResult::MORE;
|
||||||
|
|
||||||
ConsumeInput(newline + 1 - line);
|
ConsumeInput(line.size() + 1);
|
||||||
|
|
||||||
if (newline > line && newline[-1] == '\r')
|
if (line.ends_with('\r'))
|
||||||
--newline;
|
line.remove_suffix(1);
|
||||||
|
|
||||||
/* terminate the string at the end of the line */
|
|
||||||
*newline = 0;
|
|
||||||
|
|
||||||
if (!HandleLine(line)) {
|
if (!HandleLine(line)) {
|
||||||
LockClose();
|
LockClose();
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
// Copyright The Music Player Daemon Project
|
// Copyright The Music Player Daemon Project
|
||||||
|
|
||||||
#ifndef MPD_OUTPUT_HTTPD_CLIENT_HXX
|
#pragma once
|
||||||
#define MPD_OUTPUT_HTTPD_CLIENT_HXX
|
|
||||||
|
|
||||||
#include "Page.hxx"
|
#include "Page.hxx"
|
||||||
#include "event/BufferedSocket.hxx"
|
#include "event/BufferedSocket.hxx"
|
||||||
@ -11,6 +10,7 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
class UniqueSocketDescriptor;
|
class UniqueSocketDescriptor;
|
||||||
class HttpdOutput;
|
class HttpdOutput;
|
||||||
@ -143,7 +143,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Handle a line of the HTTP request.
|
* Handle a line of the HTTP request.
|
||||||
*/
|
*/
|
||||||
bool HandleLine(const char *line) noexcept;
|
bool HandleLine(std::string_view line) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Switch the client to #State::RESPONSE.
|
* Switch the client to #State::RESPONSE.
|
||||||
@ -185,5 +185,3 @@ protected:
|
|||||||
void OnSocketError(std::exception_ptr ep) noexcept override;
|
void OnSocketError(std::exception_ptr ep) noexcept override;
|
||||||
void OnSocketClosed() noexcept override;
|
void OnSocketClosed() noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
|
||||||
|
Loading…
Reference in New Issue
Block a user