提交 97277ed6 编写于 作者: V Vitaliy Lyudvichenko 提交者: alexey-milovidov

Return 411 code in case of empty body without Content-Length head. [#CLICKHOUSE-3333]

上级 4e4355a2
......@@ -383,6 +383,7 @@ namespace ErrorCodes
extern const int DATA_TYPE_CANNOT_HAVE_ARGUMENTS = 378;
extern const int UNKNOWN_STATUS_OF_DISTRIBUTED_DDL_TASK = 379;
extern const int CANNOT_KILL = 380;
extern const int HTTP_LENGTH_REQUIRED = 381;
extern const int KEEPER_EXCEPTION = 999;
extern const int POCO_EXCEPTION = 1000;
......
......@@ -84,6 +84,7 @@ namespace ErrorCodes
extern const int REQUIRED_PASSWORD;
extern const int INVALID_SESSION_TIMEOUT;
extern const int HTTP_LENGTH_REQUIRED;
}
......@@ -127,6 +128,8 @@ static Poco::Net::HTTPResponse::HTTPStatus exceptionCodeToHTTPStatus(int excepti
else if (exception_code == ErrorCodes::SOCKET_TIMEOUT ||
exception_code == ErrorCodes::CANNOT_OPEN_FILE)
return HTTPResponse::HTTP_SERVICE_UNAVAILABLE;
else if (exception_code == ErrorCodes::HTTP_LENGTH_REQUIRED)
return HTTPResponse::HTTP_LENGTH_REQUIRED;
return HTTPResponse::HTTP_INTERNAL_SERVER_ERROR;
}
......@@ -379,14 +382,7 @@ void HTTPHandler::processQuery(
std::unique_ptr<ReadBuffer> in_param = std::make_unique<ReadBufferFromString>(query_param);
std::unique_ptr<ReadBuffer> in_post_raw;
/// A grubby workaround for CLICKHOUSE-3333 problem. This condition should detect POST query with empty body.
/// In that case Poco doesn't work properly and returns HTTPInputStream which just listen TCP connection.
/// NOTE: if Poco are updated, this heuristic might not work properly.
if (typeid_cast<Poco::Net::HTTPInputStream *>(&istr) == nullptr)
in_post_raw = std::make_unique<ReadBufferFromIStream>(istr);
else
in_post_raw = std::make_unique<ReadBufferFromString>(String()); // will read empty body.
std::unique_ptr<ReadBuffer> in_post_raw = std::make_unique<ReadBufferFromIStream>(istr);
/// Request body can be compressed using algorithm specified in the Content-Encoding header.
std::unique_ptr<ReadBuffer> in_post;
......@@ -567,7 +563,8 @@ void HTTPHandler::trySendExceptionToClient(const std::string & s, int exception_
/// to avoid reading part of the current request body in the next request.
if (request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST
&& response.getKeepAlive()
&& !request.stream().eof())
&& !request.stream().eof()
&& exception_code != ErrorCodes::HTTP_LENGTH_REQUIRED)
{
request.stream().ignore(std::numeric_limits<std::streamsize>::max());
}
......@@ -642,6 +639,13 @@ void HTTPHandler::handleRequest(Poco::Net::HTTPServerRequest & request, Poco::Ne
HTMLForm params(request);
with_stacktrace = params.getParsed<bool>("stacktrace", false);
/// Workaround. Poco does not detect 411 Length Required case.
if (request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST && !request.getChunkedTransferEncoding() &&
!request.hasContentLength())
{
throw Exception("There is neither Transfer-Encoding header nor Content-Length header", ErrorCodes::HTTP_LENGTH_REQUIRED);
}
processQuery(request, params, response, used_output);
LOG_INFO(log, "Done processing query");
}
......
......@@ -10,5 +10,3 @@ Content-Type: text/tab-separated-values; charset=UTF-8
Transfer-Encoding: chunked
Keep-Alive: timeout=3
1
1
......@@ -3,5 +3,6 @@
( curl -s --head "${CLICKHOUSE_URL:=http://localhost:8123/}?query=SELECT%201";
curl -s --head "${CLICKHOUSE_URL:=http://localhost:8123/}?query=select+*+from+system.numbers+limit+1000000" ) | grep -v "Date:"
curl -sS -X POST "http://127.0.0.1:8123?query=SELECT+1"
curl -sS -X POST "http://127.0.0.1:8123?query=SELECT+1" --data ''
if [[ `curl -sS -X POST -I "http://127.0.0.1:8123?query=SELECT+1" | grep -c '411 Length Required'` -ne 1 ]]; then
echo FAIL
fi
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册