TensorFlow Serving C++ API Documentation
server_request_interface.h
1 /* Copyright 2018 Google Inc. 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 // net_http::ServerRequestInterface defines a pure interface class for handling
17 // an HTTP request on the server-side. It is designed as a minimum API
18 // to ensure reusability and to work with different HTTP implementations.
19 //
20 // ServerRequestInterface is thread-compatible. Once the request object
21 // has been dispatched to the application-specified handler, the HTTP server
22 // runtime will not access the request object till Reply() is called.
23 //
24 // Streamed request/response APIs are to be added, which will introduce
25 // additional API contract wrt the threading semantics.
26 
27 #ifndef TENSORFLOW_SERVING_UTIL_NET_HTTP_SERVER_PUBLIC_SERVER_REQUEST_INTERFACE_H_
28 #define TENSORFLOW_SERVING_UTIL_NET_HTTP_SERVER_PUBLIC_SERVER_REQUEST_INTERFACE_H_
29 
30 #include <cstdlib>
31 #include <functional>
32 #include <memory>
33 #include <vector>
34 
35 #include "absl/strings/string_view.h"
36 #include "tensorflow_serving/util/net_http/public/response_code_enum.h"
37 
38 namespace tensorflow {
39 namespace serving {
40 namespace net_http {
41 
43  public:
44  // To be used with memory blocks returned via std::unique_ptr<char[]>
45  struct BlockDeleter {
46  public:
47  BlockDeleter() : size_(0) {} // nullptr
48  explicit BlockDeleter(int64_t size) : size_(size) {}
49  inline void operator()(char* ptr) const {
50  // TODO: c++14 ::operator delete[](ptr, size_t)
51  std::allocator<char>().deallocate(ptr, static_cast<std::size_t>(size_));
52  }
53 
54  private:
55  int64_t size_;
56  };
57 
58  virtual ~ServerRequestInterface() = default;
59 
60  ServerRequestInterface(const ServerRequestInterface& other) = delete;
61  ServerRequestInterface& operator=(const ServerRequestInterface& other) =
62  delete;
63 
64  // The portion of the request URI after the host and port.
65  // E.g. "/path/to/resource?param=value&param=value#fragment".
66  // Doesn't unescape the contents; returns "/" at least.
67  virtual absl::string_view uri_path() const = 0;
68 
69  // HTTP request method.
70  // Must be in Upper Case.
71  virtual absl::string_view http_method() const = 0;
72 
73  // Input/output byte-buffer types are subject to change!
74  // I/O buffer choices:
75  // - absl::ByteStream would work but it is not yet open-sourced
76  // - iovec doesn't add much value and may limit portability; but otherwise
77  // the current API is compatible with iovec
78  // - absl::Span is open-sourced, but string_view is simpler to use for writing
79  // to an HTTP response.
80 
81  // Appends the data block of the specified size to the response body.
82  // This request object takes the ownership of the data block.
83  //
84  // Note this is not a streaming write API. See PartialReply() below.
85  virtual void WriteResponseBytes(const char* data, int64_t size) = 0;
86 
87  // Appends (by coping) the data of string_view to the end of
88  // the response body.
89  virtual void WriteResponseString(absl::string_view data) = 0;
90 
91  // Reads from the request body.
92  // Returns the number bytes of data read, whose ownership will be transferred
93  // to the caller. Returns nullptr when EOF is reached or when there
94  // is no request body.
95  //
96  // The returned memory will be "free-ed" via the custom Deleter. Do not
97  // release the memory manually as its allocator is subject to change.
98  //
99  // Note this is not a streaming read API in that the complete request body
100  // should have already been received.
101  virtual std::unique_ptr<char[], ServerRequestInterface::BlockDeleter>
102  ReadRequestBytes(int64_t* size) = 0;
103 
104  // Returns the first value, including "", associated with a request
105  // header name. The header name argument is case-insensitive.
106  // Returns nullptr if the specified header doesn't exist.
107  virtual absl::string_view GetRequestHeader(
108  absl::string_view header) const = 0;
109 
110  // To be added: multi-value headers.
111 
112  // Returns all the request header names.
113  // This is not an efficient way to access headers, mainly for debugging uses.
114  virtual std::vector<absl::string_view> request_headers() const = 0;
115 
116  virtual void OverwriteResponseHeader(absl::string_view header,
117  absl::string_view value) = 0;
118  virtual void AppendResponseHeader(absl::string_view header,
119  absl::string_view value) = 0;
120 
121  // The IO status of a request or response body.
122  enum class BodyStatus {
123  // The body hasn't been completely read or written.
124  PENDING = 0,
125  // The body has been completely read or written or when there is no body.
126  COMPLETE = 1,
127  // The transport has reported a failure and the request should be aborted.
128  FAILED = 2,
129  };
130 
131  // This serves as the return value type for callbacks that may be
132  // skipped for optimization reasons
133  enum class CallbackStatus {
134  NOT_SCHEDULED = 0,
135  SCHEDULED = 1,
136  };
137 
138  // Sends headers and/or any buffered response body data to the client.
139  // Assumes 200 if status is not specified.
140  // If called for the first time, all the response headers will be sent
141  // together including headers specified by the application and
142  // headers generated by the server.
143  // Trying to modify headers or specifying a status after the first
144  // PartialReply() is called is considered a programming error and
145  // the underlying behavior is undefined.
146  virtual void PartialReplyWithStatus(HTTPStatusCode status) = 0;
147  virtual void PartialReply() = 0;
148 
149  // Similar to PartialReply() but with an on_flush callback which will be
150  // invoked when the response data has been completely flushed by the
151  // transport. This allows the handler to apply transport-provided flow-control
152  // in writing data to the peer.
153  //
154  // Returns SCHEDULED if the callback will be invoked asynchronously after
155  // this method returns. Until the callback is invoked, the request object
156  // should not be accessed by the handler.
157  //
158  // Returns NOT_SCHEDULED if data is already flushed when this method returns
159  // or when the request should be aborted due to transport failures.
160  //
161  // The handler should check response_body_status() after this method returns
162  // or from the callback to decide if the request should be aborted due to
163  // transport failures.
164  virtual CallbackStatus PartialReplyWithFlushCallback(
165  std::function<void()> callback) = 0;
166  virtual BodyStatus response_body_status() { return BodyStatus::PENDING; }
167 
168  // Request streaming is disabled by default
169  virtual BodyStatus request_body_status() { return BodyStatus::COMPLETE; }
170 
171  // Completes the response and sends any buffered response body
172  // to the client. Headers will be generated and sent first if PartialReply()
173  // has never be called.
174  // Assumes 200 if status is not specified.
175  // Once Reply() is called, the request object will be owned and destructed
176  // by the server runtime.
177  virtual void ReplyWithStatus(HTTPStatusCode status) = 0;
178  virtual void Reply() = 0;
179 
180  // Aborts the current request forcibly.
181  // Once Abort() is called, the request object will be owned and destructed
182  // by the server runtime.
183  virtual void Abort() = 0;
184 
185  protected:
186  ServerRequestInterface() = default;
187 
188  private:
189  // Do not add any data members to this class.
190 };
191 
192 // Helper methods.
193 
194 inline void SetContentType(ServerRequestInterface* request,
195  absl::string_view type) {
196  request->OverwriteResponseHeader("Content-Type", type);
197 }
198 
199 inline void SetContentTypeHTML(ServerRequestInterface* request) {
200  SetContentType(request, "text/html");
201 }
202 
203 inline void SetContentTypeTEXT(ServerRequestInterface* request) {
204  SetContentType(request, "text/plain");
205 }
206 
207 } // namespace net_http
208 } // namespace serving
209 } // namespace tensorflow
210 
211 #endif // TENSORFLOW_SERVING_UTIL_NET_HTTP_SERVER_PUBLIC_SERVER_REQUEST_INTERFACE_H_