1 /* Copyright 2016 The TensorFlow Authors. All Rights Reserved. 2 3 Licensed under the Apache License, Version 2.0 (the "License"); 4 you may not use this file except in compliance with the License. 5 You may obtain a copy of the License at 6 7 http://www.apache.org/licenses/LICENSE-2.0 8 9 Unless required by applicable law or agreed to in writing, software 10 distributed under the License is distributed on an "AS IS" BASIS, 11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 See the License for the specific language governing permissions and 13 limitations under the License. 14 ==============================================================================*/ 15 16 #ifndef TENSORFLOW_CORE_PLATFORM_CLOUD_HTTP_REQUEST_H_ 17 #define TENSORFLOW_CORE_PLATFORM_CLOUD_HTTP_REQUEST_H_ 18 19 #include <string> 20 #include <unordered_map> 21 #include <vector> 22 23 #include "tensorflow/core/platform/env.h" 24 #include "tensorflow/core/platform/errors.h" 25 #include "tensorflow/core/platform/macros.h" 26 #include "tensorflow/core/platform/protobuf.h" 27 #include "tensorflow/core/platform/status.h" 28 #include "tensorflow/core/platform/stringpiece.h" 29 #include "tensorflow/core/platform/types.h" 30 31 namespace tensorflow { 32 33 /// \brief An abstract basic HTTP client. 34 /// 35 /// The usage pattern for the class is based on the libcurl library: 36 /// create a request object, set request parameters and call Send(). 37 /// 38 /// For example: 39 /// HttpRequest request; 40 /// request.SetUri("http://www.google.com"); 41 /// request.SetResultsBuffer(out_buffer); 42 /// request.Send(); 43 class HttpRequest { 44 public: 45 class Factory { 46 public: ~Factory()47 virtual ~Factory() {} 48 virtual HttpRequest* Create() = 0; 49 }; 50 51 /// RequestMethod is used to capture what type of HTTP request is made and 52 /// is used in conjunction with RequestStats for instrumentation and 53 /// monitoring of HTTP requests and their responses. 54 enum class RequestMethod : char { 55 kGet, 56 kPost, 57 kPut, 58 kDelete, 59 }; 60 61 /// RequestMethodName converts a RequestMethod to the canonical method string. RequestMethodName(RequestMethod m)62 inline static const char* RequestMethodName(RequestMethod m) { 63 switch (m) { 64 case RequestMethod::kGet: 65 return "GET"; 66 case RequestMethod::kPost: 67 return "POST"; 68 case RequestMethod::kPut: 69 return "PUT"; 70 case RequestMethod::kDelete: 71 return "DELETE"; 72 default: 73 return "???"; 74 } 75 } 76 77 /// RequestStats is a class that can be used to instrument an Http Request. 78 class RequestStats { 79 public: 80 virtual ~RequestStats() = default; 81 82 /// RecordRequest is called right before a request is sent on the wire. 83 virtual void RecordRequest(const HttpRequest* request, const string& uri, 84 RequestMethod method) = 0; 85 86 /// RecordResponse is called after the response has been received. 87 virtual void RecordResponse(const HttpRequest* request, const string& uri, 88 RequestMethod method, const Status& result) = 0; 89 }; 90 HttpRequest()91 HttpRequest() {} ~HttpRequest()92 virtual ~HttpRequest() {} 93 94 /// Sets the request URI. 95 virtual void SetUri(const string& uri) = 0; 96 97 /// \brief Sets the Range header. 98 /// 99 /// Used for random seeks, for example "0-999" returns the first 1000 bytes 100 /// (note that the right border is included). 101 virtual void SetRange(uint64 start, uint64 end) = 0; 102 103 /// Sets a request header. 104 virtual void AddHeader(const string& name, const string& value) = 0; 105 106 /// Sets a DNS resolve mapping (to skip DNS resolution). 107 /// 108 /// Note: because GCS is available over HTTPS, we cannot replace the hostname 109 /// in the URI with an IP address, as that will cause the certificate check 110 /// to fail. 111 virtual void AddResolveOverride(const string& hostname, int64_t port, 112 const string& ip_addr) = 0; 113 114 /// Sets the 'Authorization' header to the value of 'Bearer ' + auth_token. 115 virtual void AddAuthBearerHeader(const string& auth_token) = 0; 116 117 /// Sets the RequestStats object to use to record the request and response. 118 virtual void SetRequestStats(RequestStats* stats) = 0; 119 120 /// Makes the request a DELETE request. 121 virtual void SetDeleteRequest() = 0; 122 123 /// \brief Makes the request a PUT request. 124 /// 125 /// The request body will be taken from the specified file starting from 126 /// the given offset. 127 virtual Status SetPutFromFile(const string& body_filepath, size_t offset) = 0; 128 129 /// Makes the request a PUT request with an empty body. 130 virtual void SetPutEmptyBody() = 0; 131 132 /// \brief Makes the request a POST request. 133 /// 134 /// The request body will be taken from the specified buffer. 135 virtual void SetPostFromBuffer(const char* buffer, size_t size) = 0; 136 137 /// Makes the request a POST request with an empty body. 138 virtual void SetPostEmptyBody() = 0; 139 140 /// \brief Specifies the buffer for receiving the response body. 141 /// 142 /// Size of out_buffer after an access will be exactly the number of bytes 143 /// read. Existing content of the vector will be cleared. 144 virtual void SetResultBuffer(std::vector<char>* out_buffer) = 0; 145 146 /// \brief Specifies the buffer for receiving the response body. 147 /// 148 /// This method should be used when a caller knows the upper bound of the 149 /// size of the response data. The caller provides a pre-allocated buffer 150 /// and its size. After the Send() method is called, the 151 /// GetResultBufferDirectBytesTransferred() method may be used to learn to the 152 /// number of bytes that were transferred using this method. 153 virtual void SetResultBufferDirect(char* buffer, size_t size) = 0; 154 155 /// \brief Returns the number of bytes transferred, when using 156 /// SetResultBufferDirect(). This method may only be used when using 157 /// SetResultBufferDirect(). 158 virtual size_t GetResultBufferDirectBytesTransferred() = 0; 159 160 /// \brief Returns the response headers of a completed request. 161 /// 162 /// If the header is not found, returns an empty string. 163 virtual string GetResponseHeader(const string& name) const = 0; 164 165 /// Returns the response code of a completed request. 166 virtual uint64 GetResponseCode() const = 0; 167 168 /// \brief Sends the formed request. 169 /// 170 /// If the result buffer was defined, the response will be written there. 171 /// The object is not designed to be re-used after Send() is executed. 172 virtual Status Send() = 0; 173 174 // Url encodes str and returns a new string. 175 virtual string EscapeString(const string& str) = 0; 176 177 /// \brief Set timeouts for this request. 178 /// 179 /// The connection parameter controls how long we should wait for the 180 /// connection to be established. The inactivity parameter controls how long 181 /// we should wait between additional responses from the server. Finally the 182 /// total parameter controls the maximum total connection time to prevent 183 /// hanging indefinitely. 184 virtual void SetTimeouts(uint32 connection, uint32 inactivity, 185 uint32 total) = 0; 186 187 TF_DISALLOW_COPY_AND_ASSIGN(HttpRequest); 188 }; 189 190 } // namespace tensorflow 191 192 #endif // TENSORFLOW_CORE_PLATFORM_CLOUD_HTTP_REQUEST_H_ 193