12 #include <boost/algorithm/string.hpp> 24 using std::unique_ptr;
27 const string kHeaderStr_ =
"header.";
28 const string kQueryStr_ =
"query.";
29 const string kCookieStr =
"cookie.";
37 std::locale defaultLocale;
143 if (&message ==
this) {
222 VLOG(9) <<
"setMethod: " << method;
229 auto& storedMethod = boost::get<std::string>(req.
method_);
231 storedMethod.begin(), ::toupper);
237 if (req.method_.which() == 2) {
238 return boost::get<HTTPMethod>(req.method_);
248 if (req.method_.which() == 1) {
249 return boost::get<std::string>(req.method_);
250 }
else if (req.method_.which() == 2) {
269 if (value.length() > 0) {
272 max_forwards = folly::to<int64_t>(
value);
273 }
catch (
const std::range_error& ex) {
277 if (max_forwards < 0) {
279 }
else if (max_forwards == 0) {
283 folly::to<string>(max_forwards - 1));
299 struct FormattedDate {
303 string formatDate() {
304 const auto now = std::chrono::system_clock::to_time_t(
310 gmtime_r(&
now, &timeTupple);
312 strftime(buff, 1024,
"%a, %d %b %Y %H:%M:%S %Z", &timeTupple);
324 return obj.formatDate();
360 const string& statusMsg,
386 [&](
const string& headerval) {
389 cookies_.emplace(cookieName, cookieValue);
428 [
this] (
string&& paramName,
string&& paramValue) {
430 auto it = queryParams_.find(paramName);
431 if (it == queryParams_.end()) {
432 queryParams_.emplace(std::move(paramName), std::move(paramValue));
437 it->second = std::move(paramValue);
476 }
catch (
const std::exception& ex) {
488 }
catch (
const std::exception& ex) {
516 VLOG(4) <<
"Error parsing URL during setQueryString: " <<
request().
url_;
548 const std::map<std::string, std::string>&
params,
uint32_t maxLength) {
550 query.reserve(maxLength);
551 for (
auto it = params.begin(); it != params.end(); it++) {
552 if (it != params.begin()) {
555 query.append(it->first +
"=" + it->second);
557 query.shrink_to_fit();
568 fragment.
size() + 5);
569 if (!scheme.
empty()) {
573 if (!query.
empty()) {
576 if (!fragment.
empty()) {
590 while (!sp.empty()) {
591 size_t pairDelimPos = sp.find(pairDelim);
594 if (pairDelimPos == string::npos) {
598 keyValue = sp.subpiece(0, pairDelimPos);
600 sp.advance(pairDelimPos + 1);
603 if (keyValue.empty()) {
607 size_t valueDelimPos = keyValue.find(valueDelim);
608 if (valueDelimPos == string::npos) {
612 auto name = keyValue.subpiece(0, valueDelimPos);
613 auto value = keyValue.subpiece(valueDelimPos + 1);
621 for (; !sp.empty() && sp.front() ==
' '; sp.pop_front()) {
623 for (; !sp.empty() && sp.back() ==
' '; sp.pop_back()) {
632 std::function<
void(
string&&,
string&&)> callback) {
635 while (!sp.
empty()) {
636 size_t pairDelimPos = sp.
find(pairDelim);
639 if (pairDelimPos == string::npos) {
643 keyValue = sp.
subpiece(0, pairDelimPos);
648 if (keyValue.
empty()) {
652 size_t valueDelimPos = keyValue.
find(valueDelim);
653 if (valueDelimPos == string::npos) {
658 boost::trim(name, defaultLocale);
664 boost::trim(name, defaultLocale);
665 boost::trim(value, defaultLocale);
677 VLOG(vlogLevel) << *
this;
683 <<
", Fields for message:" << std::endl;
686 std::vector<std::pair<const char*, const std::string*>> fields {{
696 fields.push_back(make_pair(
"client_ip", &req.
clientIP_));
697 fields.push_back(make_pair(
"client_port", &req.
clientPort_));
699 fields.push_back(make_pair(
"path", &req.
path_));
700 fields.push_back(make_pair(
"query", &req.
query_));
701 fields.push_back(make_pair(
"url", &req.
url_));
706 fields.push_back(make_pair(
"status", &resp.
statusStr_));
707 fields.push_back(make_pair(
"status_msg", &resp.
statusMsg_));
710 for (
auto field : fields) {
711 if (!
field.second->empty()) {
712 os <<
" " <<
field.first
722 os <<
"Per-Hop Headers" << std::endl;
737 LOG_TO_SINK(logSink, INFO) << *
this;
763 const std::string kKeepAliveConnToken =
"keep-alive";
771 kKeepAliveConnToken.c_str(),
784 bool caseSensitive)
const {
791 bool caseSensitive)
const {
794 if (!caseSensitive) {
796 boost::to_lower(lowerToken, defaultLocale);
797 tokenPiece.reset(lowerToken);
808 headerValue.
reset(value);
814 boost::to_lower(lower, defaultLocale);
815 headerValue.reset(lower);
820 size_t end = headerValue.size();
822 idx = headerValue.find(tokenPiece, idx);
823 if (idx == string::npos) {
829 bool at_token_start =
false;
833 at_token_start =
true;
837 char c = headerValue[prev];
839 at_token_start =
true;
847 if (!at_token_start) {
853 bool at_token_end =
false;
854 size_t next = idx + tokenPiece.size();
860 char c = headerValue[
next];
884 case 100:
return "Continue";
885 case 101:
return "Switching Protocols";
886 case 200:
return "OK";
887 case 201:
return "Created";
888 case 202:
return "Accepted";
889 case 203:
return "Non-Authoritative Information";
890 case 204:
return "No Content";
891 case 205:
return "Reset Content";
892 case 206:
return "Partial Content";
893 case 300:
return "Multiple Choices";
894 case 301:
return "Moved Permanently";
895 case 302:
return "Found";
896 case 303:
return "See Other";
897 case 304:
return "Not Modified";
898 case 305:
return "Use Proxy";
899 case 307:
return "Temporary Redirect";
900 case 400:
return "Bad Request";
901 case 401:
return "Unauthorized";
902 case 402:
return "Payment Required";
903 case 403:
return "Forbidden";
904 case 404:
return "Not Found";
905 case 405:
return "Method Not Allowed";
906 case 406:
return "Not Acceptable";
907 case 407:
return "Proxy Authentication Required";
908 case 408:
return "Request Timeout";
909 case 409:
return "Conflict";
910 case 410:
return "Gone";
911 case 411:
return "Length Required";
912 case 412:
return "Precondition Failed";
913 case 413:
return "Request Entity Too Large";
914 case 414:
return "Request-URI Too Long";
915 case 415:
return "Unsupported Media Type";
916 case 416:
return "Requested Range Not Satisfiable";
917 case 417:
return "Expectation Failed";
918 case 418:
return "I'm a teapot";
919 case 500:
return "Internal Server Error";
920 case 501:
return "Not Implemented";
921 case 502:
return "Bad Gateway";
922 case 503:
return "Service Unavailable";
923 case 504:
return "Gateway Timeout";
924 case 505:
return "HTTP Version Not Supported";
std::string authority() const
static void splitNameValuePieces(const std::string &input, char pairDelim, char valueDelim, std::function< void(folly::StringPiece, folly::StringPiece)> callback)
folly::Optional< HTTPMethod > stringToMethod(folly::StringPiece method)
HTTPHeaders strippedPerHopHeaders_
std::unique_ptr< HTTPHeaders > trailers_
std::string stripCntrlChars(const Str &str)
spdy::GoawayStatusCode statusCode
void atomicDumpMessage(int verbosity) const
HTTPMessage & operator=(const HTTPMessage &message)
static const std::pair< uint8_t, uint8_t > kHTTPVersion10
std::ostream & operator<<(std::ostream &os, const HeaderTable &table)
Map field(FieldType Class::*field)
static folly::StringPiece trim(folly::StringPiece sp)
static std::string createQueryString(const std::map< std::string, std::string > ¶ms, uint32_t maxSize)
void uriUnescape(StringPiece str, String &out, UriEscapeMode mode)
void setStatusMessage(T &&msg)
const folly::SocketAddress & getDstAddress() const
uint16_t getStatusCode() const
fbstring exceptionStr(const std::exception &e)
std::chrono::steady_clock::time_point now()
constexpr detail::Map< Move > move
size_type find(const_range_type str) const
void advance(size_type n)
const std::string * protoStr_
bool doHeaderTokenCheck(const HTTPHeaders &headers_, const HTTPHeaderCode headerCode, char const *token, bool caseSensitive) const
constexpr size_type size() const
static std::string formatDateHeader()
boost::variant< boost::blank, std::string, HTTPMethod > method_
requires E e noexcept(noexcept(s.error(std::move(e))))
PUSHMI_INLINE_VAR constexpr detail::transform_fn transform
static void splitNameValue(const std::string &input, char pairDelim, char valueDelim, std::function< void(std::string &&, std::string &&)> callback)
void setPushStatusCode(const uint16_t status)
void constructDirectResponse(const std::pair< uint8_t, uint8_t > &version, const int statusCode, const std::string &statusMsg, int contentLength=0)
void dumpMessageToSink(google::LogSink *logSink) const
bool computeKeepalive() const
void setIsChunked(bool chunked)
const folly::StringPiece getCookie(const std::string &name) const
const std::string & getQueryParam(const std::string &name) const
constexpr bool empty() const
bool checkForHeaderToken(const HTTPHeaderCode headerCode, char const *token, bool caseSensitive) const
constexpr Params params[]
const std::string & methodToString(HTTPMethod method)
WebSocketUpgrade upgradeWebsocket_
folly::Optional< HTTPPriority > h2Pri_
void parseCookies() const
const std::string * getQueryParamPtr(const std::string &name) const
std::pair< uint8_t, uint8_t > version_
std::map< folly::StringPiece, folly::StringPiece > cookies_
auto end(TestAdlIterable &instance)
uint16_t getPushStatusCode() const
folly::StringPiece path() const
static const std::pair< uint8_t, uint8_t > kHTTPVersion11
std::string pushStatusStr_
Range subpiece(size_type first, size_type length=npos) const
void stripPerHopHeaders()
int getIntQueryParam(const std::string &name) const
static const char *const value
static const int8_t kMaxPriority
bool setQueryParam(const std::string &name, const std::string &value)
static std::string createUrl(const folly::StringPiece scheme, const folly::StringPiece authority, const folly::StringPiece path, const folly::StringPiece query, const folly::StringPiece fragment)
void toAppend(char value, Tgt *result)
void setIsUpgraded(bool upgraded)
const std::string & getPushStatusStr() const
bool setQueryString(const std::string &query)
void setMethod(HTTPMethod method)
boost::variant< boost::blank, Request, Response > fields_
std::string getDecodedQueryParam(const std::string &name) const
void describe(std::ostream &os) const
const std::string empty_string
FOLLY_EXPORT static FOLLY_ALWAYS_INLINE T & get()
bool removeQueryParam(const std::string &name)
folly::SocketAddress dstAddress_
bool hasQueryParam(const std::string &name) const
void parseQueryParams() const
std::chrono::time_point< ClockType > getCurrentTime()
const std::string & getMethodString() const
void setHTTPVersion(uint8_t major, uint8_t minor)
std::map< std::string, std::string > queryParams_
static const char * getDefaultReason(uint16_t status)
folly::Optional< HTTPMethod > getMethod() const
Range< const char * > StringPiece
const std::map< std::string, std::string > & getQueryParams() const
static std::mutex mutexDump_
void dumpMessage(int verbosity) const
folly::StringPiece scheme() const
void unparseCookies() const
void reset(Iter start, size_type size)
const std::string & getDstIP() const
const std::pair< uint8_t, uint8_t > & getHTTPVersion() const
void unparseQueryParams()
folly::StringPiece fragment() const
void setStatusCode(uint16_t status)