From f945415210f0e18c2c6d941fda6b7d45cb0f06f1 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Wed, 13 Mar 2013 06:26:25 +0000 Subject: Large changes to the LLCurl::Responder API, as well as pulling in some changes to common libraries from the server codebase: * Additional error checking in http handlers. * Uniform log spam for http errors. * Switch to using constants for http heads and status codes. * Fixed bugs in incorrectly checking if parsing LLSD xml resulted in an error. * Reduced spam regarding LLSD parsing errors in the default completedRaw http handler. It should not longer be necessary to short-circuit completedRaw to avoid spam. * Ported over a few bug fixes from the server code. * Switch mode http status codes to use S32 instead of U32. * Ported LLSD::asStringRef from server code; avoids copying strings all over the place. * Ported server change to LLSD::asBinary; this always returns a reference now instead of copying the entire binary blob. * Ported server pretty notation format (and pretty binary format) to llsd serialization. * The new LLCurl::Responder API no longer has two error handlers to choose from. Overriding the following methods have been deprecated: ** error - use httpFailure ** errorWithContent - use httpFailure ** result - use httpSuccess ** completed - use httpCompleted ** completedHeader - no longer necessary; call getResponseHeaders() from a completion method to obtain these headers. * In order to 'catch' a completed http request, override one of these methods: ** httpSuccess - Called for any 2xx status code. ** httpFailure - Called for any non-2xx status code. ** httpComplete - Called for all status codes. Default implementation is to call either httpSuccess or httpFailure. * It is recommended to keep these methods protected/private in order to avoid triggering of these methods without using a 'push' method (see below). * Uniform error handling should followed whenever possible by calling a variant of this during httpFailure: ** llwarns << dumpResponse() << llendl; * Be sure to include LOG_CLASS(your_class_name) in your class in order for the log entry to give more context. * In order to 'push' a result into the responder, you should no longer call error, errorWithContent, result, or completed. * Nor should you directly call httpSuccess/Failure/Completed (unless passing a message up to a parent class). * Instead, you can set the internal content of a responder and trigger a corresponding method using the following methods: ** successResult - Sets results and calls httpSuccess ** failureResult - Sets results and calls httpFailure ** completedResult - Sets results and calls httpCompleted * To obtain information about a the response from a reponder method, use the following getters: ** getStatus - HTTP status code ** getReason - Reason string ** getContent - Content (Parsed body LLSD) ** getResponseHeaders - Response Headers (LLSD map) ** getHTTPMethod - HTTP method of the request ** getURL - URL of the request * It is still possible to override completeRaw if you want to manipulate data directly out of LLPumpIO. * See indra/llmessage/llcurl.h for more information. --- indra/llmessage/llavatarnamecache.cpp | 53 +++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 24 deletions(-) (limited to 'indra/llmessage/llavatarnamecache.cpp') diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index f9e3ad26f7..87c4b5952c 100644 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -126,7 +126,7 @@ namespace LLAvatarNameCache // Erase expired names from cache void eraseUnrefreshed(); - bool expirationFromCacheControl(LLSD headers, F64 *expires); + bool expirationFromCacheControl(const LLSD& headers, F64 *expires); } /* Sample response: @@ -170,33 +170,31 @@ namespace LLAvatarNameCache class LLAvatarNameResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLAvatarNameResponder); private: // need to store agent ids that are part of this request in case of // an error, so we can flag them as unavailable std::vector mAgentIDs; - // Need the headers to look up Expires: and Retry-After: - LLSD mHeaders; - public: LLAvatarNameResponder(const std::vector& agent_ids) - : mAgentIDs(agent_ids), - mHeaders() + : mAgentIDs(agent_ids) { } - /*virtual*/ void completedHeader(U32 status, const std::string& reason, - const LLSD& headers) - { - mHeaders = headers; - } - - /*virtual*/ void result(const LLSD& content) +protected: + /*virtual*/ void httpSuccess() { + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } // Pull expiration out of headers if available - F64 expires = LLAvatarNameCache::nameExpirationFromHeaders(mHeaders); + F64 expires = LLAvatarNameCache::nameExpirationFromHeaders(getResponseHeaders()); F64 now = LLFrameTimer::getTotalSeconds(); - LLSD agents = content["agents"]; + const LLSD& agents = content["agents"]; LLSD::array_const_iterator it = agents.beginArray(); for ( ; it != agents.endArray(); ++it) { @@ -226,7 +224,7 @@ public: } // Same logic as error response case - LLSD unresolved_agents = content["bad_ids"]; + const LLSD& unresolved_agents = content["bad_ids"]; S32 num_unresolved = unresolved_agents.size(); if (num_unresolved > 0) { @@ -250,14 +248,13 @@ public: << LL_ENDL; } - /*virtual*/ void error(U32 status, const std::string& reason) + /*virtual*/ void httpFailure() { // If there's an error, it might be caused by PeopleApi, // or when loading textures on startup and using a very slow // network, this query may time out. // What we should do depends on whether or not we have a cached name - LL_WARNS("AvNameCache") << "LLAvatarNameResponder::error " << status << " " << reason - << LL_ENDL; + LL_WARNS("AvNameCache") << dumpResponse() << LL_ENDL; // Add dummy records for any agent IDs in this request that we do not have cached already std::vector::const_iterator it = mAgentIDs.begin(); @@ -748,7 +745,7 @@ void LLAvatarNameCache::insert(const LLUUID& agent_id, const LLAvatarName& av_na sCache[agent_id] = av_name; } -F64 LLAvatarNameCache::nameExpirationFromHeaders(LLSD headers) +F64 LLAvatarNameCache::nameExpirationFromHeaders(const LLSD& headers) { F64 expires = 0.0; if (expirationFromCacheControl(headers, &expires)) @@ -764,17 +761,25 @@ F64 LLAvatarNameCache::nameExpirationFromHeaders(LLSD headers) } } -bool LLAvatarNameCache::expirationFromCacheControl(LLSD headers, F64 *expires) +bool LLAvatarNameCache::expirationFromCacheControl(const LLSD& headers, F64 *expires) { bool fromCacheControl = false; F64 now = LLFrameTimer::getTotalSeconds(); // Allow the header to override the default - LLSD cache_control_header = headers["cache-control"]; - if (cache_control_header.isDefined()) + std::string cache_control; + if (headers.has(HTTP_HEADER_CACHE_CONTROL)) + { + cache_control = headers[HTTP_HEADER_CACHE_CONTROL].asString(); + } + else if (headers.has(HTTP_HEADER_LOWER_CACHE_CONTROL)) + { + cache_control = headers[HTTP_HEADER_LOWER_CACHE_CONTROL].asString(); + } + + if (!cache_control.empty()) { S32 max_age = 0; - std::string cache_control = cache_control_header.asString(); if (max_age_from_cache_control(cache_control, &max_age)) { *expires = now + (F64)max_age; -- cgit v1.2.3