mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-22 23:52:03 +00:00
dbms: returning proper HTTP code in case of errors [#CONV-2944].
This commit is contained in:
parent
b205d51215
commit
274f2d0828
55
dbms/include/DB/IO/WriteBufferFromHTTPServerResponse.h
Normal file
55
dbms/include/DB/IO/WriteBufferFromHTTPServerResponse.h
Normal file
@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
|
||||
#include <Poco/Net/HTTPServerResponse.h>
|
||||
|
||||
#include <DB/Core/Exception.h>
|
||||
#include <DB/Core/ErrorCodes.h>
|
||||
|
||||
#include <DB/IO/WriteBuffer.h>
|
||||
#include <DB/IO/BufferWithOwnMemory.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
|
||||
/** Отличается от WriteBufferFromOStream тем, что инициализируется не std::ostream, а Poco::Net::HTTPServerResponse.
|
||||
* При первом сбросе данных, получает из него std::ostream (с помощью метода send).
|
||||
* Это нужно в HTTP серверах, чтобы после передачи в какой-нибудь метод WriteBuffer-а,
|
||||
* но до вывода первых данных клиенту, можно было изменить какие-нибудь HTTP заголовки (например, код ответа).
|
||||
* (После вызова Poco::Net::HTTPServerResponse::send() изменить заголовки уже нельзя.)
|
||||
* То есть, суть в том, чтобы вызывать метод Poco::Net::HTTPServerResponse::send() не сразу.
|
||||
*/
|
||||
class WriteBufferFromHTTPServerResponse : public BufferWithOwnMemory<WriteBuffer>
|
||||
{
|
||||
private:
|
||||
Poco::Net::HTTPServerResponse & response;
|
||||
std::ostream * ostr;
|
||||
|
||||
void nextImpl()
|
||||
{
|
||||
if (!ostr)
|
||||
ostr = &response.send();
|
||||
|
||||
if (!offset())
|
||||
return;
|
||||
|
||||
ostr->write(working_buffer.begin(), offset());
|
||||
ostr->flush();
|
||||
|
||||
if (!ostr->good())
|
||||
throw Exception("Cannot write to ostream", ErrorCodes::CANNOT_WRITE_TO_OSTREAM);
|
||||
}
|
||||
|
||||
public:
|
||||
WriteBufferFromHTTPServerResponse(Poco::Net::HTTPServerResponse & response_, size_t size = DBMS_DEFAULT_BUFFER_SIZE)
|
||||
: BufferWithOwnMemory<WriteBuffer>(size), response(response_), ostr(NULL) {}
|
||||
|
||||
~WriteBufferFromHTTPServerResponse()
|
||||
{
|
||||
if (!std::uncaught_exception())
|
||||
next();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
@ -12,7 +12,7 @@
|
||||
#include <DB/IO/ConcatReadBuffer.h>
|
||||
#include <DB/IO/CompressedReadBuffer.h>
|
||||
#include <DB/IO/CompressedWriteBuffer.h>
|
||||
#include <DB/IO/WriteBufferFromOStream.h>
|
||||
#include <DB/IO/WriteBufferFromHTTPServerResponse.h>
|
||||
#include <DB/IO/WriteBufferFromString.h>
|
||||
#include <DB/IO/WriteHelpers.h>
|
||||
|
||||
@ -40,7 +40,7 @@ struct HTMLForm : public Poco::Net::HTMLForm
|
||||
};
|
||||
|
||||
|
||||
void HTTPHandler::processQuery(Poco::Net::NameValueCollection & params, std::ostream & ostr, std::istream & istr)
|
||||
void HTTPHandler::processQuery(Poco::Net::NameValueCollection & params, Poco::Net::HTTPServerResponse & response, std::istream & istr)
|
||||
{
|
||||
BlockInputStreamPtr query_plan;
|
||||
|
||||
@ -64,7 +64,7 @@ void HTTPHandler::processQuery(Poco::Net::NameValueCollection & params, std::ost
|
||||
ConcatReadBuffer in(in_param, *in_post_maybe_compressed);
|
||||
|
||||
/// Если указано compress, то будем сжимать результат.
|
||||
SharedPtr<WriteBuffer> out = new WriteBufferFromOStream(ostr);
|
||||
SharedPtr<WriteBuffer> out = new WriteBufferFromHTTPServerResponse(response);
|
||||
SharedPtr<WriteBuffer> out_maybe_compressed;
|
||||
|
||||
if (0 != Poco::NumberParser::parseUnsigned(params.get("compress", "0")))
|
||||
@ -130,28 +130,41 @@ void HTTPHandler::handleRequest(Poco::Net::HTTPServerRequest & request, Poco::Ne
|
||||
|
||||
if (is_browser)
|
||||
response.setContentType("text/plain; charset=UTF-8");
|
||||
|
||||
std::ostream & ostr = response.send();
|
||||
|
||||
try
|
||||
{
|
||||
LOG_TRACE(log, "Request URI: " << request.getURI());
|
||||
|
||||
HTMLForm params(request);
|
||||
std::istream & istr = request.stream();
|
||||
processQuery(params, ostr, istr);
|
||||
processQuery(params, response, istr);
|
||||
|
||||
LOG_INFO(log, "Done processing query");
|
||||
}
|
||||
catch (DB::Exception & e)
|
||||
{
|
||||
response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR);
|
||||
std::ostream & ostr = response.send();
|
||||
std::stringstream s;
|
||||
s << "Code: " << e.code()
|
||||
<< ", e.displayText() = " << e.displayText() << ", e.what() = " << e.what();
|
||||
ostr << s.str() << std::endl;
|
||||
LOG_ERROR(log, s.str());
|
||||
}
|
||||
catch (Poco::Exception & e)
|
||||
{
|
||||
response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR);
|
||||
std::ostream & ostr = response.send();
|
||||
std::stringstream s;
|
||||
s << "Code: " << ErrorCodes::POCO_EXCEPTION << ", e.code() = " << e.code()
|
||||
<< ", e.message() = " << e.message() << ", e.what() = " << e.what();
|
||||
<< ", e.displayText() = " << e.displayText() << ", e.what() = " << e.what();
|
||||
ostr << s.str() << std::endl;
|
||||
LOG_ERROR(log, s.str());
|
||||
}
|
||||
catch (std::exception & e)
|
||||
{
|
||||
response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR);
|
||||
std::ostream & ostr = response.send();
|
||||
std::stringstream s;
|
||||
s << "Code: " << ErrorCodes::STD_EXCEPTION << ". " << e.what();
|
||||
ostr << s.str() << std::endl;
|
||||
@ -159,6 +172,8 @@ void HTTPHandler::handleRequest(Poco::Net::HTTPServerRequest & request, Poco::Ne
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR);
|
||||
std::ostream & ostr = response.send();
|
||||
std::stringstream s;
|
||||
s << "Code: " << ErrorCodes::UNKNOWN_EXCEPTION << ". Unknown exception.";
|
||||
ostr << s.str() << std::endl;
|
||||
|
@ -25,7 +25,7 @@ private:
|
||||
|
||||
Logger * log;
|
||||
|
||||
void processQuery(Poco::Net::NameValueCollection & params, std::ostream & ostr, std::istream & istr);
|
||||
void processQuery(Poco::Net::NameValueCollection & params, Poco::Net::HTTPServerResponse & response, std::istream & istr);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ void TCPHandler::runImpl()
|
||||
}
|
||||
catch (DB::Exception & e)
|
||||
{
|
||||
LOG_ERROR(log, "DB::Exception. Code: " << e.code() << ", e.displayText() = " << e.displayText()
|
||||
LOG_ERROR(log, "DB::Exception. Code: " << e.code() << ", e.displayText() = " << e.displayText() << ", e.what() = " << e.what()
|
||||
<< ", Stack trace:\n\n" << e.getStackTrace().toString());
|
||||
state.exception = e.clone();
|
||||
|
||||
@ -102,7 +102,8 @@ void TCPHandler::runImpl()
|
||||
}
|
||||
catch (Poco::Exception & e)
|
||||
{
|
||||
LOG_ERROR(log, "Poco::Exception. Code: " << ErrorCodes::POCO_EXCEPTION << ", e.code() = " << e.code() << ", e.displayText() = " << e.displayText());
|
||||
LOG_ERROR(log, "Poco::Exception. Code: " << ErrorCodes::POCO_EXCEPTION << ", e.code() = " << e.code()
|
||||
<< ", e.displayText() = " << e.displayText() << ", e.what() = " << e.what());
|
||||
state.exception = new Exception(e.message(), e.code());
|
||||
}
|
||||
catch (std::exception & e)
|
||||
|
Loading…
Reference in New Issue
Block a user