xref: /aosp_15_r20/external/federated-compute/fcp/client/http/http_client_util.h (revision 14675a029014e728ec732f129a32e299b2da0601)
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