1 /***********************************************************************************************************************************
2 HTTP Request
3 
4 Send a request to an HTTP server and get a response. The interface is natively asynchronous, i.e. httpRequestNew() sends a request
5 and httpRequestResponse() waits for a response. These can be called together for synchronous behavior or separately for asynchronous
6 behavior.
7 ***********************************************************************************************************************************/
8 #ifndef COMMON_IO_HTTP_REQUEST_H
9 #define COMMON_IO_HTTP_REQUEST_H
10 
11 /***********************************************************************************************************************************
12 Object type
13 ***********************************************************************************************************************************/
14 typedef struct HttpRequest HttpRequest;
15 
16 #include "common/io/http/header.h"
17 #include "common/io/http/query.h"
18 #include "common/io/http/response.h"
19 #include "common/type/object.h"
20 
21 /***********************************************************************************************************************************
22 HTTP Constants
23 ***********************************************************************************************************************************/
24 #define HTTP_VERSION                                                "HTTP/1.1"
25     STRING_DECLARE(HTTP_VERSION_STR);
26 #define HTTP_VERSION_10                                             "HTTP/1.0"
27     STRING_DECLARE(HTTP_VERSION_10_STR);
28 
29 #define HTTP_VERB_DELETE                                            "DELETE"
30     STRING_DECLARE(HTTP_VERB_DELETE_STR);
31 #define HTTP_VERB_GET                                               "GET"
32     STRING_DECLARE(HTTP_VERB_GET_STR);
33 #define HTTP_VERB_HEAD                                              "HEAD"
34     STRING_DECLARE(HTTP_VERB_HEAD_STR);
35 #define HTTP_VERB_POST                                              "POST"
36     STRING_DECLARE(HTTP_VERB_POST_STR);
37 #define HTTP_VERB_PUT                                               "PUT"
38     STRING_DECLARE(HTTP_VERB_PUT_STR);
39 
40 #define HTTP_HEADER_AUTHORIZATION                                   "authorization"
41     STRING_DECLARE(HTTP_HEADER_AUTHORIZATION_STR);
42 #define HTTP_HEADER_CONTENT_LENGTH                                  "content-length"
43     STRING_DECLARE(HTTP_HEADER_CONTENT_LENGTH_STR);
44 #define HTTP_HEADER_CONTENT_MD5                                     "content-md5"
45     STRING_DECLARE(HTTP_HEADER_CONTENT_MD5_STR);
46 #define HTTP_HEADER_CONTENT_RANGE                                   "content-range"
47     STRING_DECLARE(HTTP_HEADER_CONTENT_RANGE_STR);
48 #define HTTP_HEADER_CONTENT_TYPE                                    "content-type"
49     STRING_DECLARE(HTTP_HEADER_CONTENT_TYPE_STR);
50 #define HTTP_HEADER_CONTENT_TYPE_APP_FORM_URL                       "application/x-www-form-urlencoded"
51     STRING_DECLARE(HTTP_HEADER_CONTENT_TYPE_APP_FORM_URL_STR);
52 #define HTTP_HEADER_CONTENT_RANGE_BYTES                             "bytes"
53 #define HTTP_HEADER_DATE                                            "date"
54     STRING_DECLARE(HTTP_HEADER_DATE_STR);
55 #define HTTP_HEADER_ETAG                                            "etag"
56     STRING_DECLARE(HTTP_HEADER_ETAG_STR);
57 #define HTTP_HEADER_HOST                                            "host"
58     STRING_DECLARE(HTTP_HEADER_HOST_STR);
59 #define HTTP_HEADER_LAST_MODIFIED                                   "last-modified"
60     STRING_DECLARE(HTTP_HEADER_LAST_MODIFIED_STR);
61 
62 /***********************************************************************************************************************************
63 Constructors
64 ***********************************************************************************************************************************/
65 typedef struct HttpRequestNewParam
66 {
67     VAR_PARAM_HEADER;
68     const HttpQuery *query;
69     const HttpHeader *header;
70     const Buffer *content;
71 } HttpRequestNewParam;
72 
73 #define httpRequestNewP(client, verb, path, ...)                                                                                   \
74     httpRequestNew(client, verb, path, (HttpRequestNewParam){VAR_PARAM_INIT, __VA_ARGS__})
75 
76 HttpRequest *httpRequestNew(HttpClient *client, const String *verb, const String *path, HttpRequestNewParam param);
77 
78 /***********************************************************************************************************************************
79 Getters/Setters
80 ***********************************************************************************************************************************/
81 typedef struct HttpRequestPub
82 {
83     MemContext *memContext;                                         // Mem context
84     const String *verb;                                             // HTTP verb (GET, POST, etc.)
85     const String *path;                                             // HTTP path
86     const HttpQuery *query;                                         // HTTP query
87     const HttpHeader *header;                                       // HTTP headers
88 } HttpRequestPub;
89 
90 // Request path
91 __attribute__((always_inline)) static inline const String *
httpRequestPath(const HttpRequest * const this)92 httpRequestPath(const HttpRequest *const this)
93 {
94     return THIS_PUB(HttpRequest)->path;
95 }
96 
97 // Request query
98 __attribute__((always_inline)) static inline const HttpQuery *
httpRequestQuery(const HttpRequest * const this)99 httpRequestQuery(const HttpRequest *const this)
100 {
101     return THIS_PUB(HttpRequest)->query;
102 }
103 
104 // Request headers
105 __attribute__((always_inline)) static inline const HttpHeader *
httpRequestHeader(const HttpRequest * const this)106 httpRequestHeader(const HttpRequest *const this)
107 {
108     return THIS_PUB(HttpRequest)->header;
109 }
110 
111 // Request verb
112 __attribute__((always_inline)) static inline const String *
httpRequestVerb(const HttpRequest * const this)113 httpRequestVerb(const HttpRequest *const this)
114 {
115     return THIS_PUB(HttpRequest)->verb;
116 }
117 
118 /***********************************************************************************************************************************
119 Functions
120 ***********************************************************************************************************************************/
121 // Wait for a response from the request
122 HttpResponse *httpRequestResponse(HttpRequest *this, bool contentCache);
123 
124 // Throw an error if the request failed
125 void httpRequestError(const HttpRequest *this, HttpResponse *response) __attribute__((__noreturn__));
126 
127 // Move to a new parent mem context
128 __attribute__((always_inline)) static inline HttpRequest *
httpRequestMove(HttpRequest * const this,MemContext * const parentNew)129 httpRequestMove(HttpRequest *const this, MemContext *const parentNew)
130 {
131     return objMove(this, parentNew);
132 }
133 
134 /***********************************************************************************************************************************
135 Destructor
136 ***********************************************************************************************************************************/
137 __attribute__((always_inline)) static inline void
httpRequestFree(HttpRequest * const this)138 httpRequestFree(HttpRequest *const this)
139 {
140     objFree(this);
141 }
142 
143 /***********************************************************************************************************************************
144 Macros for function logging
145 ***********************************************************************************************************************************/
146 String *httpRequestToLog(const HttpRequest *this);
147 
148 #define FUNCTION_LOG_HTTP_REQUEST_TYPE                                                                                            \
149     HttpRequest *
150 #define FUNCTION_LOG_HTTP_REQUEST_FORMAT(value, buffer, bufferSize)                                                               \
151     FUNCTION_LOG_STRING_OBJECT_FORMAT(value, httpRequestToLog, buffer, bufferSize)
152 
153 #endif
154