1*14675a02SAndroid Build Coastguard Worker /* 2*14675a02SAndroid Build Coastguard Worker * Copyright 2021 Google LLC 3*14675a02SAndroid Build Coastguard Worker * 4*14675a02SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*14675a02SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*14675a02SAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*14675a02SAndroid Build Coastguard Worker * 8*14675a02SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*14675a02SAndroid Build Coastguard Worker * 10*14675a02SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*14675a02SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*14675a02SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*14675a02SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*14675a02SAndroid Build Coastguard Worker * limitations under the License. 15*14675a02SAndroid Build Coastguard Worker */ 16*14675a02SAndroid Build Coastguard Worker #ifndef FCP_CLIENT_HTTP_HTTP_CLIENT_H_ 17*14675a02SAndroid Build Coastguard Worker #define FCP_CLIENT_HTTP_HTTP_CLIENT_H_ 18*14675a02SAndroid Build Coastguard Worker 19*14675a02SAndroid Build Coastguard Worker #include <cstdint> 20*14675a02SAndroid Build Coastguard Worker #include <memory> 21*14675a02SAndroid Build Coastguard Worker #include <optional> 22*14675a02SAndroid Build Coastguard Worker #include <string> 23*14675a02SAndroid Build Coastguard Worker #include <utility> 24*14675a02SAndroid Build Coastguard Worker #include <vector> 25*14675a02SAndroid Build Coastguard Worker 26*14675a02SAndroid Build Coastguard Worker #include "absl/base/attributes.h" 27*14675a02SAndroid Build Coastguard Worker #include "absl/container/flat_hash_map.h" 28*14675a02SAndroid Build Coastguard Worker #include "absl/status/status.h" 29*14675a02SAndroid Build Coastguard Worker #include "absl/status/statusor.h" 30*14675a02SAndroid Build Coastguard Worker #include "absl/strings/string_view.h" 31*14675a02SAndroid Build Coastguard Worker 32*14675a02SAndroid Build Coastguard Worker namespace fcp { 33*14675a02SAndroid Build Coastguard Worker namespace client { 34*14675a02SAndroid Build Coastguard Worker namespace http { 35*14675a02SAndroid Build Coastguard Worker 36*14675a02SAndroid Build Coastguard Worker using Header = std::pair<std::string, std::string>; 37*14675a02SAndroid Build Coastguard Worker // This is a vector of pairs and not a map since multiple request headers with 38*14675a02SAndroid Build Coastguard Worker // the same name are allowed (see RFC2616 section 4.2). 39*14675a02SAndroid Build Coastguard Worker using HeaderList = std::vector<Header>; 40*14675a02SAndroid Build Coastguard Worker 41*14675a02SAndroid Build Coastguard Worker class HttpRequest; // forward declaration 42*14675a02SAndroid Build Coastguard Worker class HttpRequestCallback; // forward declaration 43*14675a02SAndroid Build Coastguard Worker class HttpRequestHandle; // forward declaration 44*14675a02SAndroid Build Coastguard Worker class HttpResponse; // forward declaration 45*14675a02SAndroid Build Coastguard Worker 46*14675a02SAndroid Build Coastguard Worker // An interface that allows the callers to make HTTP requests and receive their 47*14675a02SAndroid Build Coastguard Worker // responses. 48*14675a02SAndroid Build Coastguard Worker // 49*14675a02SAndroid Build Coastguard Worker // Platforms will be required to pass an instance of this class to 50*14675a02SAndroid Build Coastguard Worker // `RunFederatedComputation(...)`, and such instances must remain alive for at 51*14675a02SAndroid Build Coastguard Worker // least the duration of those calls. 52*14675a02SAndroid Build Coastguard Worker // 53*14675a02SAndroid Build Coastguard Worker // Instances of this class must support being called from any thread. In such 54*14675a02SAndroid Build Coastguard Worker // cases implementations should ideally handle multiple requests in parallel, at 55*14675a02SAndroid Build Coastguard Worker // least up to an implementation-defined max number of parallel requests (i.e. 56*14675a02SAndroid Build Coastguard Worker // ideally two `PerformRequests` calls on different threads can be handled in 57*14675a02SAndroid Build Coastguard Worker // parallel, rather than having the 2nd call block until the 1st call is 58*14675a02SAndroid Build Coastguard Worker // completed). 59*14675a02SAndroid Build Coastguard Worker // 60*14675a02SAndroid Build Coastguard Worker // Besides the requirements documented further below, the following high-level 61*14675a02SAndroid Build Coastguard Worker // behavior is required of any `HttpClient` implementation: 62*14675a02SAndroid Build Coastguard Worker // - Underlying protocols: 63*14675a02SAndroid Build Coastguard Worker // * Implementations must support at least HTTP/1.1 over TLS 1.2. 64*14675a02SAndroid Build Coastguard Worker // * Implementations are also allowed to serve requests using HTTP/2, QUIC or 65*14675a02SAndroid Build Coastguard Worker // other newer protocols. 66*14675a02SAndroid Build Coastguard Worker // * Implementations must support both IPv4 and IPv6 (but they are allowed to 67*14675a02SAndroid Build Coastguard Worker // fall back to IPv4). 68*14675a02SAndroid Build Coastguard Worker // - Certificate validation: 69*14675a02SAndroid Build Coastguard Worker // * Implementations are responsible for TLS certificate validation and for 70*14675a02SAndroid Build Coastguard Worker // maintaining an up-to-date set of root certificates as well as an 71*14675a02SAndroid Build Coastguard Worker // up-to-date HTTP/TLS implementation. 72*14675a02SAndroid Build Coastguard Worker // * Implementations should not include user-added CAs, and should consider 73*14675a02SAndroid Build Coastguard Worker // restricting the set of CAs further to only those needed for connecting to 74*14675a02SAndroid Build Coastguard Worker // the expected endpoints. 75*14675a02SAndroid Build Coastguard Worker // - Cookies: 76*14675a02SAndroid Build Coastguard Worker // * Implementations must not supply any cookies in requests (beyond those 77*14675a02SAndroid Build Coastguard Worker // that may be specified in the `HttpRequest::headers()` method). 78*14675a02SAndroid Build Coastguard Worker // * Implementations must not store any cookies returned by the server. 79*14675a02SAndroid Build Coastguard Worker // * Instead, they must return any server-specified "Set-Cookie" response 80*14675a02SAndroid Build Coastguard Worker // header via `HttpResponse::headers()`. 81*14675a02SAndroid Build Coastguard Worker // - Redirects: 82*14675a02SAndroid Build Coastguard Worker // * Implementations must follow HTTP redirects responses, up to an 83*14675a02SAndroid Build Coastguard Worker // implementation-defined maximum. 84*14675a02SAndroid Build Coastguard Worker // * In such cases the response headers & body returned via the interfaces 85*14675a02SAndroid Build Coastguard Worker // below should be those of the final response. 86*14675a02SAndroid Build Coastguard Worker // * See `HttpRequestCallback` docs below for more details. 87*14675a02SAndroid Build Coastguard Worker // - Caching: 88*14675a02SAndroid Build Coastguard Worker // * Implementations should not implement a cache as it is expected that 89*14675a02SAndroid Build Coastguard Worker // naive HTTP-level caching will not be effective (and since a cache may 90*14675a02SAndroid Build Coastguard Worker // ultimately be implemented over this interface, in the Federated Compute 91*14675a02SAndroid Build Coastguard Worker // library itself). 92*14675a02SAndroid Build Coastguard Worker // * If implementations do implement one, however, they are expected to abide 93*14675a02SAndroid Build Coastguard Worker // by the standard HTTP caching rules (see the `HttpRequest::Method` docs 94*14675a02SAndroid Build Coastguard Worker // for more details). 95*14675a02SAndroid Build Coastguard Worker // - Response body decompression & decoding: 96*14675a02SAndroid Build Coastguard Worker // * If no "Accept-Encoding" request header is explicitly specified in 97*14675a02SAndroid Build Coastguard Worker // `HttpRequest::headers()`, then implementations must advertise an 98*14675a02SAndroid Build Coastguard Worker // "Accept-Encoding" request header themselves whose value includes at 99*14675a02SAndroid Build Coastguard Worker // least "gzip" (additional encodings are allowed to be specified in 100*14675a02SAndroid Build Coastguard Worker // addition to "gzip"), and must transparently decompress any compressed 101*14675a02SAndroid Build Coastguard Worker // server responses before returning the data via these interfaces. 102*14675a02SAndroid Build Coastguard Worker // Implementations are also allowed to advertise/support additional 103*14675a02SAndroid Build Coastguard Worker // encoding methods. 104*14675a02SAndroid Build Coastguard Worker // * In such cases where no "Accept-Encoding" header is specified, 105*14675a02SAndroid Build Coastguard Worker // implementations must remove the "Content-Encoding" and 106*14675a02SAndroid Build Coastguard Worker // "Content-Length" headers from headers returned via 107*14675a02SAndroid Build Coastguard Worker // `HttpResponse::headers()` (since those wouldn't reflect the payload 108*14675a02SAndroid Build Coastguard Worker // delivered via this interface). 109*14675a02SAndroid Build Coastguard Worker // * However, if an "Accept-Encoding" request header *is* explicitly 110*14675a02SAndroid Build Coastguard Worker // specified, then implementations must use that header verbatim and they 111*14675a02SAndroid Build Coastguard Worker // must not decompress the response (even if they natively support the 112*14675a02SAndroid Build Coastguard Worker // compression method), and they must leave the "Content-Encoding" and 113*14675a02SAndroid Build Coastguard Worker // "Content-Length" headers intact. 114*14675a02SAndroid Build Coastguard Worker // * This ensures that the caller of this interface can take full control of 115*14675a02SAndroid Build Coastguard Worker // the decompression and/or choose to store decompressed payloads on disk 116*14675a02SAndroid Build Coastguard Worker // if it so chooses. 117*14675a02SAndroid Build Coastguard Worker // * Implementations must transparently decode server responses served with 118*14675a02SAndroid Build Coastguard Worker // "Transfer-Encoding: chunked". In such cases they must remove the 119*14675a02SAndroid Build Coastguard Worker // "Transfer-Encoding" response header. 120*14675a02SAndroid Build Coastguard Worker // - Request body compression & encoding: 121*14675a02SAndroid Build Coastguard Worker // * If implementations receive a "Content-Encoding" request header, this 122*14675a02SAndroid Build Coastguard Worker // means that the request body stream they receive has already been 123*14675a02SAndroid Build Coastguard Worker // compressed. The implementation must leave the header and request body 124*14675a02SAndroid Build Coastguard Worker // intact in such cases (i.e. not re-compress it). 125*14675a02SAndroid Build Coastguard Worker // * If implementations receive a "Content-Length" request header, they must 126*14675a02SAndroid Build Coastguard Worker // use it verbatim and they should then assume that the request body will 127*14675a02SAndroid Build Coastguard Worker // be of exactly that size. 128*14675a02SAndroid Build Coastguard Worker // * If they do not receive such a header then they must use the 129*14675a02SAndroid Build Coastguard Worker // "Transfer-encoding: chunked" mechanism to transmit the request body 130*14675a02SAndroid Build Coastguard Worker // (i.e. they shouldn't specify a "Content-Length" header and they should 131*14675a02SAndroid Build Coastguard Worker // transmit the body in chunks), or use an equivalent method of streaming 132*14675a02SAndroid Build Coastguard Worker // the data (such as HTTP/2's data streaming). 133*14675a02SAndroid Build Coastguard Worker class HttpClient { 134*14675a02SAndroid Build Coastguard Worker public: 135*14675a02SAndroid Build Coastguard Worker virtual ~HttpClient() = default; 136*14675a02SAndroid Build Coastguard Worker 137*14675a02SAndroid Build Coastguard Worker // Enqueues an HTTP request, without starting it yet. To start the request the 138*14675a02SAndroid Build Coastguard Worker // `HttpRequestHandle` must be passed to `PerformRequests`. Each 139*14675a02SAndroid Build Coastguard Worker // `HttpRequestHandle` must be passed to at most one `PerformRequests` call. 140*14675a02SAndroid Build Coastguard Worker // 141*14675a02SAndroid Build Coastguard Worker // The `HttpClient` implementation assumes ownership of the `HttpRequest` 142*14675a02SAndroid Build Coastguard Worker // object, and the implementation must delete the object when the 143*14675a02SAndroid Build Coastguard Worker // `HttpRequestHandle` is deleted. 144*14675a02SAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT 145*14675a02SAndroid Build Coastguard Worker virtual std::unique_ptr<HttpRequestHandle> EnqueueRequest( 146*14675a02SAndroid Build Coastguard Worker std::unique_ptr<HttpRequest> request) = 0; 147*14675a02SAndroid Build Coastguard Worker 148*14675a02SAndroid Build Coastguard Worker // Performs the given requests. Results will be returned to each 149*14675a02SAndroid Build Coastguard Worker // corresponding `HttpRequestCallback` while this method is blocked. This 150*14675a02SAndroid Build Coastguard Worker // method must block until all requests have finished or have been cancelled, 151*14675a02SAndroid Build Coastguard Worker // and until all corresponding request callbacks have returned. 152*14675a02SAndroid Build Coastguard Worker // 153*14675a02SAndroid Build Coastguard Worker // By decoupling the enqueueing and starting of (groups of) requests, 154*14675a02SAndroid Build Coastguard Worker // implementations may be able to handle concurrent requests more optimally 155*14675a02SAndroid Build Coastguard Worker // (e.g. by issuing them over a shared HTTP connection). Having separate 156*14675a02SAndroid Build Coastguard Worker // per-request `HttpRequestHandle` objects also makes it easier to support 157*14675a02SAndroid Build Coastguard Worker // canceling specific requests, releasing resources for specific requests, 158*14675a02SAndroid Build Coastguard Worker // accessing stats for specific requests, etc. 159*14675a02SAndroid Build Coastguard Worker // 160*14675a02SAndroid Build Coastguard Worker // The `HttpRequestHandle` and `HttpRequestCallback` instances must outlive 161*14675a02SAndroid Build Coastguard Worker // the call to `PerformRequests`, but may be deleted any time after this call 162*14675a02SAndroid Build Coastguard Worker // has returned. 163*14675a02SAndroid Build Coastguard Worker // 164*14675a02SAndroid Build Coastguard Worker // Returns an `INVALID_ARGUMENT` error if a `HttpRequestHandle` was previously 165*14675a02SAndroid Build Coastguard Worker // already passed to another `PerformRequests` call, or if an 166*14675a02SAndroid Build Coastguard Worker // `HttpRequestHandle`'s `Cancel` method was already called before being 167*14675a02SAndroid Build Coastguard Worker // passed to this call. 168*14675a02SAndroid Build Coastguard Worker virtual absl::Status PerformRequests( 169*14675a02SAndroid Build Coastguard Worker std::vector<std::pair<HttpRequestHandle*, HttpRequestCallback*>> 170*14675a02SAndroid Build Coastguard Worker requests) = 0; 171*14675a02SAndroid Build Coastguard Worker }; 172*14675a02SAndroid Build Coastguard Worker 173*14675a02SAndroid Build Coastguard Worker // An HTTP request for a single resource. Implemented by the caller of 174*14675a02SAndroid Build Coastguard Worker // `HttpClient`. 175*14675a02SAndroid Build Coastguard Worker // 176*14675a02SAndroid Build Coastguard Worker // Once instances are passed to `EnqueueRequest`, their lifetime is managed by 177*14675a02SAndroid Build Coastguard Worker // the `HttpClient` implementation. Implementations must tie the `HttpRequest` 178*14675a02SAndroid Build Coastguard Worker // instance lifetime to the lifetime of the `HttpRequestHandle` they return 179*14675a02SAndroid Build Coastguard Worker // (i.e. they should delete the `HttpRequest` from the `HttpRequestHandle` 180*14675a02SAndroid Build Coastguard Worker // destructor). 181*14675a02SAndroid Build Coastguard Worker // 182*14675a02SAndroid Build Coastguard Worker // Methods of this class may get called from any thread (and subsequent calls 183*14675a02SAndroid Build Coastguard Worker // are not required to all happen on the same thread). 184*14675a02SAndroid Build Coastguard Worker class HttpRequest { 185*14675a02SAndroid Build Coastguard Worker public: 186*14675a02SAndroid Build Coastguard Worker // Note: the request methods imply a set of standard request properties such 187*14675a02SAndroid Build Coastguard Worker // as cacheability, safety, and idempotency. See 188*14675a02SAndroid Build Coastguard Worker // https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods. 189*14675a02SAndroid Build Coastguard Worker // 190*14675a02SAndroid Build Coastguard Worker // The caller of `HttpClient` may implement its own caching layer in the 191*14675a02SAndroid Build Coastguard Worker // future, so implementations are not expected to cache cacheable requests 192*14675a02SAndroid Build Coastguard Worker // (although they are technically allowed to). 193*14675a02SAndroid Build Coastguard Worker // 194*14675a02SAndroid Build Coastguard Worker // Implementations should not automatically retry requests, even if the 195*14675a02SAndroid Build Coastguard Worker // request method implies it is safe or idempotent. The caller of `HttpClient` 196*14675a02SAndroid Build Coastguard Worker // will own the responsibility for retrying requests. 197*14675a02SAndroid Build Coastguard Worker enum class Method { kHead, kGet, kPost, kPut, kPatch, kDelete }; 198*14675a02SAndroid Build Coastguard Worker 199*14675a02SAndroid Build Coastguard Worker // Must not be called until any corresponding `HttpRequestHandle` has been 200*14675a02SAndroid Build Coastguard Worker // deleted. 201*14675a02SAndroid Build Coastguard Worker virtual ~HttpRequest() = default; 202*14675a02SAndroid Build Coastguard Worker 203*14675a02SAndroid Build Coastguard Worker // The URI to request. Will always have an "https://" scheme (but this may be 204*14675a02SAndroid Build Coastguard Worker // extended in the future). 205*14675a02SAndroid Build Coastguard Worker virtual absl::string_view uri() const = 0; 206*14675a02SAndroid Build Coastguard Worker 207*14675a02SAndroid Build Coastguard Worker // The HTTP method to use for this request. 208*14675a02SAndroid Build Coastguard Worker virtual Method method() const = 0; 209*14675a02SAndroid Build Coastguard Worker 210*14675a02SAndroid Build Coastguard Worker // Extra request headers to include with this request, in addition to any 211*14675a02SAndroid Build Coastguard Worker // headers specified by the `HttpClient` implementation. 212*14675a02SAndroid Build Coastguard Worker // 213*14675a02SAndroid Build Coastguard Worker // See the `HttpClient` comment for the expected behavior w.r.t. a few 214*14675a02SAndroid Build Coastguard Worker // specific headers. 215*14675a02SAndroid Build Coastguard Worker virtual const HeaderList& extra_headers() const = 0; 216*14675a02SAndroid Build Coastguard Worker 217*14675a02SAndroid Build Coastguard Worker // Returns true if the request has a request body (which can be read using 218*14675a02SAndroid Build Coastguard Worker // `ReadBody`). If the request body payload size is known ahead of time, then 219*14675a02SAndroid Build Coastguard Worker // the "Content-Length" header will be set in `extra_headers()`. If it isn't 220*14675a02SAndroid Build Coastguard Worker // known yet then the `HttpClient` implementation should use the 221*14675a02SAndroid Build Coastguard Worker // "Transfer-Encoding: chunked" encoding to transmit the request body to the 222*14675a02SAndroid Build Coastguard Worker // server in chunks (or use an equivalent method of streaming the data, e.g. 223*14675a02SAndroid Build Coastguard Worker // if the connection uses HTTP/2). See the `HttpClient` comment for more 224*14675a02SAndroid Build Coastguard Worker // details. 225*14675a02SAndroid Build Coastguard Worker virtual bool HasBody() const = 0; 226*14675a02SAndroid Build Coastguard Worker 227*14675a02SAndroid Build Coastguard Worker // HttpRequests that up to `requested` bytes of the request body be read into 228*14675a02SAndroid Build Coastguard Worker // `buffer`, and that the actual amount of bytes read is returned. The caller 229*14675a02SAndroid Build Coastguard Worker // retains ownership of the buffer. 230*14675a02SAndroid Build Coastguard Worker // 231*14675a02SAndroid Build Coastguard Worker // Callees must return at least 1 byte, but may otherwise return less than the 232*14675a02SAndroid Build Coastguard Worker // requested amount of data, if more data isn't available yet. Callees should 233*14675a02SAndroid Build Coastguard Worker // return `OUT_OF_RANGE` when the end of data has been reached, in which case 234*14675a02SAndroid Build Coastguard Worker // `buffer` should not be modified. 235*14675a02SAndroid Build Coastguard Worker // 236*14675a02SAndroid Build Coastguard Worker // Callees should return data ASAP, as delaying this for too long may cause 237*14675a02SAndroid Build Coastguard Worker // the network stream to fall idle/run out of data to transmit. 238*14675a02SAndroid Build Coastguard Worker // 239*14675a02SAndroid Build Coastguard Worker // May also return other errors, in which case the request will be ended and 240*14675a02SAndroid Build Coastguard Worker // `HttpRequestCallback::OnResponseError` will be called with the same error. 241*14675a02SAndroid Build Coastguard Worker virtual absl::StatusOr<int64_t> ReadBody(char* buffer, int64_t requested) = 0; 242*14675a02SAndroid Build Coastguard Worker }; 243*14675a02SAndroid Build Coastguard Worker 244*14675a02SAndroid Build Coastguard Worker // A handle to a pending `HttpRequest`, allowing a caller of `HttpClient` to 245*14675a02SAndroid Build Coastguard Worker // access stats for the request or to cancel ongoing requests. Implemented by 246*14675a02SAndroid Build Coastguard Worker // the `HttpClient` implementer. 247*14675a02SAndroid Build Coastguard Worker // 248*14675a02SAndroid Build Coastguard Worker // The lifetimes of instances of this class are owned by the caller of 249*14675a02SAndroid Build Coastguard Worker // `HttpClient`. 250*14675a02SAndroid Build Coastguard Worker // 251*14675a02SAndroid Build Coastguard Worker // Methods of this class may get called from any thread (and subsequent calls 252*14675a02SAndroid Build Coastguard Worker // are not required to all happen on the same thread). 253*14675a02SAndroid Build Coastguard Worker class HttpRequestHandle { 254*14675a02SAndroid Build Coastguard Worker public: 255*14675a02SAndroid Build Coastguard Worker // When this is called, `HttpClient` implementations should delete all their 256*14675a02SAndroid Build Coastguard Worker // owned resources as well as the associated `HttpRequest`. 257*14675a02SAndroid Build Coastguard Worker virtual ~HttpRequestHandle() = default; 258*14675a02SAndroid Build Coastguard Worker 259*14675a02SAndroid Build Coastguard Worker // The total amount of data sent/received over the network for this request up 260*14675a02SAndroid Build Coastguard Worker // to this point. These numbers should reflect as close as possible the amount 261*14675a02SAndroid Build Coastguard Worker // of bytes sent "over the wire". This means, for example, that if the data is 262*14675a02SAndroid Build Coastguard Worker // compressed or if a `Transfer-Encoding` is used, the numbers should reflect 263*14675a02SAndroid Build Coastguard Worker // the compressed and/or encoded size of the data (if the implementation is 264*14675a02SAndroid Build Coastguard Worker // able to account for that). Implementations are allowed to account for the 265*14675a02SAndroid Build Coastguard Worker // overhead of TLS encoding in these numbers, but are not required to (since 266*14675a02SAndroid Build Coastguard Worker // many HTTP libraries also do not provide stats at that level of 267*14675a02SAndroid Build Coastguard Worker // granularity). 268*14675a02SAndroid Build Coastguard Worker // 269*14675a02SAndroid Build Coastguard Worker // If the request was served from a cache then this should reflect only the 270*14675a02SAndroid Build Coastguard Worker // actual bytes sent over the network (e.g. 0 if returned from disk directly, 271*14675a02SAndroid Build Coastguard Worker // or if a cache validation request was sent only those bytes used by the 272*14675a02SAndroid Build Coastguard Worker // validation request/response). 273*14675a02SAndroid Build Coastguard Worker // 274*14675a02SAndroid Build Coastguard Worker // If the request involved redirects, the numbers returned here should include 275*14675a02SAndroid Build Coastguard Worker // the bytes sent/received for those redirects, if the implementation supports 276*14675a02SAndroid Build Coastguard Worker // this. Otherwise they are allowed to reflect only the final 277*14675a02SAndroid Build Coastguard Worker // request/response's bytes sent/received. 278*14675a02SAndroid Build Coastguard Worker // 279*14675a02SAndroid Build Coastguard Worker // Implementations should strive to return as up-to-date numbers are possible 280*14675a02SAndroid Build Coastguard Worker // from these methods (e.g. ideally the 'sent' number should reflect the 281*14675a02SAndroid Build Coastguard Worker // amount of request body data that has been uploaded so far, even if the 282*14675a02SAndroid Build Coastguard Worker // upload hasn't completed fully yet; similarly the 'received' number should 283*14675a02SAndroid Build Coastguard Worker // reflect the amount of response body data received so far, even if the 284*14675a02SAndroid Build Coastguard Worker // response hasn't been fully received yet). 285*14675a02SAndroid Build Coastguard Worker // 286*14675a02SAndroid Build Coastguard Worker // The numbers returned here are not required to increase monotonically 287*14675a02SAndroid Build Coastguard Worker // between each call to the method. E.g. implementations are allowed to return 288*14675a02SAndroid Build Coastguard Worker // best-available estimates while the request is still in flight, and then 289*14675a02SAndroid Build Coastguard Worker // revise the numbers down to a more accurate number once the request has been 290*14675a02SAndroid Build Coastguard Worker // completed. 291*14675a02SAndroid Build Coastguard Worker struct SentReceivedBytes { 292*14675a02SAndroid Build Coastguard Worker int64_t sent_bytes; 293*14675a02SAndroid Build Coastguard Worker int64_t received_bytes; 294*14675a02SAndroid Build Coastguard Worker }; 295*14675a02SAndroid Build Coastguard Worker virtual SentReceivedBytes TotalSentReceivedBytes() const = 0; 296*14675a02SAndroid Build Coastguard Worker 297*14675a02SAndroid Build Coastguard Worker // Used to indicate that the request should be cancelled and that 298*14675a02SAndroid Build Coastguard Worker // implementations may release resources associated with this request (e.g. 299*14675a02SAndroid Build Coastguard Worker // the socket used by the request). 300*14675a02SAndroid Build Coastguard Worker // 301*14675a02SAndroid Build Coastguard Worker // Callers are still only allowed to delete this instance once after any 302*14675a02SAndroid Build Coastguard Worker // corresponding `PerformRequests()` call has completed, and not before. 303*14675a02SAndroid Build Coastguard Worker // 304*14675a02SAndroid Build Coastguard Worker // If a `PerformRequests` call is ongoing for this handle, then the 305*14675a02SAndroid Build Coastguard Worker // corresponding `HttpRequestCallback` instance may still receive further 306*14675a02SAndroid Build Coastguard Worker // method invocations after this call returns (e.g. because an invocation may 307*14675a02SAndroid Build Coastguard Worker // already have been in flight). 308*14675a02SAndroid Build Coastguard Worker // 309*14675a02SAndroid Build Coastguard Worker // If a `PerformRequests` call is ongoing for this handle, and if the 310*14675a02SAndroid Build Coastguard Worker // `HttpRequestCallback::OnResponseStarted` method was not called yet, then 311*14675a02SAndroid Build Coastguard Worker // the `HttpRequestCallback::OnResponseError` method must be called with 312*14675a02SAndroid Build Coastguard Worker // status `CANCELLED`. 313*14675a02SAndroid Build Coastguard Worker // 314*14675a02SAndroid Build Coastguard Worker // Otherwise, if a `PerformRequests` call is ongoing for this handle, and if 315*14675a02SAndroid Build Coastguard Worker // the `HttpRequestCallback::OnResponseCompleted` method was not called yet, 316*14675a02SAndroid Build Coastguard Worker // then the `HttpRequestCallback::OnResponseBodyError` method must be called 317*14675a02SAndroid Build Coastguard Worker // with status `CANCELLED`. 318*14675a02SAndroid Build Coastguard Worker virtual void Cancel() = 0; 319*14675a02SAndroid Build Coastguard Worker }; 320*14675a02SAndroid Build Coastguard Worker 321*14675a02SAndroid Build Coastguard Worker // The callback interface that `HttpClient` implementations must use to deliver 322*14675a02SAndroid Build Coastguard Worker // the response to a `HttpRequest`. Implemented by the caller of `HttpClient`. 323*14675a02SAndroid Build Coastguard Worker // 324*14675a02SAndroid Build Coastguard Worker // The lifetimes of instances of this class are owned by the caller of 325*14675a02SAndroid Build Coastguard Worker // `HttpClient`. Instances must remain alive for at least as long as their 326*14675a02SAndroid Build Coastguard Worker // corresponding `PerformRequests` call. 327*14675a02SAndroid Build Coastguard Worker // 328*14675a02SAndroid Build Coastguard Worker // Methods of this class may get called from any thread (incl. concurrently), 329*14675a02SAndroid Build Coastguard Worker // but callers of this class must always call the callback methods for a 330*14675a02SAndroid Build Coastguard Worker // specific `HttpRequest` in the order specified in each method's documentation. 331*14675a02SAndroid Build Coastguard Worker // Implementations of this class therefore likely should use internal 332*14675a02SAndroid Build Coastguard Worker // synchronization. 333*14675a02SAndroid Build Coastguard Worker // 334*14675a02SAndroid Build Coastguard Worker // For example, a call to `OnResponseBody` for a given `HttpRequest` A will 335*14675a02SAndroid Build Coastguard Worker // always be preceded by a completed call to `OnResponseStarted` for that same 336*14675a02SAndroid Build Coastguard Worker // request A. However, callbacks for different `HttpRequest` objects may happen 337*14675a02SAndroid Build Coastguard Worker // concurrently, so for example, `OnResponseStarted` may be called concurrently 338*14675a02SAndroid Build Coastguard Worker // for two different requests A and B. This latter scenario means that if the 339*14675a02SAndroid Build Coastguard Worker // same `HttpRequestCallback` object is used to handle callbacks for both 340*14675a02SAndroid Build Coastguard Worker // requests, then the object has to handle concurrent calls correctly. 341*14675a02SAndroid Build Coastguard Worker class HttpRequestCallback { 342*14675a02SAndroid Build Coastguard Worker public: 343*14675a02SAndroid Build Coastguard Worker virtual ~HttpRequestCallback() = default; 344*14675a02SAndroid Build Coastguard Worker 345*14675a02SAndroid Build Coastguard Worker // Called when the final HTTP response headers have been received (i.e. after 346*14675a02SAndroid Build Coastguard Worker // any redirects have been followed but before the response body may have been 347*14675a02SAndroid Build Coastguard Worker // received fully) for the given `HttpRequest`. The response data can be 348*14675a02SAndroid Build Coastguard Worker // accessed via the given `HttpResponse`, which will remain alive for the 349*14675a02SAndroid Build Coastguard Worker // lifetime of the corresponding `HttpRequestHandle`. 350*14675a02SAndroid Build Coastguard Worker // 351*14675a02SAndroid Build Coastguard Worker // Note that all the data in the `HttpResponse` object should reflect the 352*14675a02SAndroid Build Coastguard Worker // last/final response (i.e. it shouldn't reflect any already-followed 353*14675a02SAndroid Build Coastguard Worker // redirects). 354*14675a02SAndroid Build Coastguard Worker // 355*14675a02SAndroid Build Coastguard Worker // If the response has a body then after this method is called 356*14675a02SAndroid Build Coastguard Worker // `OnResponseBody` will be called one or more times to deliver the response 357*14675a02SAndroid Build Coastguard Worker // body (or `OnResponseBodyError` if an error occurs). 358*14675a02SAndroid Build Coastguard Worker // 359*14675a02SAndroid Build Coastguard Worker // Note that responses with an HTTP status code other than 200 ("OK") may 360*14675a02SAndroid Build Coastguard Worker // still have response bodies, and implementations must deliver these via the 361*14675a02SAndroid Build Coastguard Worker // `OnResponseBody` callback, just as they should for a successful response. 362*14675a02SAndroid Build Coastguard Worker // 363*14675a02SAndroid Build Coastguard Worker // If this method returns an error then the `HttpClient` implementation should 364*14675a02SAndroid Build Coastguard Worker // consider the `HttpRequest` canceled. No further methods must be called on 365*14675a02SAndroid Build Coastguard Worker // this `HttpRequestCallback` instance for the given `HttpRequest` after in 366*14675a02SAndroid Build Coastguard Worker // this case. 367*14675a02SAndroid Build Coastguard Worker virtual absl::Status OnResponseStarted(const HttpRequest& request, 368*14675a02SAndroid Build Coastguard Worker const HttpResponse& response) = 0; 369*14675a02SAndroid Build Coastguard Worker 370*14675a02SAndroid Build Coastguard Worker // Called when the request encountered an error or timed out, before receiving 371*14675a02SAndroid Build Coastguard Worker // the response headers completely. No further methods must be called on this 372*14675a02SAndroid Build Coastguard Worker // `HttpRequestCallback` instance for the given `HttpRequest` after this 373*14675a02SAndroid Build Coastguard Worker // method is called. 374*14675a02SAndroid Build Coastguard Worker // 375*14675a02SAndroid Build Coastguard Worker // If the implementation is able to discern that the error may have been 376*14675a02SAndroid Build Coastguard Worker // transient, they should return `UNAVAILABLE`. 377*14675a02SAndroid Build Coastguard Worker // 378*14675a02SAndroid Build Coastguard Worker // If more than the implementation's defined max number of redirects occurred 379*14675a02SAndroid Build Coastguard Worker // (without reaching the final response), then implementations should return 380*14675a02SAndroid Build Coastguard Worker // `OUT_OF_RANGE` here. 381*14675a02SAndroid Build Coastguard Worker // 382*14675a02SAndroid Build Coastguard Worker // If the implementation hit an implementation-specific timeout (even though 383*14675a02SAndroid Build Coastguard Worker // implementations are discouraged from imposing such timeouts), then this 384*14675a02SAndroid Build Coastguard Worker // should be `DEADLINE_EXCEEDED`. 385*14675a02SAndroid Build Coastguard Worker // 386*14675a02SAndroid Build Coastguard Worker // If the `HttpRequestHandle::Cancel` method was called before 387*14675a02SAndroid Build Coastguard Worker // `OnResponseStarted` was called for the given `HttpRequest`, then this 388*14675a02SAndroid Build Coastguard Worker // method will be called with a `CANCELLED` status. 389*14675a02SAndroid Build Coastguard Worker // 390*14675a02SAndroid Build Coastguard Worker // If the request's `HttpRequest::ReadBody` returned an unexpected error, 391*14675a02SAndroid Build Coastguard Worker // then method will be called with that error. 392*14675a02SAndroid Build Coastguard Worker virtual void OnResponseError(const HttpRequest& request, 393*14675a02SAndroid Build Coastguard Worker const absl::Status& error) = 0; 394*14675a02SAndroid Build Coastguard Worker 395*14675a02SAndroid Build Coastguard Worker // Called (possibly multiple times per request) when a block of response data 396*14675a02SAndroid Build Coastguard Worker // is available in `data`. This method must only be called after 397*14675a02SAndroid Build Coastguard Worker // `OnResponseStarted` was called for the given `HttpRequest`. 398*14675a02SAndroid Build Coastguard Worker // 399*14675a02SAndroid Build Coastguard Worker // Callees must process the data ASAP, as delaying this for too long may 400*14675a02SAndroid Build Coastguard Worker // prevent additional data from arriving on the network stream. 401*14675a02SAndroid Build Coastguard Worker // 402*14675a02SAndroid Build Coastguard Worker // If this method returns an error then the `HttpClient` implementation should 403*14675a02SAndroid Build Coastguard Worker // consider the `HttpRequest` canceled. No further methods must be called on 404*14675a02SAndroid Build Coastguard Worker // this `HttpRequestCallback` instance for the given `HttpRequest` after in 405*14675a02SAndroid Build Coastguard Worker // this case. 406*14675a02SAndroid Build Coastguard Worker virtual absl::Status OnResponseBody(const HttpRequest& request, 407*14675a02SAndroid Build Coastguard Worker const HttpResponse& response, 408*14675a02SAndroid Build Coastguard Worker absl::string_view data) = 0; 409*14675a02SAndroid Build Coastguard Worker 410*14675a02SAndroid Build Coastguard Worker // Called when the request encountered an error or timed out while receiving 411*14675a02SAndroid Build Coastguard Worker // the response body (i.e. after `OnResponseStarted` was called). No further 412*14675a02SAndroid Build Coastguard Worker // methods must be called on this `HttpRequestCallback` instance for the given 413*14675a02SAndroid Build Coastguard Worker // `HttpRequest` after this method is called. 414*14675a02SAndroid Build Coastguard Worker // 415*14675a02SAndroid Build Coastguard Worker // If the implementation is able to discern that the error may have been 416*14675a02SAndroid Build Coastguard Worker // transient, they should return `UNAVAILABLE`. 417*14675a02SAndroid Build Coastguard Worker // 418*14675a02SAndroid Build Coastguard Worker // If the implementation hit an implementation-specific timeout (even though 419*14675a02SAndroid Build Coastguard Worker // implementations are discouraged from imposing such timeouts), then this 420*14675a02SAndroid Build Coastguard Worker // should be `DEADLINE_EXCEEDED`. 421*14675a02SAndroid Build Coastguard Worker // 422*14675a02SAndroid Build Coastguard Worker // If the `HttpRequestHandle::Cancel` method was called before 423*14675a02SAndroid Build Coastguard Worker // `OnResponseCompleted` was called for the given `HttpRequest`, then this 424*14675a02SAndroid Build Coastguard Worker // method will be called with a `CANCELLED` status. 425*14675a02SAndroid Build Coastguard Worker virtual void OnResponseBodyError(const HttpRequest& request, 426*14675a02SAndroid Build Coastguard Worker const HttpResponse& response, 427*14675a02SAndroid Build Coastguard Worker const absl::Status& error) = 0; 428*14675a02SAndroid Build Coastguard Worker 429*14675a02SAndroid Build Coastguard Worker // Called when the request has completed successfully (i.e. the response 430*14675a02SAndroid Build Coastguard Worker // headers were delivered, and if there was a response body then it was also 431*14675a02SAndroid Build Coastguard Worker // delivered successfully). Must not be called if one of the error callbacks 432*14675a02SAndroid Build Coastguard Worker // was already called for the given `HttpRequest`, and no further methods must 433*14675a02SAndroid Build Coastguard Worker // be called on this `HttpRequestCallback` instance for the given 434*14675a02SAndroid Build Coastguard Worker // `HttpRequest` after this method is called. 435*14675a02SAndroid Build Coastguard Worker virtual void OnResponseCompleted(const HttpRequest& request, 436*14675a02SAndroid Build Coastguard Worker const HttpResponse& response) = 0; 437*14675a02SAndroid Build Coastguard Worker }; 438*14675a02SAndroid Build Coastguard Worker 439*14675a02SAndroid Build Coastguard Worker // A response to a given `HttpRequest`. Implemented by the `HttpClient` 440*14675a02SAndroid Build Coastguard Worker // implementer. 441*14675a02SAndroid Build Coastguard Worker // 442*14675a02SAndroid Build Coastguard Worker // The lifetimes of instances of this class are managed by the `HttpClient` 443*14675a02SAndroid Build Coastguard Worker // implementer. Instances of this class must remain alive for at least long as 444*14675a02SAndroid Build Coastguard Worker // the corresponding `HttpRequestHandle` is alive. 445*14675a02SAndroid Build Coastguard Worker // 446*14675a02SAndroid Build Coastguard Worker // Note that all the data in this object should be for the last/final response. 447*14675a02SAndroid Build Coastguard Worker // I.e. any responses corresponding to redirects should not be reflected here. 448*14675a02SAndroid Build Coastguard Worker class HttpResponse { 449*14675a02SAndroid Build Coastguard Worker public: 450*14675a02SAndroid Build Coastguard Worker virtual ~HttpResponse() = default; 451*14675a02SAndroid Build Coastguard Worker 452*14675a02SAndroid Build Coastguard Worker // The response code returned by the server (e.g. 200). 453*14675a02SAndroid Build Coastguard Worker virtual int code() const = 0; 454*14675a02SAndroid Build Coastguard Worker 455*14675a02SAndroid Build Coastguard Worker // The response headers. Implementations are allowed to either coalesce 456*14675a02SAndroid Build Coastguard Worker // repeated headers using commas (as per RFC2616 section 4.2), or to return 457*14675a02SAndroid Build Coastguard Worker // them as separate entries. 458*14675a02SAndroid Build Coastguard Worker // 459*14675a02SAndroid Build Coastguard Worker // See `HttpClient` comment for the expected behavior w.r.t. a few specific 460*14675a02SAndroid Build Coastguard Worker // headers. 461*14675a02SAndroid Build Coastguard Worker virtual const HeaderList& headers() const = 0; 462*14675a02SAndroid Build Coastguard Worker }; 463*14675a02SAndroid Build Coastguard Worker 464*14675a02SAndroid Build Coastguard Worker } // namespace http 465*14675a02SAndroid Build Coastguard Worker } // namespace client 466*14675a02SAndroid Build Coastguard Worker } // namespace fcp 467*14675a02SAndroid Build Coastguard Worker 468*14675a02SAndroid Build Coastguard Worker #endif // FCP_CLIENT_HTTP_HTTP_CLIENT_H_ 469