ClickHouse/dbms/include/DB/IO/WriteBufferFromHTTPServerResponse.h

68 lines
1.9 KiB
C
Raw Normal View History

#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 (!offset())
return;
2013-11-18 17:17:45 +00:00
try
2012-11-19 04:16:00 +00:00
{
if (!ostr)
ostr = &response.send();
next();
2012-11-19 04:16:00 +00:00
}
2013-11-18 17:17:45 +00:00
catch (...)
{
2013-11-18 19:18:03 +00:00
tryLogCurrentException(__PRETTY_FUNCTION__);
2013-11-18 17:17:45 +00:00
}
}
};
}