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