1 /* 2 * Copyright 2021 Google LLC 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #ifndef FCP_CLIENT_HTTP_HTTP_CLIENT_UTIL_H_ 17 #define FCP_CLIENT_HTTP_HTTP_CLIENT_UTIL_H_ 18 19 #include <optional> 20 #include <string> 21 22 // #include "google/rpc/status.pb.h" 23 #include "absl/status/status.h" 24 #include "absl/status/statusor.h" 25 #include "absl/strings/string_view.h" 26 #include "fcp/client/http/http_client.h" 27 #include "fcp/protos/federatedcompute/common.pb.h" 28 29 namespace fcp::client::http { 30 31 inline static constexpr char kHttpsScheme[] = "https://"; 32 inline static constexpr char kLocalhostUri[] = "http://localhost:"; 33 inline static constexpr char kAcceptEncodingHdr[] = "Accept-Encoding"; 34 inline static constexpr char kContentLengthHdr[] = "Content-Length"; 35 inline static constexpr char kContentEncodingHdr[] = "Content-Encoding"; 36 inline static constexpr char kContentTypeHdr[] = "Content-Type"; 37 inline static constexpr char kExpectHdr[] = "Expect"; 38 inline static constexpr char kTransferEncodingHdr[] = "Transfer-Encoding"; 39 inline static constexpr char kApiKeyHdr[] = "x-goog-api-key"; 40 // The "Transfer-Encoding" header value when the header is present but indicates 41 // that no encoding was actually applied. 42 inline static constexpr char kIdentityEncodingHdrValue[] = "identity"; 43 inline static constexpr char kGzipEncodingHdrValue[] = "gzip"; 44 inline static constexpr char kProtobufContentType[] = "application/x-protobuf"; 45 46 // A non-exhaustive enumeration of common HTTP response codes. 47 // Note this is purposely *not* an "enum class", to allow easy comparisons 48 // against the int codes returned by `HttpResponse`. 49 enum HttpResponseCode { 50 kHttpOk = 200, 51 kHttpMovedPermanently = 301, 52 kHttpBadRequest = 400, 53 kHttpUnauthorized = 401, 54 kHttpForbidden = 403, 55 kHttpNotFound = 404, 56 kHttpConflict = 409, 57 kHttpTooManyRequests = 429, 58 kHttpClientClosedRequest = 499, 59 kHttpInternalServerError = 500, 60 kHttpNotImplemented = 501, 61 kHttpServiceUnavailable = 503, 62 kHttpGatewayTimeout = 504, 63 }; 64 65 // Converts an HTTP response code into an `absl::Status` (incl. an error message 66 // with the original HTTP code). 67 absl::Status ConvertHttpCodeToStatus(int code); 68 69 // Converts a `::google::internal::federatedcompute::v1::Status` into an 70 // `absl::Status`. 71 absl::Status ConvertRpcStatusToAbslStatus( 72 ::google::internal::federatedcompute::v1::Status rpc_status); 73 74 // Converts an `absl::Status` into a `google::rpc::Status`. 75 ::google::internal::federatedcompute::v1::Status ConvertAbslStatusToRpcStatus( 76 absl::Status status); 77 78 // Converts the method enum to a string. 79 std::string ConvertMethodToString(HttpRequest::Method method); 80 81 // Finds the header value for header with name `needle` in a list of headers 82 // (incl. normalizing the header names to lowercase before doing any 83 // comparisons). Note that this returns the first matching header value (rather 84 // than coalescing repeated header values as per RFC2616 section 4.2), so it 85 // must only be used for headers for which only a single value is expected. 86 // Returns an empty optional if no header value was found. 87 std::optional<std::string> FindHeader(const HeaderList& headers, 88 absl::string_view needle); 89 90 // Creates a URI out of a base URI and a suffix. 91 // 92 // The `base_uri` argument is expected to be a valid fully qualified URI on its 93 // own (i.e. having non-empty scheme and authority/host segments, and possibly a 94 // path segment as well), although this function does not validate this. It may 95 // or may not end with a trailing '/'. may or may not 96 // 97 // The `uri_suffix` argument must always either be empty or start with a 98 // leading '/'. 99 // 100 // Returns a URI formed by joining the two arguments, ensuring there is 101 // always a single '/' in between the two parts. E.g. if both `base_uri` ends 102 // with a '/' and `uri_suffix` start with a '/', then the two '/' characters 103 // will be normalized into a single one. If `uri_suffix` is empty, then the 104 // resulting URI will always end in a '/'. 105 absl::StatusOr<std::string> JoinBaseUriWithSuffix(absl::string_view base_uri, 106 absl::string_view uri_suffix); 107 108 // URI-encodes the input, for use a *single path segment* in a URI. This means 109 // that '/' characters *are* escaped. 110 // 111 // See "exactly one path segment" in the "Path template syntax" section in 112 // https://github.com/googleapis/googleapis/blob/master/google/api/http.proto. 113 // 114 // Note that only ASCII strings are accepted (others will return 115 // `INVALID_ARGUMENT`). This is stricter than the http.proto spec requires. 116 absl::StatusOr<std::string> EncodeUriSinglePathSegment(absl::string_view input); 117 118 // URI-encodes the input, for use as *multiple path segments* in a URI. This 119 // means that '/' characters *are not* escaped. 120 // 121 // See "multiple path segments" in the "Path template syntax" section in 122 // https://github.com/googleapis/googleapis/blob/master/google/api/http.proto. 123 // 124 // Note that only ASCII strings are accepted (others will return 125 // `INVALID_ARGUMENT`). This is stricter than the http.proto spec requires. 126 absl::StatusOr<std::string> EncodeUriMultiplePathSegments( 127 absl::string_view input); 128 129 // Create a ByteStream upload URI suffix based on the resource name. 130 // Returns INVALID_ARGUMENT when the resource name cannot be URI-encoded. 131 absl::StatusOr<std::string> CreateByteStreamUploadUriSuffix( 132 absl::string_view resource_name); 133 } // namespace fcp::client::http 134 135 #endif // FCP_CLIENT_HTTP_HTTP_CLIENT_UTIL_H_ 136