HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NET_WebAPI.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  * COMMENTS:
7  *
8  * Sample usage:
9  * NET_WebAPIResponse response =
10  * NET_WebAPI("http://www.orbolt.com/api").call1(
11  * "is_asset_in_store", "SideFX::spaceship");
12  * response.myJSONResult.dump();
13  * std::cout << "\nerrors: " << response.myErrors.nonNullBuffer()
14  * << std::endl;
15  * Prints:
16  * true
17  * errors:
18  */
19 
20 #ifndef __NET_WebAPI_h__
21 #define __NET_WebAPI_h__
22 
23 #include "NET_API.h"
24 
25 #include "NET_ConvertToType.h"
26 #include "NET_WebResponse.h"
27 #include "NET_WebTypes.h"
28 #include "NET_WebSocket.h"
29 #include "NET_WebAPIResponse.h"
30 
31 #include <NET/NET_NetworkCookie.h>
33 #include <NET/NET_Time.h>
34 #include <NET/NET_Utils.h>
35 
36 #include <type_traits>
37 
38 #include <UT/UT_ArrayStringMap.h>
39 #include <UT/UT_DeepString.h>
40 #include <UT/UT_JSONValue.h>
41 #include <UT/UT_JSONWriter.h>
42 #include <UT/UT_Lock.h>
43 #include <UT/UT_Optional.h>
44 #include <UT/UT_ScopeExit.h>
45 #include <UT/UT_SharedPtr.h>
46 #include <UT/UT_String.h>
47 #include <UT/UT_StringArray.h>
48 #include <UT/UT_StringHolder.h>
49 #include <UT/UT_UniquePtr.h>
50 #include <UT/UT_Url.h>
51 #include <UT/UT_Variant.h>
52 #include <UT/UT_WorkBuffer.h>
53 
54 #include <chrono>
55 
57 
58 // This entire class will be removed next release so do not add any more uses
59 // of this!!!
60 class NET_API NET_WebAPIParameters
61 {
62  friend class NET_NetSession;
63 
64 public:
65  NET_WebAPIParameters() = default;
68 };
69 
70 class NET_API NET_WebAPIBody
71 {
72 public:
74 };
75 
76 class NET_API NET_WebAPIFunction
77 {
78 public:
79  NET_WebAPIFunction() = default;
80  template <typename... Args>
81  NET_WebAPIFunction(const char *function_name, Args &&... args);
82 
84 };
85 
86 class NET_API NET_WebAPICookies
87 {
88 public:
90 };
91 
92 class NET_API NET_WebAPITimeout
93 {
94 public:
97 };
98 
99 class NET_API NET_WebAPICa
100 {
101 public:
104 };
105 
106 class NET_API NET_WebAPIVerbose
107 {
108 public:
109  bool myVerbose;
110 };
111 
112 class NET_API NET_WebAPIProxy
113 {
114 public:
116 };
117 
118 class NET_API NET_WebAPIRedirects
119 {
120 public:
121  bool myAllow;
123 };
124 
125 class NET_API NET_WebAPILowSpeed
126 {
127 public:
130 };
131 
132 /// This is a deprecated class used just for older code.
134 {
135 public:
136  NET_WebsiteAPIResponse() = default;
138 
139  explicit operator bool() const { return !myErrors.isstring(); }
140 
143 };
144 
145 /// If you are using curl then you must call this function prior to set the
146 /// library up
147 NET_API void NETinitializeBackend();
148 
149 class NET_API NET_NetSession
150 {
151 public:
152  NET_NetSession();
153  ~NET_NetSession();
154 
155  // The impl likely doesnt support/allow copying
156  NET_NetSession(const NET_NetSession &) = delete;
157  NET_NetSession &operator=(const NET_NetSession &) = delete;
158 
159  template <typename T>
160  void setOptions(T &&opt)
161  {
162  setOption(opt);
163  }
164  template <typename T, typename... Args>
165  void setOptions(T &&arg, Args &&... args)
166  {
167  setOption(arg);
168  setOptions(std::forward<Args>(args)...);
169  }
170 
171  void setOption(const UT_Url &opt);
172  void setOption(const NET_WebMap &opt);
173  void setOption(const NET_WebAPIParameters &opt);
174  void setOption(const NET_WebAPIBody &opt);
175  void setOption(const NET_WebAPIFunction &opt);
176  void setOption(const NET_WebAPICookies &opt);
177  void setOption(const NET_WebAPITimeout &opt);
178  void setOption(const NET_WebAPICa &opt);
179  void setOption(const NET_WebAPIVerbose &opt);
180  void setOption(const NET_WebAPIProxy &opt);
181  void setOption(const NET_WebAPIRedirects &opt);
182  void setOption(const NET_WebAPILowSpeed &opt);
183 
184  void setUrl(const UT_Url &url);
185  void setUrl(const UT_StringHolder &url);
186  void setTimeout(int64 timeout);
187  void setConnectTimeout(int64 timeout);
188  void setUserAgent(const UT_StringHolder &agent);
189  void setLowSpeed(int64 time, int64 limit);
190 #if 0
191  void setLimitRate(const NET_NetLimitRate& rate);
192 #endif
193  void setVerbose(bool verbose);
194  void setFollowRedirs(bool follow);
195  void setMaxRedirs(int64 max);
196  void addHeaders(const NET_WebMap &headers);
197  void setRawHeader(const UT_StringRef& name, const UT_StringRef& value);
198  void setHeader(NET_KnownHeaders header, const UT_StringRef& value);
199  void setBody(const UT_StringHolder &body);
200  void setCookies(const UT_Array<NET_NetworkCookie> &cookies);
201  void setCaPath(const UT_StringHolder &ca_path);
202  void setCaInfo(const UT_StringHolder &ca_info);
203  void setProxy(const UT_StringHolder &proxy);
204 
205  /// {@
206  /// Get information about the last request used by this session instance.
207  /// Trying to retrieve the information before actually sending the
208  /// request is undefined.
209  bool getTotalTime(fpreal64& total_time) const;
210  bool getConnectTime(fpreal64& connect_time) const;
211  /// @}
212 
213  NET_HTTPResponse post();
214  template <typename T, typename... Args>
215  NET_HTTPResponse post(T &&arg, Args &&... args)
216  {
217  setOptions(arg, std::forward<Args>(args)...);
218  return post();
219  }
220 
221  NET_HTTPResponse get();
222  template <typename T, typename... Args>
223  NET_HTTPResponse get(T &&arg, Args &&... args)
224  {
225  setOptions(arg, std::forward<Args>(args)...);
226  return get();
227  }
228 
229 private:
230  void setOptions() {}
231 
232  static constexpr int SIZEOF_IMPL = 256;
233  char myImpl[SIZEOF_IMPL];
234 };
235 
236 class NET_API NET_WebAPI
237 {
238 public:
241 
242  static UT_StringHolder decodeUri(const UT_StringView uri);
243  static UT_StringHolder encodeUri(const UT_StringView uri);
244 
245  // The following method lets you make API calls to named functions in
246  // the Web API. Call the appropriate method for the given number of
247  // arguments.
248  template <typename... Args>
250  const UT_Url &api_url,
251  const char *api_function,
252  Args &&... args)
253  {
254  NET_NetSession session;
255  return session.post(
256  api_url,
257  NET_WebAPIFunction(api_function, std::forward<Args>(args)...));
258  }
259  template <typename... Args>
261  const UT_Url &api_url,
262  const NET_WebMap &headers,
263  const char *api_function,
264  Args &&... args)
265  {
266  NET_NetSession session;
267  return session.post(
268  api_url, headers,
269  NET_WebAPIFunction(api_function, std::forward<Args>(args)...));
270  }
271  template <typename... Args>
273  NET_NetSession &session,
274  const UT_Url &api_url,
275  const char *api_function,
276  Args &&... args)
277  {
278  return session.post(
279  api_url,
280  NET_WebAPIFunction(api_function, std::forward<Args>(args)...));
281  }
282  template <typename... Args>
285  std::chrono::milliseconds timeout,
286  const char *api_function,
287  Args &&... args)
288  {
289  UT_WorkBuffer wbuf;
291  wbuf, api_function, std::forward<Args>(args)...);
292 
293  NET_Future<NET_WebAPIResponse> f = callWebSocket(ws, wbuf);
294 
295  NET_WebAPIResponse resp;
296  std::future_status status = f.wait_for(timeout);
297 
298  if (status == std::future_status::ready)
299  {
300  resp = f.get();
301  }
302  else
303  {
305  resp.myData = "Response from server was not retrieved before the "
306  "timeout was reached.";
307  }
308  return resp;
309  }
310  template <typename... Args>
313  const char* api_function,
314  Args&&... args)
315  {
316  UT_WorkBuffer wbuf;
317  NET_WebAPI::buildApiCall(wbuf, api_function, std::forward<Args>(args)...);
318 
319  NET_Future<NET_WebAPIResponse> f = callWebSocket(ws, wbuf);
320 
321  return f;
322  }
323 
324  /// Build a json api function with the provided api function name and args.
325  /// The result is placed in the func parameter.
326  template <typename... Args>
327  static void buildApiCall(
329  const char *api_function,
330  Args &&... args);
331 
332  // Determines CURLOPT_CAPATH
333  static UT_StringHolder determineCAPath();
334  // Determines CURLOPT_CAINFO
335  static UT_StringHolder determineCAInfo();
336 
337  static UT_StringHolder encodeVariables(const WebMap &variables);
338 
339 private:
340  static NET_Future<NET_WebAPIResponse> callWebSocket(
342  const UT_WorkBuffer &api);
343 
344 #define __NET_WEB_REQUIRES(T) typename std::enable_if<T>::type * = nullptr
345 
346 #define NET_IS_KWARG(T) (std::is_same<std::decay_t<T>, UT_VariantMap>::value)
347 
348  // Needed until we switch to c++17 (needs constexpr if)
349  static inline void webCall(UT_JSONWriter &writer) {}
350 
351  template <typename T, __NET_WEB_REQUIRES(!NET_IS_KWARG(T))>
352  static inline void webCall(UT_JSONWriter &writer, T &&arg)
353  {
354  using namespace NET_ConvertToType;
355  NETserialize<NET_remove_cref_t<T>>(writer, arg);
356  }
357 
358  template <typename T, __NET_WEB_REQUIRES(NET_IS_KWARG(T))>
359  static inline void webCall(UT_JSONWriter &writer, T &&arg)
360  {
361  writeAPICallSuffixToJSON(writer, arg);
362  }
363 
364  template <typename T, typename... REST>
365  static void webCall(UT_JSONWriter &writer, T &&arg, REST &&... rest)
366  {
367  using namespace NET_ConvertToType;
368  static_assert(
369  !std::is_same<UT_VariantMap, NET_remove_cref_t<T>>::value,
370  "KWargs must be the last element in the function call");
371  NETserialize<NET_remove_cref_t<T>>(writer, arg);
372  webCall(writer, std::forward<REST>(rest)...);
373  }
374 
375  static void writeAPICallPrefixToJSON(
376  UT_JSONWriter &writer,
377  const char *api_function);
378  static void writeAPICallSuffixToJSON(
379  UT_JSONWriter &writer,
380  const UT_VariantMap &kwargs);
381 };
382 
383 template <typename... Args>
384 inline NET_HTTPResponse
385 NEThttpGet(const UT_Url& url, Args &&... args)
386 {
387  NET_NetSession session;
388  return session.get(url, std::forward<Args>(args)...);
389 }
390 template <typename... Args>
391 inline NET_HTTPResponse
392 NEThttpPost(const UT_Url& url, Args &&... args)
393 {
394  NET_NetSession session;
395  return session.post(url, std::forward<Args>(args)...);
396 }
397 
398 //---------------------------------------------------------------------------
399 
400 namespace NET
401 {
402 namespace details
403 {
404 // Detect the last type in the variadic args.
405 template <std::size_t Count, class... Args>
407 {
408  using type =
409  typename std::tuple_element<Count - 1, std::tuple<Args...>>::type;
410 };
411 
412 template <class... Args>
413 struct detect_last<0, Args...>
414 {
415  using type = void;
416 };
417 } // namespace details
418 } // namespace NET
419 
420 template <typename... Args>
421 inline void
423  UT_WorkBuffer &api_call,
424  const char *api_function,
425  Args &&... args)
426 {
427  namespace cvt = NET_ConvertToType;
428 
429  constexpr std::size_t arg_size = sizeof...(Args);
430  constexpr bool has_kwargs = std::is_same<
433  arg_size, Args...>::type>>::value;
434 
435  UT_UniquePtr<UT_JSONWriter> json_writer(NETcreateJSONWriter(api_call));
436 
437  writeAPICallPrefixToJSON(*json_writer, api_function);
438  // When we switch to c++17 switch this to check if the number of elements is
439  // > 0 so we don't need the no-op function (needs constexpr if)
440  webCall(*json_writer, std::forward<Args>(args)...);
441  // If the last type is not kwargs then write out the end of our request.
442  if (!has_kwargs)
443  {
444  // Write out the suffix of our request ']{}]'
445  json_writer->jsonEndArray();
446  json_writer->jsonBeginMap();
447  json_writer->jsonEndMap();
448  json_writer->jsonEndArray();
449  }
450 }
451 
452 template <typename... Args>
454  const char *function_name,
455  Args &&... args)
456 {
457  UT_WorkBuffer wbuf;
458  NET_WebAPI::buildApiCall(wbuf, function_name, std::forward<Args>(args)...);
459 
460  UT_StringView view(wbuf.begin(), wbuf.end());
462  result.format("json={}", NET_WebAPI::encodeUri(view));
463 
464  result.stealIntoStringHolder(myData);
465 }
466 
467 #endif
vint4 max(const vint4 &a, const vint4 &b)
Definition: simd.h:4703
GLuint const GLchar * name
Definition: glew.h:1814
UT_StringHolder myBody
Definition: NET_WebAPI.h:73
const Args & args
Definition: printf.h:628
GT_API const UT_StringHolder time
static NET_WebAPIResponse call(NET_WebSocketSPtr ws, std::chrono::milliseconds timeout, const char *api_function, Args &&...args)
Definition: NET_WebAPI.h:283
internal::named_arg< T, char > arg(string_view name, const T &arg)
Definition: core.h:1393
NET_HTTPStatusCode myStatus
UT_DeepString myErrors
Definition: NET_WebAPI.h:142
typename NET_remove_cref< T >::type NET_remove_cref_t
This is a deprecated class used just for older code.
Definition: NET_WebAPI.h:133
NET_HTTPResponse post(T &&arg, Args &&...args)
Definition: NET_WebAPI.h:215
GLint limit
Definition: glew.h:12988
basic_writer< back_insert_range< internal::buffer > > writer
Definition: format.h:361
Class which writes ASCII or binary JSON streams.
Definition: UT_JSONWriter.h:34
NET_API UT_UniquePtr< UT_JSONWriter > NETcreateJSONWriter(UT_WorkBuffer &content)
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
Definition: UT_UniquePtr.h:33
double fpreal64
Definition: SYS_Types.h:201
NET_API void NETinitializeBackend()
NET_HTTPResponse NEThttpPost(const UT_Url &url, Args &&...args)
Definition: NET_WebAPI.h:392
A utility class to do read-only operations on a subset of an existing string.
Definition: UT_StringView.h:40
GLclampf f
Definition: glew.h:3499
Response object used by a client from a response by a server.
NET_KnownHeaders
Definition: NET_WebTypes.h:52
void setOptions(T &&arg, Args &&...args)
Definition: NET_WebAPI.h:165
SYS_FORCE_INLINE const char * end() const
SYS_FORCE_INLINE const char * begin() const
Iterator compatibility.
void
Definition: png.h:1083
NET_HTTPResponse NEThttpGet(const UT_Url &url, Args &&...args)
Definition: NET_WebAPI.h:385
Definition: UT_Url.h:22
NET_HTTPResponse post()
long long int64
Definition: SYS_Types.h:116
UT_StringHolder myData
int64 myConnectTimeout
Definition: NET_WebAPI.h:96
static NET_HTTPResponse call(const UT_Url &api_url, const char *api_function, Args &&...args)
Definition: NET_WebAPI.h:249
NET_WebAPIFunction()=default
GLuint GLuint GLsizei GLenum type
Definition: glew.h:1253
UT_StringHolder myBody
Definition: NET_WebAPI.h:67
void setOptions(T &&opt)
Definition: NET_WebAPI.h:160
UT_JSONValue myJSONResult
Definition: NET_WebAPI.h:141
static NET_HTTPResponse call(const UT_Url &api_url, const NET_WebMap &headers, const char *api_function, Args &&...args)
Definition: NET_WebAPI.h:260
GLenum func
Definition: glcorearb.h:782
NET_HTTPResponse get()
UT_StringHolder myCaInfo
Definition: NET_WebAPI.h:102
UT_StringHolder myData
Definition: NET_WebAPI.h:83
static UT_StringHolder encodeUri(const UT_StringView uri)
std::future< T > NET_Future
Definition: NET_WebSocket.h:44
typename std::tuple_element< Count-1, std::tuple< Args...>>::type type
Definition: NET_WebAPI.h:409
UT_StringHolder myProxy
Definition: NET_WebAPI.h:115
Class to store JSON objects as C++ objects.
Definition: UT_JSONValue.h:77
static NET_HTTPResponse call(NET_NetSession &session, const UT_Url &api_url, const char *api_function, Args &&...args)
Definition: NET_WebAPI.h:272
UT_Array< NET_NetworkCookie > myCookies
Definition: NET_WebAPI.h:89
const GLfloat * params
Definition: glew.h:1531
GLuint64EXT * result
Definition: glew.h:14007
GLbitfield GLuint64 timeout
Definition: glew.h:6605
UT_SharedPtr< NET_WebSocket > NET_WebSocketSPtr
GA_API const UT_StringHolder rest
GLsizei const GLfloat * value
Definition: glew.h:1849
static void buildApiCall(UT_WorkBuffer &func, const char *api_function, Args &&...args)
Definition: NET_WebAPI.h:422
static NET_Future< NET_WebAPIResponse > callAsync(NET_WebSocketSPtr ws, const char *api_function, Args &&...args)
Definition: NET_WebAPI.h:311
type
Definition: core.h:528
UT_StringHolder myCaPath
Definition: NET_WebAPI.h:103