HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NET_WebResponse.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: NET_WebResponse.h
7  *
8  * COMMENTS:
9  *
10  */
11 
12 #ifndef __NET_WEBRESPONSE_H__
13 #define __NET_WEBRESPONSE_H__
14 
15 #include "NET_API.h"
16 
17 #include "NET_HTTPDefines.h"
18 #include "NET_Time.h"
19 #include "NET_WebTypes.h"
20 
21 #include <UT/UT_ArrayStringMap.h>
22 #include <UT/UT_Debug.h>
23 #include <UT/UT_FileUtil.h>
24 #include <UT/UT_Optional.h>
25 #include <UT/UT_SharedPtr.h>
26 #include <UT/UT_StringArray.h>
27 #include <UT/UT_StringHolder.h>
28 
29 class NET_NetworkCookie;
30 class NET_HTTPRequest;
31 
32 // NOTE: Not a full list of http status codes
34 {
35  // Curl uses zero to indicate no status code received
37  // Info Codes
40  // Success Codes
41  NET_HTTPOk = 200,
48  // Redirect Codes
56  // Client Error Codes
67  NET_HTTPGone = 410,
82  // Server Error Codes
90 };
91 
92 /// Holds all common information between a client response and an object holding
93 /// the servers response to a client.
95 {
96 public:
102  NET_HTTPStatusCode code,
103  const HeaderMap &headers,
104  const UT_StringHolder &data);
105  NET_BaseWebResponse(NET_HTTPStatusCode code, const HeaderMap &headers);
106 
107  explicit operator bool() const { return isSuccess(); }
108 
109  bool isSuccess() const { return myStatus == NET_HTTPOk; }
110 
111  bool isRequestNotFound() const { return myStatus == NET_HTTPNotFound; }
112  bool isBadRequest() const { return myStatus == NET_HTTPBadRequest; }
113  bool hasTimedout() const { return myStatus == NET_HTTPRequestTimeout; }
114 
115  UT_StringHolder headersAsString() const;
116 
117  // Does this response object have a specific option specified.
118  bool hasHeader(const UT_StringRef &header) const;
119 
120  void setDefault(const UT_StringHolder& name, const UT_StringHolder& value);
121 
122  UT_Optional<const UT_StringHolder &> getHeaderContentType();
124  {
125  auto it = myHeaders.find(HTTP_CONTENT_TYPE);
126  if (it == myHeaders.end())
128  return it->second;
129  }
130  UT_Optional<exint> getHeaderContentLength();
131 
132  bool hasContentType(const UT_StringRef &mime) const;
133 
134  NET_Time modTime() const;
135 
136  // Get the stock message based on the status code
137  static void stockMsgFromCode(NET_HTTPStatusCode code, UT_WorkBuffer &msg);
138 
139  bool hasJSONBody() const;
140  static bool isJSONBody(const HeaderMap &headers);
141 
142  // The status of the response
144  // The headers of the response
147  // The body of the response
149 };
150 
151 /// Response object used by a client from a response by a server.
153 {
154 public:
155  struct NET_API Error
156  {
157  // This are all of the protocol independent error codes.
158  //
159  // The currently match curls error code number but do not make the
160  // assumption that will always be the case. Use a translate function if
161  // you need to go between the two.
162  enum Code
163  {
164  INTERNAL_ERROR = -1,
165  OK = 0,
251  OBSOLETE
252  };
253 
254  UT_StringHolder buildErrorMessage() const;
255  static Code translateErrorToCode(int err);
256  static UT_StringHolder codeToString(Code code);
257 
258  Code myErrorCode = Code::OK;
259  // Explenation of the error
261  // Extra details we provide about the error. Most of the time this error
262  // string will be empty. Its meant to give extra information to a
263  // standard error. (ie. cert error)
265  };
266 
271  NET_HTTPStatusCode code,
272  const HeaderMap &headers,
273  const UT_StringHolder &data);
274  NET_HTTPResponse(NET_HTTPStatusCode code, const HeaderMap &headers);
275 
276  void parseCookies(UT_Array<NET_NetworkCookie> &cookies);
277  bool errorReceivedNothing() const
278  {
279  return myError.myErrorCode == Error::GOT_NOTHING;
280  }
281  void clear();
282 
284 };
285 
286 /// Response object used for responding to request in the server.
288 {
289 public:
291 
294  {
296  }
299  {
300  _init(code);
301  }
304  {
305  _init(code);
306  setBody(data);
307  }
309  NET_HTTPStatusCode code,
310  const HeaderMap &headers,
311  const UT_StringHolder &data)
313  {
314  _init(code);
315  setHeaders(headers);
316  setBody(data);
317  }
320  {
321  _init(code);
322  setHeaders(headers);
323  }
324 
325  NET_WebResponse(const NET_WebResponse &resp) = default;
326  NET_WebResponse &operator=(const NET_WebResponse &resp) = default;
327  NET_WebResponse(NET_WebResponse &&resp) = default;
328  NET_WebResponse &operator=(NET_WebResponse &&resp) = default;
329 
330  // Convience operators to forward a client response as a server response
333  {
334  _init(resp.myStatus);
335  setHeaders(resp.myHeaders);
336  setBody(resp.myData);
337  }
339  {
340  _init();
341  setHeaders(resp.myHeaders);
342  setBody(resp.myData);
343  return *this;
344  }
345 
346  void clear();
347 
348  bool isFile() const { return myFile.isstring(); }
349 
350  bool isChunked() const
351  {
352  return myChunked;
353  }
354  bool hasHeader(const UT_StringRef& header) const
355  {
356  return NET_BaseWebResponse::hasHeader(header);
357  }
358 
360  {
361  return NET_BaseWebResponse::setDefault(name, value);
362  }
363 
365  {
366  myStatus = code;
367 
368  if (myStatus == NET_HTTPNoContent ||
369  myStatus == NET_HTTPNotModified)
370  {
371  myChunked = true;
372  }
373  }
374  NET_HTTPStatusCode status() const { return myStatus; }
375 
376  // Set a header entry. An empty header value means to remove the entry.
377  void setHeader(const UT_StringRef& name, const UT_StringRef& value);
378  void setHeaders(const HeaderMap& headers)
379  {
380  for (auto&& header : headers)
381  {
382  setHeader(header.first, header.second);
383  }
384  }
385  // Used whenever a header can have a list of values attached to it
386  // (i.e. Vary)
387  void patchHeader(const UT_StringHolder& name, const UT_StringHolder& value);
388 
389  // Set the response as an in memory response
390  void setBody(const UT_StringHolder& body, const UT_StringRef& content_type = "")
391  {
392  clearFile();
393 
394  myData = body;
395  if (!content_type.isEmpty())
396  myContentType = content_type;
397  else if (myContentType.isEmpty())
398  myContentType = "text/plain";
399  myContentLength = myData.length();
400  }
401  // Set the next chunk to send. This only updates the body and if there is
402  // more data to be processed. The chunked header MUST be set prior to
403  // calling this function.
404  void setBodyChunk(const UT_StringHolder& body, bool has_more = false)
405  {
406  UT_ASSERT(myChunked);
407 
408  myHasMoreData = has_more;
409  myData = body;
410  }
411  // Helper method to set a text body
412  void setText(const UT_StringHolder& body)
413  {
414  setBody(body, "text/plain");
415  }
416  void setJSON(const UT_StringHolder& body)
417  {
418  setBody(body, "application/json");
419  }
420  // Set the response as a file response.
421  void setFile(const UT_StringHolder& file, bool delete_file);
422  void clearBody()
423  {
424  myData.clear();
425  }
426  void clearFile()
427  {
428  myFile.clear();
429  myDeleteFile = false;
430  myHeaders.erase(HTTP_LAST_MODIFIED);
431  }
432  // Set the ranges for our response.
433  void setRanges(const NET_RequestRangeList& ranges)
434  {
435  myRanges = ranges;
436  // Create a boundary if we have multiple ranges
437  //
438  // NB: we dont set/change the content type as we will just set the
439  // content type when sending so that the body can send the proper
440  // content type when its time to send this information.
441  if (ranges.entries() > 1)
442  myBoundary.format("-----{}", time(NULL) ^ (uint64)(this));
443  else
444  myBoundary.clear();
445 
446  setHeader(HTTP_ACCEPT_RANGES, "bytes");
447  }
448 
449  void clearRanges()
450  {
451  myRanges.clear();
452  myBoundary.clear();
453  myHeaders.erase(HTTP_ACCEPT_RANGES);
454  }
455 
456  bool shouldClose() const
457  {
458  if (!myKeepAlive)
459  return true;
460 
461  if (myUpgrade)
462  return false;
463 
464  if (myStatus > 499)
465  return true;
466 
467  return false;
468  }
469  const UT_StringHolder& data() const
470  {
471  return myData;
472  }
473  exint contentLength() const { return myContentLength; }
474  const UT_StringHolder& contentType() const { return myContentType; }
475  const HeaderMap& headers() const { return myHeaders; }
476  bool isUpgrade() const { return myUpgrade; }
477  void setErrors(const UT_StringHolder& errors)
478  {
479  myErrors = errors;
480  }
481  const NET_RequestRangeList& ranges() const { return myRanges; }
482  const UT_StringHolder& boundary() const { return myBoundary; }
483  bool isTempFile() const { return myDeleteFile; }
484  const UT_StringHolder& file() const { return myFile; }
485  // True if there is more data that needs to be sent. This only has meaning
486  // if the response is chunked.
487  bool hasMoreData() const { return myHasMoreData; }
488  bool keepAlive() const { return myKeepAlive; }
489  void setKeepAlive(bool keep_alive) { myKeepAlive = keep_alive; }
490 private:
492  {
493  myChunked = false;
494 
495  setStatus(code);
496 
497  myHeaders.clear();
498  myCookies.clear();
499 
500  myContentType.clear();
501  myBoundary.clear();
502  myContentLength = 0;
503 
504  myFile.clear();
505  myDeleteFile = false;
506 
507  myRanges.clear();
508 
509  myData.clear();
510 
511  myUpgrade = false;
512 
513  myHasMoreData = false;
514  myKeepAlive = true;
515 
516  myErrors.clear();
517  }
518 
519 private:
520  friend class NET_HttpIO;
521 
522  NET_RequestRangeList myRanges;
523 
524  UT_StringHolder myContentType;
525  UT_StringHolder myBoundary;
526  exint myContentLength;
527 
528  UT_StringHolder myFile;
529  unsigned myDeleteFile : 1;
530  unsigned myUpgrade : 1;
531  unsigned myChunked : 1;
532  unsigned myHasMoreData : 1;
533  unsigned myKeepAlive : 1;
534  // Error that you might want hidden
535  UT_StringHolder myErrors;
536 };
537 
539 
540 #endif // __NET_WEBRESPONSE_H__
541 
NET_HTTPStatusCode status() const
const UT_StringHolder & contentTypeOrEmpty() const
void setDefault(const UT_StringHolder &name, const UT_StringHolder &value)
Response object used for responding to request in the server.
void setErrors(const UT_StringHolder &errors)
GT_API const UT_StringHolder time
int64 exint
Definition: SYS_Types.h:125
void setKeepAlive(bool keep_alive)
UT_StringHolder myData
NET_WebResponse(NET_HTTPStatusCode code, const UT_StringHolder &data)
bool isFile() const
bool isTempFile() const
GLuint const GLchar * name
Definition: glcorearb.h:785
unsigned long long uint64
Definition: SYS_Types.h:117
NET_HTTPStatusCode
void setRanges(const NET_RequestRangeList &ranges)
UT_StringArray myCookies
#define NET_API
Definition: NET_API.h:9
void setText(const UT_StringHolder &body)
bool hasHeader(const UT_StringRef &header) const
hboost::optional< T > UT_Optional
Definition: UT_Optional.h:16
Response object used by a client from a response by a server.
exint length() const
void setStatus(NET_HTTPStatusCode code)
std::shared_ptr< T > UT_SharedPtr
Wrapper around std::shared_ptr.
Definition: UT_SharedPtr.h:30
bool isRequestNotFound() const
static const UT_StringHolder theEmptyString
void setJSON(const UT_StringHolder &body)
bool shouldClose() const
void setDefault(const UT_StringHolder &name, const UT_StringHolder &value)
const HeaderMap & headers() const
UT_SharedPtr< NET_WebResponse > NET_WebResponseSPtr
UT_ArrayStringMap< UT_StringHolder > HeaderMap
const UT_StringHolder & boundary() const
UT_StringHolder myExtraDetails
bool isUpgrade() const
UT_StringHolder myErrorMsg
bool isSuccess() const
bool keepAlive() const
NET_WebResponse(NET_HTTPStatusCode code, const HeaderMap &headers, const UT_StringHolder &data)
#define HTTP_ACCEPT_RANGES
NET_HTTPStatusCode myStatus
bool hasMoreData() const
NET_WebResponse(NET_HTTPStatusCode code)
exint entries() const
Alias of size(). size() is preferred.
Definition: UT_Array.h:481
GLboolean * data
Definition: glcorearb.h:130
#define HTTP_LAST_MODIFIED
NET_WebResponse & operator=(const NET_HTTPResponse &resp)
void setBody(const UT_StringHolder &body, const UT_StringRef &content_type="")
const NET_RequestRangeList & ranges() const
const UT_StringHolder & data() const
void setHeaders(const HeaderMap &headers)
GLsizei const GLfloat * value
Definition: glcorearb.h:823
exint contentLength() const
NET_WebResponse(NET_HTTPStatusCode code, const HeaderMap &headers)
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:171
void setBodyChunk(const UT_StringHolder &body, bool has_more=false)
bool errorReceivedNothing() const
bool isChunked() const
const UT_StringHolder & file() const
bool hasHeader(const UT_StringRef &header) const
void clear()
Resets list to an empty list.
Definition: UT_Array.h:549
const UT_StringHolder & contentType() const
bool hasTimedout() const
#define HTTP_CONTENT_TYPE
bool isBadRequest() const
NET_WebResponse(const NET_HTTPResponse &resp)