From e8f5a3b44ec1eeafb49d0adb59165c06ec365634 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Sun, 9 Jul 2023 14:12:08 +0800 Subject: [PATCH 1/3] Fix response for HTTP HEAD method Closes #19288. --- src/base/http/connection.cpp | 26 +++++++++++++++++++++----- src/base/http/responsegenerator.cpp | 5 +++-- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/base/http/connection.cpp b/src/base/http/connection.cpp index 617b64163..ff39cccbc 100644 --- a/src/base/http/connection.cpp +++ b/src/base/http/connection.cpp @@ -123,14 +123,30 @@ void Connection::read() { const Environment env {m_socket->localAddress(), m_socket->localPort(), m_socket->peerAddress(), m_socket->peerPort()}; - Response resp = m_requestHandler->processRequest(result.request, env); + if (result.request.method == HEADER_REQUEST_METHOD_HEAD) + { + Request getRequest = result.request; + getRequest.method = HEADER_REQUEST_METHOD_GET; - if (acceptsGzipEncoding(result.request.headers[u"accept-encoding"_s])) - resp.headers[HEADER_CONTENT_ENCODING] = u"gzip"_s; + Response resp = m_requestHandler->processRequest(getRequest, env); - resp.headers[HEADER_CONNECTION] = u"keep-alive"_s; + resp.headers[HEADER_CONNECTION] = u"keep-alive"_s; + resp.headers[HEADER_CONTENT_LENGTH] = QString::number(resp.content.length()); + resp.content.clear(); + + sendResponse(resp); + } + else + { + Response resp = m_requestHandler->processRequest(result.request, env); + + if (acceptsGzipEncoding(result.request.headers.value(u"accept-encoding"_s))) + resp.headers[HEADER_CONTENT_ENCODING] = u"gzip"_s; + resp.headers[HEADER_CONNECTION] = u"keep-alive"_s; + + sendResponse(resp); + } - sendResponse(resp); m_receivedData.remove(0, result.frameSize); } break; diff --git a/src/base/http/responsegenerator.cpp b/src/base/http/responsegenerator.cpp index a152e7fe2..b34b973db 100644 --- a/src/base/http/responsegenerator.cpp +++ b/src/base/http/responsegenerator.cpp @@ -38,8 +38,9 @@ QByteArray Http::toByteArray(Response response) { compressContent(response); - response.headers[HEADER_CONTENT_LENGTH] = QString::number(response.content.length()); response.headers[HEADER_DATE] = httpDate(); + if (QString &value = response.headers[HEADER_CONTENT_LENGTH]; value.isEmpty()) + value = QString::number(response.content.length()); QByteArray buf; buf.reserve(1024 + response.content.length()); @@ -63,7 +64,7 @@ QByteArray Http::toByteArray(Response response) // the first empty line buf += CRLF; - // message body // TODO: support HEAD request + // message body buf += response.content; return buf; From cb0c09769f6b2bff94ecdb8784c33942c6428e91 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Sun, 9 Jul 2023 14:58:34 +0800 Subject: [PATCH 2/3] Response proper error status for invalid request methods --- src/base/http/connection.cpp | 13 +++++++++++++ src/base/http/requestparser.cpp | 4 ++-- src/base/http/requestparser.h | 1 + 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/base/http/connection.cpp b/src/base/http/connection.cpp index ff39cccbc..1b5333f9b 100644 --- a/src/base/http/connection.cpp +++ b/src/base/http/connection.cpp @@ -106,6 +106,19 @@ void Connection::read() } return; + case RequestParser::ParseStatus::BadMethod: + { + LogMsg(tr("Bad Http request method, closing socket. IP: %1. Method: \"%2\"") + .arg(m_socket->peerAddress().toString(), result.request.method), Log::WARNING); + + Response resp(501, u"Not Implemented"_s); + resp.headers[HEADER_CONNECTION] = u"close"_s; + + sendResponse(resp); + m_socket->close(); + } + return; + case RequestParser::ParseStatus::BadRequest: { LogMsg(tr("Bad Http request, closing socket. IP: %1") diff --git a/src/base/http/requestparser.cpp b/src/base/http/requestparser.cpp index 540f6481c..2568e4a55 100644 --- a/src/base/http/requestparser.cpp +++ b/src/base/http/requestparser.cpp @@ -103,6 +103,7 @@ RequestParser::ParseResult RequestParser::doParse(const QByteArray &data) // handle supported methods if ((m_request.method == HEADER_REQUEST_METHOD_GET) || (m_request.method == HEADER_REQUEST_METHOD_HEAD)) return {ParseStatus::OK, m_request, headerLength}; + if (m_request.method == HEADER_REQUEST_METHOD_POST) { const auto parseContentLength = [this]() -> int @@ -146,8 +147,7 @@ RequestParser::ParseResult RequestParser::doParse(const QByteArray &data) return {ParseStatus::OK, m_request, (headerLength + contentLength)}; } - qWarning() << Q_FUNC_INFO << "unsupported request method: " << m_request.method; - return {ParseStatus::BadRequest, Request(), 0}; // TODO: SHOULD respond "501 Not Implemented" + return {ParseStatus::BadMethod, m_request, 0}; } bool RequestParser::parseStartLines(const QStringView data) diff --git a/src/base/http/requestparser.h b/src/base/http/requestparser.h index 0cab0db0e..b55907ea4 100644 --- a/src/base/http/requestparser.h +++ b/src/base/http/requestparser.h @@ -41,6 +41,7 @@ namespace Http { OK, Incomplete, + BadMethod, BadRequest }; From 543745b3f2a2a4824b318e4c8f7f8add1767a45f Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Sun, 9 Jul 2023 16:29:25 +0800 Subject: [PATCH 3/3] Avoid stuffing the log via junk requests --- src/base/http/connection.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/base/http/connection.cpp b/src/base/http/connection.cpp index 1b5333f9b..f6514e365 100644 --- a/src/base/http/connection.cpp +++ b/src/base/http/connection.cpp @@ -32,7 +32,6 @@ #include -#include "base/logger.h" #include "irequesthandler.h" #include "requestparser.h" #include "responsegenerator.h" @@ -94,8 +93,8 @@ void Connection::read() const long bufferLimit = RequestParser::MAX_CONTENT_SIZE * 1.1; // some margin for headers if (m_receivedData.size() > bufferLimit) { - LogMsg(tr("Http request size exceeds limitation, closing socket. Limit: %1, IP: %2") - .arg(bufferLimit).arg(m_socket->peerAddress().toString()), Log::WARNING); + qWarning("%s", qUtf8Printable(tr("Http request size exceeds limitation, closing socket. Limit: %1, IP: %2") + .arg(QString::number(bufferLimit), m_socket->peerAddress().toString()))); Response resp(413, u"Payload Too Large"_s); resp.headers[HEADER_CONNECTION] = u"close"_s; @@ -108,8 +107,8 @@ void Connection::read() case RequestParser::ParseStatus::BadMethod: { - LogMsg(tr("Bad Http request method, closing socket. IP: %1. Method: \"%2\"") - .arg(m_socket->peerAddress().toString(), result.request.method), Log::WARNING); + qWarning("%s", qUtf8Printable(tr("Bad Http request method, closing socket. IP: %1. Method: \"%2\"") + .arg(m_socket->peerAddress().toString(), result.request.method))); Response resp(501, u"Not Implemented"_s); resp.headers[HEADER_CONNECTION] = u"close"_s; @@ -121,8 +120,8 @@ void Connection::read() case RequestParser::ParseStatus::BadRequest: { - LogMsg(tr("Bad Http request, closing socket. IP: %1") - .arg(m_socket->peerAddress().toString()), Log::WARNING); + qWarning("%s", qUtf8Printable(tr("Bad Http request, closing socket. IP: %1") + .arg(m_socket->peerAddress().toString()))); Response resp(400, u"Bad Request"_s); resp.headers[HEADER_CONNECTION] = u"close"_s;