Suppress "Expect:" header for POST and PUT. No longer use CURLOPT_COPYPOSTFIELDS.

For POST and PUT, libcurl adds by default a "Expect: 100-continue"
header and wait for the server to reply with a 100 response.
However, since the server never does that (LL comment in the
code "I'm not sure what it means") it's up to libcurl to continue
anyway after a while and that part is apparently bugged, causing
people not to be able to login sometimes. But suppressing the
header, libcurl doesn't wait for it and we worked around this bug.

The commit introduces a much improved CurlEasyRequest::setPost
method that enforces the above for POST, but that also no longer
uses CURLOPT_COPYPOSTFIELDS (but CURLOPT_POSTFIELDS), no longer
making a copy of the body of what we are going to send to the server.
Instead it uses a new object, derived from AIPostField, to keep track
of this data and to dispose of it once the transaction is complete
(and no sooner).

Copied from llcorehttp, we now also always set a "Connection:
keep-alive" and "Keep-alive: 300" header for POST.
This was already done for texture downloads (HttpOpRequest),
but now we do it always :p. Might need to be changed in the
future, but currently those headers are ignored by the server
anyway.
This commit is contained in:
Aleric Inglewood
2012-08-12 16:34:20 +02:00
parent 2fbe7ab6ce
commit 304fa05094
7 changed files with 91 additions and 53 deletions

View File

@@ -101,7 +101,7 @@ bool Request::post(std::string const& url, headers_t const& headers, std::string
llassert_always(success); // AIFIXME: Maybe throw an error.
if (!success)
return false;
buffered_easy_request_w->setPost(NULL, bytes);
buffered_easy_request_w->setPost(bytes);
buffered_easy_request_w->addHeader("Content-Type: application/octet-stream");
buffered_easy_request_w->finalizeRequest(url);
@@ -129,7 +129,7 @@ bool Request::post(std::string const& url, headers_t const& headers, LLSD const&
LLBufferStream buffer_stream(buffer_w->sChannels, buffer_w->getInput().get());
LLSDSerialize::toXML(data, buffer_stream);
S32 bytes = buffer_w->getInput()->countAfter(buffer_w->sChannels.out(), NULL);
buffered_easy_request_w->setPost(NULL, bytes);
buffered_easy_request_w->setPost(bytes);
buffered_easy_request_w->addHeader("Content-Type: application/llsd+xml");
buffered_easy_request_w->finalizeRequest(url);

View File

@@ -168,8 +168,6 @@ public:
LLCurl::TransferInfo mTransferInfo;
std::string mURI;
char* mRequestText;
int mRequestTextSize;
std::string mProxyAddress;
@@ -200,7 +198,6 @@ LLXMLRPCTransaction::Impl::Impl(const std::string& uri,
: mCurlEasyRequestStateMachinePtr(NULL),
mStatus(LLXMLRPCTransaction::StatusNotStarted),
mURI(uri),
mRequestText(0),
mResponse(0)
{
init(request, useGzip);
@@ -212,7 +209,6 @@ LLXMLRPCTransaction::Impl::Impl(const std::string& uri,
: mCurlEasyRequestStateMachinePtr(NULL),
mStatus(LLXMLRPCTransaction::StatusNotStarted),
mURI(uri),
mRequestText(0),
mResponse(0)
{
XMLRPC_REQUEST request = XMLRPC_RequestNew();
@@ -223,8 +219,13 @@ LLXMLRPCTransaction::Impl::Impl(const std::string& uri,
init(request, useGzip);
}
// Store pointer to data allocated with XMLRPC_REQUEST_ToXML and call XMLRPC_Free to free it upon destruction.
class AIXMLRPCData : public AIPostField
{
public:
AIXMLRPCData(char const* allocated_data) : AIPostField(allocated_data) { }
/*virtual*/ ~AIXMLRPCData() { XMLRPC_Free(const_cast<char*>(mData)); mData = NULL; }
};
void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip)
{
@@ -259,12 +260,11 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip)
curlEasyRequest_w->setoptString(CURLOPT_ENCODING, "");
}
mRequestText = XMLRPC_REQUEST_ToXML(request, &mRequestTextSize);
if (mRequestText)
int requestTextSize;
char* requestText = XMLRPC_REQUEST_ToXML(request, &requestTextSize);
if (requestText)
{
Dout(dc::curl, "Writing " << mRequestTextSize << " bytes: \"" << libcwd::buf2str(mRequestText, mRequestTextSize) << "\".");;
curlEasyRequest_w->setopt(CURLOPT_POSTFIELDSIZE, mRequestTextSize);
curlEasyRequest_w->setoptString(CURLOPT_COPYPOSTFIELDS, mRequestText);
curlEasyRequest_w->setPost(new AIXMLRPCData(requestText), requestTextSize);
}
else
{
@@ -298,11 +298,6 @@ LLXMLRPCTransaction::Impl::~Impl()
{
XMLRPC_RequestFree(mResponse, 1);
}
if (mRequestText)
{
XMLRPC_Free(mRequestText);
}
}
bool LLXMLRPCTransaction::Impl::is_finished(void) const