added better support for 'Expect: 100-continue' header and '100 Continue' responses

This commit is contained in:
Guenter Obiltschnig
2015-10-06 11:11:16 +02:00
parent 6bb1f4ad62
commit c66849f9ee
11 changed files with 175 additions and 41 deletions

View File

@@ -46,7 +46,8 @@ HTTPClientSession::HTTPClientSession():
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
_reconnect(false),
_mustReconnect(false),
_expectResponseBody(false)
_expectResponseBody(false),
_responseReceived(false)
{
}
@@ -58,7 +59,8 @@ HTTPClientSession::HTTPClientSession(const StreamSocket& socket):
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
_reconnect(false),
_mustReconnect(false),
_expectResponseBody(false)
_expectResponseBody(false),
_responseReceived(false)
{
}
@@ -70,7 +72,8 @@ HTTPClientSession::HTTPClientSession(const SocketAddress& address):
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
_reconnect(false),
_mustReconnect(false),
_expectResponseBody(false)
_expectResponseBody(false),
_responseReceived(false)
{
}
@@ -82,7 +85,8 @@ HTTPClientSession::HTTPClientSession(const std::string& host, Poco::UInt16 port)
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
_reconnect(false),
_mustReconnect(false),
_expectResponseBody(false)
_expectResponseBody(false),
_responseReceived(false)
{
}
@@ -94,7 +98,8 @@ HTTPClientSession::HTTPClientSession(const std::string& host, Poco::UInt16 port,
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
_reconnect(false),
_mustReconnect(false),
_expectResponseBody(false)
_expectResponseBody(false),
_responseReceived(false)
{
}
@@ -192,6 +197,7 @@ std::ostream& HTTPClientSession::sendRequest(HTTPRequest& request)
{
clearException();
_pResponseStream = 0;
_responseReceived = false;
bool keepAlive = getKeepAlive();
if (((connected() && !keepAlive) || mustReconnect()) && !_host.empty())
@@ -259,25 +265,28 @@ std::istream& HTTPClientSession::receiveResponse(HTTPResponse& response)
_pRequestStream = 0;
if (networkException()) networkException()->rethrow();
do
if (!_responseReceived)
{
response.clear();
HTTPHeaderInputStream his(*this);
try
do
{
response.read(his);
}
catch (Exception&)
{
close();
if (networkException())
networkException()->rethrow();
else
response.clear();
HTTPHeaderInputStream his(*this);
try
{
response.read(his);
}
catch (Exception&)
{
close();
if (networkException())
networkException()->rethrow();
else
throw;
throw;
throw;
}
}
while (response.getStatus() == HTTPResponse::HTTP_CONTINUE);
}
while (response.getStatus() == HTTPResponse::HTTP_CONTINUE);
_mustReconnect = getKeepAlive() && !response.getKeepAlive();
@@ -298,6 +307,34 @@ std::istream& HTTPClientSession::receiveResponse(HTTPResponse& response)
}
bool HTTPClientSession::canContinue(HTTPResponse& response)
{
poco_assert (!_responseReceived);
_pRequestStream->flush();
if (networkException()) networkException()->rethrow();
response.clear();
HTTPHeaderInputStream his(*this);
try
{
response.read(his);
}
catch (Exception&)
{
close();
if (networkException())
networkException()->rethrow();
else
throw;
throw;
}
_responseReceived = response.getStatus() != HTTPResponse::HTTP_CONTINUE;
return !_responseReceived;
}
void HTTPClientSession::reset()
{
close();

View File

@@ -43,6 +43,7 @@ const std::string HTTPRequest::COOKIE = "Cookie";
const std::string HTTPRequest::AUTHORIZATION = "Authorization";
const std::string HTTPRequest::PROXY_AUTHORIZATION = "Proxy-Authorization";
const std::string HTTPRequest::UPGRADE = "Upgrade";
const std::string HTTPRequest::EXPECT = "Expect";
HTTPRequest::HTTPRequest():
@@ -259,4 +260,20 @@ void HTTPRequest::setCredentials(const std::string& header, const std::string& s
}
bool HTTPRequest::getExpectContinue() const
{
const std::string& expect = get(EXPECT, EMPTY);
return !expect.empty() && icompare(expect, "100-continue") == 0;
}
void HTTPRequest::setExpectContinue(bool expectContinue)
{
if (expectContinue)
set(EXPECT, "100-continue");
else
erase(EXPECT);
}
} } // namespace Poco::Net

View File

@@ -81,7 +81,7 @@ void HTTPServerConnection::run()
std::auto_ptr<HTTPRequestHandler> pHandler(_pFactory->createRequestHandler(request));
if (pHandler.get())
{
if (request.expectContinue())
if (request.getExpectContinue() && response.getStatus() == HTTPResponse::HTTP_OK)
response.sendContinue();
pHandler->handleRequest(request, response);

View File

@@ -33,9 +33,6 @@ namespace Poco {
namespace Net {
const std::string HTTPServerRequestImpl::EXPECT("Expect");
HTTPServerRequestImpl::HTTPServerRequestImpl(HTTPServerResponseImpl& response, HTTPServerSession& session, HTTPServerParams* pParams):
_response(response),
_session(session),
@@ -90,11 +87,4 @@ StreamSocket HTTPServerRequestImpl::detachSocket()
}
bool HTTPServerRequestImpl::expectContinue() const
{
const std::string& expect = get(EXPECT, EMPTY);
return !expect.empty() && icompare(expect, "100-continue") == 0;
}
} } // namespace Poco::Net