summaryrefslogtreecommitdiff
path: root/indra/llmessage/llhttpclient.cpp
diff options
context:
space:
mode:
authorMerov Linden <merov@lindenlab.com>2014-05-30 15:29:27 -0700
committerMerov Linden <merov@lindenlab.com>2014-05-30 15:29:27 -0700
commitc780f730fed7ed90bf7228fd42e9ea46b8bce1cc (patch)
tree9a617520758cc01fcf0792a8bde24f3fee3e8612 /indra/llmessage/llhttpclient.cpp
parent68b62747edb7073dd3f4975e2b38388ae80d801c (diff)
parent4885c122eaf1b4e304ce598f308d806322efacfc (diff)
DD-92 : pull merge lindenlab/sunshine-external to get AISv3 work
Diffstat (limited to 'indra/llmessage/llhttpclient.cpp')
-rwxr-xr-xindra/llmessage/llhttpclient.cpp190
1 files changed, 105 insertions, 85 deletions
diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp
index 0e6bac35f5..801cf83fae 100755
--- a/indra/llmessage/llhttpclient.cpp
+++ b/indra/llmessage/llhttpclient.cpp
@@ -54,7 +54,7 @@ namespace
{
public:
LLHTTPClientURLAdaptor(LLCurl::ResponderPtr responder)
- : LLURLRequestComplete(), mResponder(responder), mStatus(499),
+ : LLURLRequestComplete(), mResponder(responder), mStatus(HTTP_INTERNAL_ERROR),
mReason("LLURLRequest complete w/no status")
{
}
@@ -63,7 +63,7 @@ namespace
{
}
- virtual void httpStatus(U32 status, const std::string& reason)
+ virtual void httpStatus(S32 status, const std::string& reason)
{
LLURLRequestComplete::httpStatus(status,reason);
@@ -74,30 +74,33 @@ namespace
virtual void complete(const LLChannelDescriptors& channels,
const buffer_ptr_t& buffer)
{
+ // *TODO: Re-interpret mRequestStatus codes?
+ // Would like to detect curl errors, such as
+ // connection errors, write erros, etc.
if (mResponder.get())
{
- // Allow clients to parse headers before we attempt to parse
- // the body and provide completed/result/error calls.
- mResponder->completedHeader(mStatus, mReason, mHeaderOutput);
- mResponder->completedRaw(mStatus, mReason, channels, buffer);
+ mResponder->setResult(mStatus, mReason);
+ mResponder->completedRaw(channels, buffer);
}
}
virtual void header(const std::string& header, const std::string& value)
{
- mHeaderOutput[header] = value;
+ if (mResponder.get())
+ {
+ mResponder->setResponseHeader(header, value);
+ }
}
private:
LLCurl::ResponderPtr mResponder;
- U32 mStatus;
+ S32 mStatus;
std::string mReason;
- LLSD mHeaderOutput;
};
class Injector : public LLIOPipe
{
public:
- virtual const char* contentType() = 0;
+ virtual const std::string& contentType() = 0;
};
class LLSDInjector : public Injector
@@ -106,7 +109,7 @@ namespace
LLSDInjector(const LLSD& sd) : mSD(sd) {}
virtual ~LLSDInjector() {}
- const char* contentType() { return "application/llsd+xml"; }
+ const std::string& contentType() { return HTTP_CONTENT_LLSD_XML; }
virtual EStatus process_impl(const LLChannelDescriptors& channels,
buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump)
@@ -126,7 +129,7 @@ namespace
RawInjector(const U8* data, S32 size) : mData(data), mSize(size) {}
virtual ~RawInjector() {delete mData;}
- const char* contentType() { return "application/octet-stream"; }
+ const std::string& contentType() { return HTTP_CONTENT_OCTET_STREAM; }
virtual EStatus process_impl(const LLChannelDescriptors& channels,
buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump)
@@ -147,7 +150,7 @@ namespace
FileInjector(const std::string& filename) : mFilename(filename) {}
virtual ~FileInjector() {}
- const char* contentType() { return "application/octet-stream"; }
+ const std::string& contentType() { return HTTP_CONTENT_OCTET_STREAM; }
virtual EStatus process_impl(const LLChannelDescriptors& channels,
buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump)
@@ -180,7 +183,7 @@ namespace
VFileInjector(const LLUUID& uuid, LLAssetType::EType asset_type) : mUUID(uuid), mAssetType(asset_type) {}
virtual ~VFileInjector() {}
- const char* contentType() { return "application/octet-stream"; }
+ const std::string& contentType() { return HTTP_CONTENT_OCTET_STREAM; }
virtual EStatus process_impl(const LLChannelDescriptors& channels,
buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump)
@@ -213,7 +216,7 @@ void LLHTTPClient::setCertVerifyCallback(LLURLRequest::SSLCertVerifyCallback cal
static void request(
const std::string& url,
- LLURLRequest::ERequestAction method,
+ EHTTPMethod method,
Injector* body_injector,
LLCurl::ResponderPtr responder,
const F32 timeout = HTTP_REQUEST_EXPIRY_SECS,
@@ -225,7 +228,7 @@ static void request(
{
if (responder)
{
- responder->completed(U32_MAX, "No pump", LLSD());
+ responder->completeResult(HTTP_INTERNAL_ERROR, "No pump");
}
delete body_injector;
return;
@@ -237,90 +240,82 @@ static void request(
{
if (responder)
{
- responder->completed(498, "Internal Error - curl failure", LLSD());
+ responder->completeResult(HTTP_INTERNAL_CURL_ERROR, "Internal Error - curl failure");
}
- delete req ;
+ delete req;
delete body_injector;
- return ;
+ return;
}
req->setSSLVerifyCallback(LLHTTPClient::getCertVerifyCallback(), (void *)req);
-
- LL_DEBUGS() << LLURLRequest::actionAsVerb(method) << " " << url << " "
- << headers << LL_ENDL;
+ LL_DEBUGS("LLHTTPClient") << httpMethodAsVerb(method) << " " << url << " " << headers << LL_ENDL;
// Insert custom headers if the caller sent any
if (headers.isMap())
{
- if (headers.has("Cookie"))
+ if (headers.has(HTTP_OUT_HEADER_COOKIE))
{
req->allowCookies();
}
- LLSD::map_const_iterator iter = headers.beginMap();
- LLSD::map_const_iterator end = headers.endMap();
-
- for (; iter != end; ++iter)
- {
- std::ostringstream header;
- //if the header is "Pragma" with no value
- //the caller intends to force libcurl to drop
- //the Pragma header it so gratuitously inserts
- //Before inserting the header, force libcurl
- //to not use the proxy (read: llurlrequest.cpp)
- static const std::string PRAGMA("Pragma");
- if ((iter->first == PRAGMA) && (iter->second.asString().empty()))
- {
- req->useProxy(false);
- }
- header << iter->first << ": " << iter->second.asString() ;
- LL_DEBUGS() << "header = " << header.str() << LL_ENDL;
- req->addHeader(header.str().c_str());
- }
- }
+ LLSD::map_const_iterator iter = headers.beginMap();
+ LLSD::map_const_iterator end = headers.endMap();
+
+ for (; iter != end; ++iter)
+ {
+ //if the header is "Pragma" with no value
+ //the caller intends to force libcurl to drop
+ //the Pragma header it so gratuitously inserts
+ //Before inserting the header, force libcurl
+ //to not use the proxy (read: llurlrequest.cpp)
+ if ((iter->first == HTTP_OUT_HEADER_PRAGMA) && (iter->second.asString().empty()))
+ {
+ req->useProxy(false);
+ }
+ LL_DEBUGS("LLHTTPClient") << "header = " << iter->first
+ << ": " << iter->second.asString() << LL_ENDL;
+ req->addHeader(iter->first, iter->second.asString());
+ }
+ }
// Check to see if we have already set Accept or not. If no one
// set it, set it to application/llsd+xml since that's what we
// almost always want.
- if( method != LLURLRequest::HTTP_PUT && method != LLURLRequest::HTTP_POST )
+ if( method != HTTP_PUT && method != HTTP_POST )
{
- static const std::string ACCEPT("Accept");
- if(!headers.has(ACCEPT))
+ if(!headers.has(HTTP_OUT_HEADER_ACCEPT))
{
- req->addHeader("Accept: application/llsd+xml");
+ req->addHeader(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_LLSD_XML);
}
}
if (responder)
{
responder->setURL(url);
+ responder->setHTTPMethod(method);
}
req->setCallback(new LLHTTPClientURLAdaptor(responder));
- if (method == LLURLRequest::HTTP_POST && gMessageSystem)
+ if (method == HTTP_POST && gMessageSystem)
{
- req->addHeader(llformat("X-SecondLife-UDP-Listen-Port: %d",
- gMessageSystem->mPort).c_str());
- }
+ req->addHeader("X-SecondLife-UDP-Listen-Port", llformat("%d",
+ gMessageSystem->mPort));
+ }
- if (method == LLURLRequest::HTTP_PUT || method == LLURLRequest::HTTP_POST)
+ if (method == HTTP_PUT || method == HTTP_POST || method == HTTP_PATCH)
{
- static const std::string CONTENT_TYPE("Content-Type");
- if(!headers.has(CONTENT_TYPE))
+ if(!headers.has(HTTP_OUT_HEADER_CONTENT_TYPE))
{
// If the Content-Type header was passed in, it has
// already been added as a header through req->addHeader
// in the loop above. We defer to the caller's wisdom, but
// if they did not specify a Content-Type, then ask the
// injector.
- req->addHeader(
- llformat(
- "Content-Type: %s",
- body_injector->contentType()).c_str());
+ req->addHeader(HTTP_OUT_HEADER_CONTENT_TYPE, body_injector->contentType());
}
- chain.push_back(LLIOPipe::ptr_t(body_injector));
+ chain.push_back(LLIOPipe::ptr_t(body_injector));
}
chain.push_back(LLIOPipe::ptr_t(req));
@@ -342,9 +337,9 @@ void LLHTTPClient::getByteRange(
if(offset > 0 || bytes > 0)
{
std::string range = llformat("bytes=%d-%d", offset, offset+bytes-1);
- headers["Range"] = range;
+ headers[HTTP_OUT_HEADER_RANGE] = range;
}
- request(url,LLURLRequest::HTTP_GET, NULL, responder, timeout, headers, follow_redirects);
+ request(url,HTTP_GET, NULL, responder, timeout, headers, follow_redirects);
}
void LLHTTPClient::head(
@@ -354,18 +349,18 @@ void LLHTTPClient::head(
const F32 timeout,
bool follow_redirects /* = true */)
{
- request(url, LLURLRequest::HTTP_HEAD, NULL, responder, timeout, headers, follow_redirects);
+ request(url, HTTP_HEAD, NULL, responder, timeout, headers, follow_redirects);
}
void LLHTTPClient::get(const std::string& url, ResponderPtr responder, const LLSD& headers, const F32 timeout,
bool follow_redirects /* = true */)
{
- request(url, LLURLRequest::HTTP_GET, NULL, responder, timeout, headers, follow_redirects);
+ request(url, HTTP_GET, NULL, responder, timeout, headers, follow_redirects);
}
void LLHTTPClient::getHeaderOnly(const std::string& url, ResponderPtr responder, const LLSD& headers,
const F32 timeout, bool follow_redirects /* = true */)
{
- request(url, LLURLRequest::HTTP_HEAD, NULL, responder, timeout, headers, follow_redirects);
+ request(url, HTTP_HEAD, NULL, responder, timeout, headers, follow_redirects);
}
void LLHTTPClient::getHeaderOnly(const std::string& url, ResponderPtr responder, const F32 timeout,
bool follow_redirects /* = true */)
@@ -408,7 +403,7 @@ public:
return content;
}
- std::string asString()
+ const std::string& asString()
{
return mBuffer;
}
@@ -437,7 +432,7 @@ private:
*/
static LLSD blocking_request(
const std::string& url,
- LLURLRequest::ERequestAction method,
+ EHTTPMethod method,
const LLSD& body,
const LLSD& headers = LLSD(),
const F32 timeout = 5
@@ -480,11 +475,11 @@ static LLSD blocking_request(
}
// * Setup specific method / "verb" for the URI (currently only GET and POST supported + poppy)
- if (method == LLURLRequest::HTTP_GET)
+ if (method == HTTP_GET)
{
curl_easy_setopt(curlp, CURLOPT_HTTPGET, 1);
}
- else if (method == LLURLRequest::HTTP_POST)
+ else if (method == HTTP_POST)
{
curl_easy_setopt(curlp, CURLOPT_POST, 1);
//serialize to ostr then copy to str - need to because ostr ptr is unstable :(
@@ -493,18 +488,20 @@ static LLSD blocking_request(
body_str = ostr.str();
curl_easy_setopt(curlp, CURLOPT_POSTFIELDS, body_str.c_str());
//copied from PHP libs, correct?
- headers_list = curl_slist_append(headers_list, "Content-Type: application/llsd+xml");
+ headers_list = curl_slist_append(headers_list,
+ llformat("%s: %s", HTTP_OUT_HEADER_CONTENT_TYPE.c_str(), HTTP_CONTENT_LLSD_XML.c_str()).c_str());
// copied from llurlrequest.cpp
// it appears that apache2.2.3 or django in etch is busted. If
// we do not clear the expect header, we get a 500. May be
// limited to django/mod_wsgi.
- headers_list = curl_slist_append(headers_list, "Expect:");
+ headers_list = curl_slist_append(headers_list, llformat("%s:", HTTP_OUT_HEADER_EXPECT.c_str()).c_str());
}
// * Do the action using curl, handle results
LL_DEBUGS() << "HTTP body: " << body_str << LL_ENDL;
- headers_list = curl_slist_append(headers_list, "Accept: application/llsd+xml");
+ headers_list = curl_slist_append(headers_list,
+ llformat("%s: %s", HTTP_OUT_HEADER_ACCEPT.c_str(), HTTP_CONTENT_LLSD_XML.c_str()).c_str());
CURLcode curl_result = curl_easy_setopt(curlp, CURLOPT_HTTPHEADER, headers_list);
if ( curl_result != CURLE_OK )
{
@@ -513,11 +510,11 @@ static LLSD blocking_request(
LLSD response = LLSD::emptyMap();
S32 curl_success = curl_easy_perform(curlp);
- S32 http_status = 499;
+ S32 http_status = HTTP_INTERNAL_ERROR;
curl_easy_getinfo(curlp, CURLINFO_RESPONSE_CODE, &http_status);
response["status"] = http_status;
// if we get a non-404 and it's not a 200 OR maybe it is but you have error bits,
- if ( http_status != 404 && (http_status != 200 || curl_success != 0) )
+ if ( http_status != HTTP_NOT_FOUND && (http_status != HTTP_OK || curl_success != 0) )
{
// We expect 404s, don't spam for them.
LL_WARNS() << "CURL REQ URL: " << url << LL_ENDL;
@@ -547,12 +544,12 @@ static LLSD blocking_request(
LLSD LLHTTPClient::blockingGet(const std::string& url)
{
- return blocking_request(url, LLURLRequest::HTTP_GET, LLSD());
+ return blocking_request(url, HTTP_GET, LLSD());
}
LLSD LLHTTPClient::blockingPost(const std::string& url, const LLSD& body)
{
- return blocking_request(url, LLURLRequest::HTTP_POST, body);
+ return blocking_request(url, HTTP_POST, body);
}
void LLHTTPClient::put(
@@ -562,7 +559,17 @@ void LLHTTPClient::put(
const LLSD& headers,
const F32 timeout)
{
- request(url, LLURLRequest::HTTP_PUT, new LLSDInjector(body), responder, timeout, headers);
+ request(url, HTTP_PUT, new LLSDInjector(body), responder, timeout, headers);
+}
+
+void LLHTTPClient::patch(
+ const std::string& url,
+ const LLSD& body,
+ ResponderPtr responder,
+ const LLSD& headers,
+ const F32 timeout)
+{
+ request(url, HTTP_PATCH, new LLSDInjector(body), responder, timeout, headers);
}
void LLHTTPClient::putRaw(
@@ -573,7 +580,7 @@ void LLHTTPClient::putRaw(
const LLSD& headers,
const F32 timeout)
{
- request(url, LLURLRequest::HTTP_PUT, new RawInjector(data, size), responder, timeout, headers);
+ request(url, HTTP_PUT, new RawInjector(data, size), responder, timeout, headers);
}
void LLHTTPClient::post(
@@ -583,7 +590,7 @@ void LLHTTPClient::post(
const LLSD& headers,
const F32 timeout)
{
- request(url, LLURLRequest::HTTP_POST, new LLSDInjector(body), responder, timeout, headers);
+ request(url, HTTP_POST, new LLSDInjector(body), responder, timeout, headers);
}
void LLHTTPClient::postRaw(
@@ -594,7 +601,7 @@ void LLHTTPClient::postRaw(
const LLSD& headers,
const F32 timeout)
{
- request(url, LLURLRequest::HTTP_POST, new RawInjector(data, size), responder, timeout, headers);
+ request(url, HTTP_POST, new RawInjector(data, size), responder, timeout, headers);
}
void LLHTTPClient::postFile(
@@ -604,7 +611,7 @@ void LLHTTPClient::postFile(
const LLSD& headers,
const F32 timeout)
{
- request(url, LLURLRequest::HTTP_POST, new FileInjector(filename), responder, timeout, headers);
+ request(url, HTTP_POST, new FileInjector(filename), responder, timeout, headers);
}
void LLHTTPClient::postFile(
@@ -615,7 +622,7 @@ void LLHTTPClient::postFile(
const LLSD& headers,
const F32 timeout)
{
- request(url, LLURLRequest::HTTP_POST, new VFileInjector(uuid, asset_type), responder, timeout, headers);
+ request(url, HTTP_POST, new VFileInjector(uuid, asset_type), responder, timeout, headers);
}
// static
@@ -625,7 +632,7 @@ void LLHTTPClient::del(
const LLSD& headers,
const F32 timeout)
{
- request(url, LLURLRequest::HTTP_DELETE, NULL, responder, timeout, headers);
+ request(url, HTTP_DELETE, NULL, responder, timeout, headers);
}
// static
@@ -637,8 +644,21 @@ void LLHTTPClient::move(
const F32 timeout)
{
LLSD headers = hdrs;
- headers["Destination"] = destination;
- request(url, LLURLRequest::HTTP_MOVE, NULL, responder, timeout, headers);
+ headers[HTTP_OUT_HEADER_DESTINATION] = destination;
+ request(url, HTTP_MOVE, NULL, responder, timeout, headers);
+}
+
+// static
+void LLHTTPClient::copy(
+ const std::string& url,
+ const std::string& destination,
+ ResponderPtr responder,
+ const LLSD& hdrs,
+ const F32 timeout)
+{
+ LLSD headers = hdrs;
+ headers[HTTP_OUT_HEADER_DESTINATION] = destination;
+ request(url, HTTP_COPY, NULL, responder, timeout, headers);
}