Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
response.inl
Go to the documentation of this file.
1/* response.inl
2 *
3 * Bufferring for HTTP headers for HTTP response.
4 * This function are only intended to be used at the server side.
5 * Optional for HTTP/1.0 and HTTP/1.1, mandatory for HTTP/2.
6 *
7 * This file is part of the CivetWeb project.
8 */
9
10#if defined(NO_RESPONSE_BUFFERING) && defined(USE_HTTP2)
11#error "HTTP2 works only if NO_RESPONSE_BUFFERING is not set"
12#endif
13
14
15/* Internal function to free header list */
16static void
18{
19#if !defined(NO_RESPONSE_BUFFERING)
20 while (conn->response_info.num_headers > 0) {
21 conn->response_info.num_headers--;
22 mg_free((void *)conn->response_info
23 .http_headers[conn->response_info.num_headers]
24 .name);
25 conn->response_info.http_headers[conn->response_info.num_headers].name =
26 0;
27 mg_free((void *)conn->response_info
28 .http_headers[conn->response_info.num_headers]
29 .value);
30 conn->response_info.http_headers[conn->response_info.num_headers]
31 .value = 0;
32 }
33#else
34 (void)conn; /* Nothing to do */
35#endif
36}
37
38
39/* Send first line of HTTP/1.x response */
40static int
42{
43 const char *status_txt;
44 const char *http_version = conn->request_info.http_version;
45 int status_code = conn->status_code;
46
47 if ((status_code < 100) || (status_code > 999)) {
48 /* Set invalid status code to "500 Internal Server Error" */
49 status_code = 500;
50 }
51 if (!http_version) {
52 http_version = "1.0";
53 }
54
55 /* mg_get_response_code_text will never return NULL */
57
58 if (mg_printf(
59 conn, "HTTP/%s %i %s\r\n", http_version, status_code, status_txt)
60 < 10) {
61 /* Network sending failed */
62 return 0;
63 }
64 return 1;
65}
66
67
68/* Initialize a new HTTP response
69 * Parameters:
70 * conn: Current connection handle.
71 * status: HTTP status code (e.g., 200 for "OK").
72 * Return:
73 * 0: ok
74 * -1: parameter error
75 * -2: invalid connection type
76 * -3: invalid connection status
77 * -4: network error (only if built with NO_RESPONSE_BUFFERING)
78 */
79int
80mg_response_header_start(struct mg_connection *conn, int status)
81{
82 int ret = 0;
83 if ((conn == NULL) || (status < 100) || (status > 999)) {
84 /* Parameter error */
85 return -1;
86 }
89 /* Only allowed in server context */
90 return -2;
91 }
92 if (conn->request_state != 0) {
93 /* only allowed if nothing was sent up to now */
94 return -3;
95 }
96 conn->status_code = status;
97 conn->request_state = 1;
98
99 /* Buffered response is stored, unbuffered response will be sent directly,
100 * but we can only send HTTP/1.x response here */
101#if !defined(NO_RESPONSE_BUFFERING)
103#else
105 ret = -4;
106 };
107 conn->request_state = 1; /* Reset from 10 to 1 */
108#endif
109
110 return ret;
111}
112
113
114/* Add a new HTTP response header line
115 * Parameters:
116 * conn: Current connection handle.
117 * header: Header name.
118 * value: Header value.
119 * value_len: Length of header value, excluding the terminating zero.
120 * Use -1 for "strlen(value)".
121 * Return:
122 * 0: ok
123 * -1: parameter error
124 * -2: invalid connection type
125 * -3: invalid connection status
126 * -4: too many headers
127 * -5: out of memory
128 */
129int
131 const char *header,
132 const char *value,
133 int value_len)
134{
135#if !defined(NO_RESPONSE_BUFFERING)
136 int hidx;
137#endif
138
139 if ((conn == NULL) || (header == NULL) || (value == NULL)) {
140 /* Parameter error */
141 return -1;
142 }
145 /* Only allowed in server context */
146 return -2;
147 }
148 if (conn->request_state != 1) {
149 /* only allowed if mg_response_header_start has been called before */
150 return -3;
151 }
152
153#if !defined(NO_RESPONSE_BUFFERING)
154 hidx = conn->response_info.num_headers;
155 if (hidx >= MG_MAX_HEADERS) {
156 /* Too many headers */
157 return -4;
158 }
159
160 /* Alloc new element */
161 conn->response_info.http_headers[hidx].name =
162 mg_strdup_ctx(header, conn->phys_ctx);
163 if (value_len >= 0) {
164 char *hbuf =
165 (char *)mg_malloc_ctx((unsigned)value_len + 1, conn->phys_ctx);
166 if (hbuf) {
167 memcpy(hbuf, value, (unsigned)value_len);
168 hbuf[value_len] = 0;
169 }
170 conn->response_info.http_headers[hidx].value = hbuf;
171 } else {
172 conn->response_info.http_headers[hidx].value =
174 }
175
176 if ((conn->response_info.http_headers[hidx].name == 0)
177 || (conn->response_info.http_headers[hidx].value == 0)) {
178 /* Out of memory */
179 mg_free((void *)conn->response_info.http_headers[hidx].name);
180 conn->response_info.http_headers[hidx].name = 0;
181 mg_free((void *)conn->response_info.http_headers[hidx].value);
182 conn->response_info.http_headers[hidx].value = 0;
183 return -5;
184 }
185
186 /* OK, header stored */
187 conn->response_info.num_headers++;
188
189#else
190 if (value_len >= 0) {
191 mg_printf(conn, "%s: %.*s\r\n", header, (int)value_len, value);
192 } else {
193 mg_printf(conn, "%s: %s\r\n", header, value);
194 }
195 conn->request_state = 1; /* Reset from 10 to 1 */
196#endif
197
198 return 0;
199}
200
201
202/* forward */
203static int parse_http_headers(char **buf, struct mg_header hdr[MG_MAX_HEADERS]);
204
205
206/* Add a complete header string (key + value).
207 * Parameters:
208 * conn: Current connection handle.
209 * http1_headers: Header line(s) in the form "name: value".
210 * Return:
211 * >=0: no error, number of header lines added
212 * -1: parameter error
213 * -2: invalid connection type
214 * -3: invalid connection status
215 * -4: too many headers
216 * -5: out of memory
217 */
218int
220 const char *http1_headers)
221{
223 int num_hdr, i, ret;
224 char *workbuffer, *parse;
225
226 /* We need to work on a copy of the work buffer, sice parse_http_headers
227 * will modify */
229 if (!workbuffer) {
230 /* Out of memory */
231 return -5;
232 }
233
234 /* Call existing method to split header buffer */
235 parse = workbuffer;
237 ret = num_hdr;
238
239 for (i = 0; i < num_hdr; i++) {
240 int lret =
242 if ((ret > 0) && (lret < 0)) {
243 /* Store error return value */
244 ret = lret;
245 }
246 }
247
248 /* mg_response_header_add created a copy, so we can free the original */
250 return ret;
251}
252
253
254#if defined(USE_HTTP2)
255static int http2_send_response_headers(struct mg_connection *conn);
256#endif
257
258
259/* Send http response
260 * Parameters:
261 * conn: Current connection handle.
262 * Return:
263 * 0: ok
264 * -1: parameter error
265 * -2: invalid connection type
266 * -3: invalid connection status
267 * -4: network send failed
268 */
269int
271{
272#if !defined(NO_RESPONSE_BUFFERING)
273 int i;
274 int has_date = 0;
275 int has_connection = 0;
276#endif
277
278 if (conn == NULL) {
279 /* Parameter error */
280 return -1;
281 }
284 /* Only allowed in server context */
285 return -2;
286 }
287 if (conn->request_state != 1) {
288 /* only allowed if mg_response_header_start has been called before */
289 return -3;
290 }
291
292 /* State: 2 */
293 conn->request_state = 2;
294
295#if !defined(NO_RESPONSE_BUFFERING)
296#if defined(USE_HTTP2)
297 if (conn->protocol_type == PROTOCOL_TYPE_HTTP2) {
300 return (ret ? 0 : -4);
301 }
302#endif
303
304 /* Send */
307 return -4;
308 };
309 for (i = 0; i < conn->response_info.num_headers; i++) {
310 mg_printf(conn,
311 "%s: %s\r\n",
312 conn->response_info.http_headers[i].name,
313 conn->response_info.http_headers[i].value);
314
315 /* Check for some special headers */
316 if (!mg_strcasecmp("Date", conn->response_info.http_headers[i].name)) {
317 has_date = 1;
318 }
319 if (!mg_strcasecmp("Connection",
320 conn->response_info.http_headers[i].name)) {
321 has_connection = 1;
322 }
323 }
324
325 if (!has_date) {
326 time_t curtime = time(NULL);
327 char date[64];
328 gmt_time_string(date, sizeof(date), &curtime);
329 mg_printf(conn, "Date: %s\r\n", date);
330 }
331 if (!has_connection) {
332 mg_printf(conn, "Connection: %s\r\n", suggest_connection_header(conn));
333 }
334#endif
335
336 mg_write(conn, "\r\n", 2);
337 conn->request_state = 3;
338
339 /* ok */
341 return 0;
342}
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
char name[80]
Definition TGX11.cxx:110
#define mg_malloc_ctx(a, c)
Definition civetweb.c:1532
@ PROTOCOL_TYPE_HTTP2
Definition civetweb.c:2541
@ PROTOCOL_TYPE_WEBSOCKET
Definition civetweb.c:2540
int mg_printf(struct mg_connection *conn, const char *fmt,...)
Definition civetweb.c:7255
const char * mg_get_response_code_text(const struct mg_connection *conn, int response_code)
Definition civetweb.c:4291
static void gmt_time_string(char *buf, size_t buf_len, time_t *t)
Definition civetweb.c:3415
int mg_write(struct mg_connection *conn, const void *buf, size_t len)
Definition civetweb.c:7000
static const char * suggest_connection_header(const struct mg_connection *conn)
Definition civetweb.c:4120
static char * mg_strdup_ctx(const char *str, struct mg_context *ctx)
Definition civetweb.c:3134
@ CONNECTION_TYPE_REQUEST
Definition civetweb.c:2534
int mg_strcasecmp(const char *s1, const char *s2)
Definition civetweb.c:3106
static __inline void mg_free(void *a)
Definition civetweb.c:1527
#define MG_MAX_HEADERS
Definition civetweb.h:141
int mg_response_header_add(struct mg_connection *conn, const char *header, const char *value, int value_len)
Definition response.inl:130
int mg_response_header_send(struct mg_connection *conn)
Definition response.inl:270
static int parse_http_headers(char **buf, struct mg_header hdr[MG_MAX_HEADERS])
int mg_response_header_add_lines(struct mg_connection *conn, const char *http1_headers)
Definition response.inl:219
static void free_buffered_response_header_list(struct mg_connection *conn)
Definition response.inl:17
int mg_response_header_start(struct mg_connection *conn, int status)
Definition response.inl:80
static int send_http1_response_status_line(struct mg_connection *conn)
Definition response.inl:41
int connection_type
Definition civetweb.c:2559
struct mg_response_info response_info
Definition civetweb.c:2568
struct mg_request_info request_info
Definition civetweb.c:2567
struct mg_context * phys_ctx
Definition civetweb.c:2570