|
| 1 | +#pragma once |
| 2 | +/* |
| 3 | + * Copyright 2018-present Amazon.com, Inc. or its affiliates. All Rights Reserved. |
| 4 | + * |
| 5 | + * Licensed under the Apache License, Version 2.0 (the "License"). |
| 6 | + * You may not use this file except in compliance with the License. |
| 7 | + * A copy of the License is located at |
| 8 | + * |
| 9 | + * http://aws.amazon.com/apache2.0 |
| 10 | + * |
| 11 | + * or in the "license" file accompanying this file. This file is distributed |
| 12 | + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either |
| 13 | + * express or implied. See the License for the specific language governing |
| 14 | + * permissions and limitations under the License. |
| 15 | + */ |
| 16 | + |
| 17 | +#include <string> |
| 18 | +#include <vector> |
| 19 | +#include <algorithm> |
| 20 | +#include <cctype> // tolower |
| 21 | +#include <cassert> |
| 22 | + |
| 23 | +namespace aws { |
| 24 | +namespace http { |
| 25 | +enum class response_code; |
| 26 | +class response { |
| 27 | +public: |
| 28 | + /** |
| 29 | + * lower-case the name but store the value as is |
| 30 | + */ |
| 31 | + inline void add_header(std::string name, std::string const& value); |
| 32 | + inline void append_body(const char* p, size_t sz); |
| 33 | + inline bool has_header(char const* header) const; |
| 34 | + inline std::string const& get_header(char const* header) const; |
| 35 | + inline response_code get_response_code() const { return m_response_code; } |
| 36 | + inline void set_response_code(aws::http::response_code c); |
| 37 | + inline void set_content_type(char const* ct); |
| 38 | + inline std::string const& get_body() const; |
| 39 | + inline std::string const& get_content_type() const; |
| 40 | + |
| 41 | +private: |
| 42 | + response_code m_response_code; |
| 43 | + using key_value_collection = std::vector<std::pair<std::string, std::string>>; |
| 44 | + key_value_collection m_headers; |
| 45 | + std::string m_body; |
| 46 | + std::string m_content_type; |
| 47 | +}; |
| 48 | + |
| 49 | +enum class response_code { |
| 50 | + REQUEST_NOT_MADE = -1, |
| 51 | + CONTINUE = 100, |
| 52 | + SWITCHING_PROTOCOLS = 101, |
| 53 | + PROCESSING = 102, |
| 54 | + OK = 200, |
| 55 | + CREATED = 201, |
| 56 | + ACCEPTED = 202, |
| 57 | + NON_AUTHORITATIVE_INFORMATION = 203, |
| 58 | + NO_CONTENT = 204, |
| 59 | + RESET_CONTENT = 205, |
| 60 | + PARTIAL_CONTENT = 206, |
| 61 | + MULTI_STATUS = 207, |
| 62 | + ALREADY_REPORTED = 208, |
| 63 | + IM_USED = 226, |
| 64 | + MULTIPLE_CHOICES = 300, |
| 65 | + MOVED_PERMANENTLY = 301, |
| 66 | + FOUND = 302, |
| 67 | + SEE_OTHER = 303, |
| 68 | + NOT_MODIFIED = 304, |
| 69 | + USE_PROXY = 305, |
| 70 | + SWITCH_PROXY = 306, |
| 71 | + TEMPORARY_REDIRECT = 307, |
| 72 | + PERMANENT_REDIRECT = 308, |
| 73 | + BAD_REQUEST = 400, |
| 74 | + UNAUTHORIZED = 401, |
| 75 | + PAYMENT_REQUIRED = 402, |
| 76 | + FORBIDDEN = 403, |
| 77 | + NOT_FOUND = 404, |
| 78 | + METHOD_NOT_ALLOWED = 405, |
| 79 | + NOT_ACCEPTABLE = 406, |
| 80 | + PROXY_AUTHENTICATION_REQUIRED = 407, |
| 81 | + REQUEST_TIMEOUT = 408, |
| 82 | + CONFLICT = 409, |
| 83 | + GONE = 410, |
| 84 | + LENGTH_REQUIRED = 411, |
| 85 | + PRECONDITION_FAILED = 412, |
| 86 | + REQUEST_ENTITY_TOO_LARGE = 413, |
| 87 | + REQUEST_URI_TOO_LONG = 414, |
| 88 | + UNSUPPORTED_MEDIA_TYPE = 415, |
| 89 | + REQUESTED_RANGE_NOT_SATISFIABLE = 416, |
| 90 | + EXPECTATION_FAILED = 417, |
| 91 | + IM_A_TEAPOT = 418, |
| 92 | + AUTHENTICATION_TIMEOUT = 419, |
| 93 | + METHOD_FAILURE = 420, |
| 94 | + UNPROC_ENTITY = 422, |
| 95 | + LOCKED = 423, |
| 96 | + FAILED_DEPENDENCY = 424, |
| 97 | + UPGRADE_REQUIRED = 426, |
| 98 | + PRECONDITION_REQUIRED = 427, |
| 99 | + TOO_MANY_REQUESTS = 429, |
| 100 | + REQUEST_HEADER_FIELDS_TOO_LARGE = 431, |
| 101 | + LOGIN_TIMEOUT = 440, |
| 102 | + NO_RESPONSE = 444, |
| 103 | + RETRY_WITH = 449, |
| 104 | + BLOCKED = 450, |
| 105 | + REDIRECT = 451, |
| 106 | + REQUEST_HEADER_TOO_LARGE = 494, |
| 107 | + CERT_ERROR = 495, |
| 108 | + NO_CERT = 496, |
| 109 | + HTTP_TO_HTTPS = 497, |
| 110 | + CLIENT_CLOSED_TO_REQUEST = 499, |
| 111 | + INTERNAL_SERVER_ERROR = 500, |
| 112 | + NOT_IMPLEMENTED = 501, |
| 113 | + BAD_GATEWAY = 502, |
| 114 | + SERVICE_UNAVAILABLE = 503, |
| 115 | + GATEWAY_TIMEOUT = 504, |
| 116 | + HTTP_VERSION_NOT_SUPPORTED = 505, |
| 117 | + VARIANT_ALSO_NEGOTIATES = 506, |
| 118 | + INSUFFICIENT_STORAGE = 506, |
| 119 | + LOOP_DETECTED = 508, |
| 120 | + BANDWIDTH_LIMIT_EXCEEDED = 509, |
| 121 | + NOT_EXTENDED = 510, |
| 122 | + NETWORK_AUTHENTICATION_REQUIRED = 511, |
| 123 | + NETWORK_READ_TIMEOUT = 598, |
| 124 | + NETWORK_CONNECT_TIMEOUT = 599 |
| 125 | +}; |
| 126 | + |
| 127 | +inline void response::set_response_code(http::response_code c) |
| 128 | +{ |
| 129 | + m_response_code = c; |
| 130 | +} |
| 131 | + |
| 132 | +inline void response::set_content_type(char const* ct) |
| 133 | +{ |
| 134 | + m_content_type = ct; |
| 135 | +} |
| 136 | + |
| 137 | +inline std::string const& response::get_body() const |
| 138 | +{ |
| 139 | + return m_body; |
| 140 | +} |
| 141 | + |
| 142 | +inline std::string const& response::get_content_type() const |
| 143 | +{ |
| 144 | + return m_content_type; |
| 145 | +} |
| 146 | + |
| 147 | +inline void response::add_header(std::string name, std::string const& value) |
| 148 | +{ |
| 149 | + std::transform(name.begin(), name.end(), name.begin(), ::tolower); |
| 150 | + m_headers.emplace_back(name, value); |
| 151 | +} |
| 152 | + |
| 153 | +inline void response::append_body(const char* p, size_t sz) |
| 154 | +{ |
| 155 | + // simple and generates significantly less code than std::stringstream |
| 156 | + constexpr size_t min_capacity = 512; |
| 157 | + if (m_body.capacity() < min_capacity) { |
| 158 | + m_body.reserve(min_capacity); |
| 159 | + } |
| 160 | + |
| 161 | + m_body.append(p, sz); |
| 162 | +} |
| 163 | + |
| 164 | +inline bool response::has_header(char const* header) const |
| 165 | +{ |
| 166 | + return std::any_of(m_headers.begin(), m_headers.end(), [header](std::pair<std::string, std::string> const& p) { |
| 167 | + return p.first == header; |
| 168 | + }); |
| 169 | +} |
| 170 | + |
| 171 | +inline std::string const& response::get_header(char const* header) const |
| 172 | +{ |
| 173 | + auto it = std::find_if(m_headers.begin(), m_headers.end(), [header](std::pair<std::string, std::string> const& p) { |
| 174 | + return p.first == header; |
| 175 | + }); |
| 176 | + assert(it != m_headers.end()); |
| 177 | + return it->second; |
| 178 | +} |
| 179 | + |
| 180 | +} // namespace http |
| 181 | +} // namespace aws |
0 commit comments