Mercurial > hg > orthanc
diff OrthancFramework/Sources/HttpServer/HttpContentNegociation.cpp @ 5338:78c59b02b121
accept parameters are now provided to HttpContentNegociation::IHandler::Handle()
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 28 Jun 2023 08:29:43 +0200 |
parents | 0ea402b4d901 |
children | cb11e5ced4e3 |
line wrap: on
line diff
--- a/OrthancFramework/Sources/HttpServer/HttpContentNegociation.cpp Tue Jun 27 17:55:09 2023 +0200 +++ b/OrthancFramework/Sources/HttpServer/HttpContentNegociation.cpp Wed Jun 28 08:29:43 2023 +0200 @@ -49,28 +49,70 @@ { return true; } - - if (subtype == "*" && type == type_) + else if (subtype == "*" && type == type_) { return true; } - - return type == type_ && subtype == subtype_; + else + { + return type == type_ && subtype == subtype_; + } } - struct HttpContentNegociation::Reference : public boost::noncopyable + class HttpContentNegociation::Reference : public boost::noncopyable { + private: const Handler& handler_; uint8_t level_; float quality_; + std::string application_; + Dictionary parameters_; + static float GetQuality(const Dictionary& parameters) + { + Dictionary::const_iterator found = parameters.find("q"); + + if (found != parameters.end()) + { + float quality; + bool ok = false; + + try + { + quality = boost::lexical_cast<float>(found->second); + ok = (quality >= 0.0f && quality <= 1.0f); + } + catch (boost::bad_lexical_cast&) + { + } + + if (ok) + { + return quality; + } + else + { + throw OrthancException( + ErrorCode_BadRequest, + "Quality parameter out of range in a HTTP request (must be between 0 and 1): " + found->second); + } + } + else + { + return 1.0f; // Default quality + } + } + + public: Reference(const Handler& handler, const std::string& type, const std::string& subtype, - float quality) : + const Dictionary& parameters) : handler_(handler), - quality_(quality) + quality_(GetQuality(parameters)), + application_(type + "/" + subtype), + parameters_(parameters) { if (type == "*" && subtype == "*") { @@ -85,6 +127,11 @@ level_ = 2; } } + + void Call() const + { + handler_.Call(parameters_); + } bool operator< (const Reference& other) const { @@ -92,13 +139,14 @@ { return true; } - - if (level_ > other.level_) + else if (level_ > other.level_) { return false; } - - return quality_ < other.quality_; + else + { + return quality_ < other.quality_; + } } }; @@ -123,58 +171,21 @@ } - float HttpContentNegociation::GetQuality(const Tokens& parameters) - { - for (size_t i = 1; i < parameters.size(); i++) - { - std::string key, value; - if (SplitPair(key, value, parameters[i], '=') && - key == "q") - { - float quality; - bool ok = false; - - try - { - quality = boost::lexical_cast<float>(value); - ok = (quality >= 0.0f && quality <= 1.0f); - } - catch (boost::bad_lexical_cast&) - { - } - - if (ok) - { - return quality; - } - else - { - throw OrthancException( - ErrorCode_BadRequest, - "Quality parameter out of range in a HTTP request (must be between 0 and 1): " + value); - } - } - } - - return 1.0f; // Default quality - } - - - void HttpContentNegociation::SelectBestMatch(std::unique_ptr<Reference>& best, + void HttpContentNegociation::SelectBestMatch(std::unique_ptr<Reference>& target, const Handler& handler, const std::string& type, const std::string& subtype, - float quality) + const Dictionary& parameters) { - std::unique_ptr<Reference> match(new Reference(handler, type, subtype, quality)); + std::unique_ptr<Reference> match(new Reference(handler, type, subtype, parameters)); - if (best.get() == NULL || - *best < *match) + if (target.get() == NULL || + *target < *match) { #if __cplusplus < 201103L - best.reset(match.release()); + target.reset(match.release()); #else - best = std::move(match); + target = std::move(match); #endif } } @@ -198,9 +209,9 @@ } - bool HttpContentNegociation::Apply(const HttpHeaders& headers) + bool HttpContentNegociation::Apply(const Dictionary& headers) { - HttpHeaders::const_iterator accept = headers.find("accept"); + Dictionary::const_iterator accept = headers.find("accept"); if (accept != headers.end()) { return Apply(accept->second); @@ -222,26 +233,39 @@ Toolbox::TokenizeString(mediaRanges, accept, ','); std::unique_ptr<Reference> bestMatch; + Dictionary bestParameters; for (Tokens::const_iterator it = mediaRanges.begin(); it != mediaRanges.end(); ++it) { - Tokens parameters; - Toolbox::TokenizeString(parameters, *it, ';'); + Tokens tokens; + Toolbox::TokenizeString(tokens, *it, ';'); - if (parameters.size() > 0) + if (tokens.size() > 0) { - float quality = GetQuality(parameters); + Dictionary parameters; + for (size_t i = 1; i < tokens.size(); i++) + { + std::string key, value; + + if (!SplitPair(key, value, tokens[i], '=')) + { + key = Toolbox::StripSpaces(tokens[i]); + value = ""; + } + parameters[key] = value; + } + std::string type, subtype; - if (SplitPair(type, subtype, parameters[0], '/')) + if (SplitPair(type, subtype, tokens[0], '/')) { for (Handlers::const_iterator it2 = handlers_.begin(); it2 != handlers_.end(); ++it2) { if (it2->IsMatch(type, subtype)) { - SelectBestMatch(bestMatch, *it2, type, subtype, quality); + SelectBestMatch(bestMatch, *it2, type, subtype, parameters); } } } @@ -254,7 +278,7 @@ } else { - bestMatch->handler_.Call(); + bestMatch->Call(); return true; } }