HomePort
httpd_request.c
Go to the documentation of this file.
1 /*
2  * Copyright 2011 Aalborg University. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification, are
5  * permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright notice, this list of
8  * conditions and the following disclaimer.
9  *
10  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11  * of conditions and the following disclaimer in the documentation and/or other materials
12  * provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY Aalborg University ''AS IS'' AND ANY EXPRESS OR IMPLIED
15  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Aalborg University OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  * The views and conclusions contained in the software and documentation are those of the
25  * authors and should not be interpreted as representing official policies, either expressed
26  */
27 
28 #include "httpd_request.h"
29 #include "http_parser.h"
30 #include "httpd_url_parser.h"
31 #include "httpd_header_parser.h"
32 #include "hpd/hpd_shared_api.h"
33 #include <string.h>
34 #include <stdlib.h>
35 
37 enum state {
48 };
49 
122 {
127  http_parser parser;
128  struct up *url_parser;
129  struct hp *header_parser;
130  enum state state;
131  char *url;
135  void* data;
137 };
138 
139 // Methods for http_parser settings
140 static int parser_msg_begin(http_parser *parser);
141 static int parser_url (http_parser *parser, const char *buf, size_t len);
142 static int parser_hdr_field(http_parser *parser, const char *buf, size_t len);
143 static int parser_hdr_value(http_parser *parser, const char *buf, size_t len);
144 static int parser_hdr_cmpl (http_parser *parser);
145 static int parser_body (http_parser *parser, const char *buf, size_t len);
146 static int parser_msg_cmpl (http_parser *parser);
147 
149 static http_parser_settings parser_settings =
150  {
151  .on_message_begin = parser_msg_begin,
152  .on_url = parser_url,
153  .on_status = NULL,
154  .on_header_field = parser_hdr_field,
155  .on_header_value = parser_hdr_value,
156  .on_headers_complete = parser_hdr_cmpl,
157  .on_body = parser_body,
158  .on_message_complete = parser_msg_cmpl
159  };
160 
171 static hpd_error_t url_parser_path_complete(void *data, const char* parsedSegment, size_t segment_length)
172 {
173  hpd_httpd_request_t *req = data;
174  char *newUrl = realloc(req->url, sizeof(char)*(segment_length+1));
175  if (!newUrl) HPD_LOG_RETURN_E_NULL(req->context);
176  req->url = newUrl;
177  strncpy(req->url, parsedSegment, segment_length);
178  req->url[segment_length] = '\0';
179 
180  return HPD_E_SUCCESS;
181 }
182 
195 static hpd_error_t url_parser_key_value(void *data, const char *key, size_t key_len, const char *value, size_t value_len)
196 {
197  hpd_httpd_request_t *req = data;
198  return hpd_map_set_n(req->arguments, key, key_len, value, value_len);
199 }
200 
216 static hpd_error_t header_parser_field_value_pair_complete(void* data, const char* field, size_t field_length, const char* value, size_t value_length)
217 {
218  hpd_error_t rc;
219  hpd_httpd_request_t *req = data;
220 
221  const char *existing;
222  switch ((rc = hpd_map_get_n(req->headers, field, field_length, &existing))) {
223  case HPD_E_SUCCESS:
224  case HPD_E_NOT_FOUND:
225  break;
226  default:
227  return rc;
228  }
229 
230  // If cookie, then store it in cookie list
231  if (strncmp(field, "Cookie", 6) == 0) {
232  size_t key_s = 0, key_e, val_s, val_e;
233 
234  while (key_s < value_length) {
235  for (key_e = key_s; key_e < value_length && value[key_e] != '='; key_e++);
236  if (key_e == value_length) HPD_LOG_RETURN(req->context, HPD_E_ARGUMENT, "Parse error.");
237  val_s = key_e + 1;
238  for (val_e = val_s; val_e < value_length && value[val_e] != ';'; val_e++);
239  if (key_e-key_s > 0 && val_e-val_s > 0) {
240  if ((rc = hpd_map_set_n(req->cookies, &value[key_s], (size_t) key_e - key_s, &value[val_s], val_e - val_s))) return rc;
241  } else {
242  HPD_LOG_RETURN(req->context, HPD_E_ARGUMENT, "Parse error.");
243  }
244  key_s = val_e + 2;
245  }
246  }
247 
248  // Store header in headers list
249  if (existing) {
250  // Combine values
251  size_t new_len = strlen(existing) + 1 + value_length + 1;
252  char *new = malloc(new_len * sizeof(char));
253  if (!new) HPD_LOG_RETURN_E_ALLOC(req->context);
254  strcpy(new, existing);
255  strcat(new, ",");
256  strncat(new, value, value_length);
257  new[new_len-1] = '\0';
258 
259  // Replace
260  rc = hpd_map_set_n(req->headers, field, field_length, new, new_len);
261 
262  // Clean up
263  free(new);
264 
265  if (rc) return rc;
266  } else {
267  if ((rc = hpd_map_set_n(req->headers, field, field_length, value, value_length))) return rc;
268  }
269 
270  return HPD_E_SUCCESS;
271 }
272 
284 static int parser_msg_begin(http_parser *parser)
285 {
286  hpd_httpd_return_t stat;
287  hpd_httpd_request_t *req = parser->data;
288  const hpd_httpd_settings_t *settings = req->settings;
289 
290  switch (req->state) {
291  case S_STOP:
292  return 1;
293  case S_START:
294  req->state = S_BEGIN;
295  // Send request begin
296  if(settings->on_req_begin && (stat = settings->on_req_begin(req->webserver, req, settings->httpd_ctx, &req->data))) {
297  req->state = S_STOP; return stat;
298  }
299 
300  return 0;
301  default:
302  HPD_LOG_ERROR(req->context, "Unexpected state.");
303  req->state = S_ERROR;
304  return 1;
305  }
306 }
307 
321 static int parser_url(http_parser *parser, const char *buf, size_t len)
322 {
323  hpd_error_t rc;
324  hpd_httpd_return_t stat;
325  hpd_httpd_request_t *req = parser->data;
327 
328  switch ((enum http_method) req->parser.method) {
329  case HTTP_GET:
330  req->method = HPD_HTTPD_M_GET;
331  break;
332  case HTTP_PUT:
333  req->method = HPD_HTTPD_M_PUT;
334  break;
335  case HTTP_OPTIONS:
337  break;
338  default:
340  break;
341  }
342 
343  switch (req->state) {
344  case S_STOP:
345  return 1;
346  case S_BEGIN:
347  req->state = S_URL;
348  case S_URL:
349  if ((rc = up_add_chunk(req->url_parser, buf, len))) {
350  HPD_LOG_ERROR(req->context, "URL parser failed (code: %d).", rc);
351  req->state = S_ERROR;
352  return 1;
353  }
354  if(settings->on_req_url && (stat = settings->on_req_url(req->webserver, req, settings->httpd_ctx, &req->data, buf, len))) {
355  req->state = S_STOP;
356  return stat;
357  }
358  return 0;
359  default:
360  HPD_LOG_ERROR(req->context, "Unexpected state.");
361  req->state = S_ERROR;
362  return 1;
363  }
364 }
365 
380 static int parser_hdr_field(http_parser *parser, const char *buf, size_t len)
381 {
382  hpd_error_t rc;
383  hpd_httpd_return_t stat;
384  hpd_httpd_request_t *req = parser->data;
386 
387  switch (req->state) {
388  case S_STOP:
389  return 1;
390  case S_URL:
391  if ((rc = up_complete(req->url_parser))) {
392  HPD_LOG_ERROR(req->context, "URL parser failed (code: %d).", rc);
393  req->state = S_ERROR;
394  return 1;
395  }
396  if(settings->on_req_url_cmpl && (stat = settings->on_req_url_cmpl(req->webserver, req, settings->httpd_ctx, &req->data))) {
397  req->state = S_STOP;
398  return stat;
399  }
400  case S_HEADER_VALUE:
401  req->state = S_HEADER_FIELD;
402  case S_HEADER_FIELD:
403  if ((rc = hp_on_header_field(req->header_parser, buf, len))) {
404  HPD_LOG_ERROR(req->context, "Header parser failed (code: %d).", rc);
405  req->state = S_ERROR;
406  return 1;
407  }
408  if(settings->on_req_hdr_field && (stat = settings->on_req_hdr_field(req->webserver, req, settings->httpd_ctx, &req->data, buf, len))) {
409  req->state = S_STOP;
410  return stat;
411  }
412  return 0;
413  default:
414  HPD_LOG_ERROR(req->context, "Unexpected state.");
415  req->state = S_ERROR;
416  return 1;
417  }
418 }
419 
433 static int parser_hdr_value(http_parser *parser, const char *buf, size_t len)
434 {
435  hpd_error_t rc;
436  hpd_httpd_return_t stat;
437  hpd_httpd_request_t *req = parser->data;
439 
440  switch (req->state) {
441  case S_STOP:
442  return 1;
443  case S_HEADER_FIELD:
444  req->state = S_HEADER_VALUE;
445  case S_HEADER_VALUE:
446  if ((rc = hp_on_header_value(req->header_parser, buf, len))) {
447  HPD_LOG_ERROR(req->context, "Header parser failed (code: %d).", rc);
448  req->state = S_ERROR;
449  return 1;
450  }
451  if(settings->on_req_hdr_value && (stat = settings->on_req_hdr_value(req->webserver, req, settings->httpd_ctx, &req->data, buf, len))) {
452  req->state = S_STOP;
453  return stat;
454  }
455  return 0;
456  default:
457  HPD_LOG_ERROR(req->context, "Unexpected state.");
458  req->state = S_ERROR;
459  return 1;
460  }
461 }
462 
476 static int parser_hdr_cmpl(http_parser *parser)
477 {
478  hpd_error_t rc;
479  hpd_httpd_return_t stat;
480  hpd_httpd_request_t *req = parser->data;
482 
483  switch (req->state) {
484  case S_STOP:
485  return 1;
486  case S_URL:
487  if ((rc = up_complete(req->url_parser))) {
488  HPD_LOG_ERROR(req->context, "Header parser failed (code: %d).", rc);
489  req->state = S_ERROR;
490  return 1;
491  }
492  if(settings->on_req_url_cmpl && (stat = settings->on_req_url_cmpl(req->webserver, req, settings->httpd_ctx, &req->data))){
493  req->state = S_STOP;
494  return stat;
495  }
496  case S_HEADER_VALUE:
497  if ((rc = hp_on_header_complete(req->header_parser))) {
498  HPD_LOG_ERROR(req->context, "Header parser failed (code: %d).", rc);
499  req->state = S_ERROR;
500  return 1;
501  }
502  req->state = S_HEADER_COMPLETE;
503  if(settings->on_req_hdr_cmpl && (stat = settings->on_req_hdr_cmpl(req->webserver, req, settings->httpd_ctx, &req->data))) {
504  req->state = S_STOP;
505  return stat;
506  }
507  return 0;
508  default:
509  HPD_LOG_ERROR(req->context, "Unexpected state.");
510  req->state = S_ERROR;
511  return 1;
512  }
513 }
514 
528 static int parser_body(http_parser *parser, const char *buf, size_t len)
529 {
530  hpd_httpd_return_t stat;
531  hpd_httpd_request_t *req = parser->data;
533 
534  switch (req->state) {
535  case S_STOP:
536  return 1;
537  case S_HEADER_COMPLETE:
538  req->state = S_BODY;
539  case S_BODY:
540  if (settings->on_req_body) {
541  stat = settings->on_req_body(req->webserver, req, settings->httpd_ctx, &req->data, buf, len);
542  if (stat) { req->state = S_STOP; return stat; }
543  }
544  return 0;
545  default:
546  HPD_LOG_ERROR(req->context, "Unexpected state.");
547  req->state = S_ERROR;
548  return 1;
549  }
550 }
551 
561 static int parser_msg_cmpl(http_parser *parser)
562 {
563  hpd_httpd_return_t stat;
564  hpd_httpd_request_t *req = parser->data;
566 
567  switch (req->state) {
568  case S_STOP:
569  return 1;
570  case S_HEADER_COMPLETE:
571  case S_BODY:
572  req->state = S_COMPLETE;
573  if(settings->on_req_cmpl && (stat = settings->on_req_cmpl(req->webserver, req, settings->httpd_ctx, &req->data))) {
574  req->state = S_STOP;
575  return stat;
576  }
577  return 0;
578  default:
579  HPD_LOG_ERROR(req->context, "Unexpected state.");
580  req->state = S_ERROR;
581  return 1;
582  }
583 }
584 
602  hpd_tcpd_conn_t *conn, const hpd_module_t *context)
603 {
604  if (!context) return HPD_E_NULL;
605  if (!req || !httpd || !settings || !conn) HPD_LOG_RETURN_E_NULL(context);
606 
607  hpd_error_t rc, rc2;
608 
609  (*req) = malloc(sizeof(hpd_httpd_request_t));
610  if(!(*req)) HPD_LOG_RETURN_E_ALLOC(context);
611 
612  // Init references
613  (*req)->context = context;
614  (*req)->webserver = httpd;
615  (*req)->conn = conn;
616  (*req)->settings = settings;
617 
618  // Init parser
619  http_parser_init(&((*req)->parser), HTTP_REQUEST);
620  (*req)->parser.data = (*req);
621  (*req)->state = S_START;
622 
623  // Init URL Parser
624  struct up_settings up_settings = UP_SETTINGS_DEFAULT;
626  up_settings.on_key_value = url_parser_key_value;
627  if ((rc = up_create(&(*req)->url_parser, &up_settings, context, (*req)))) goto error;
628 
629  // Init Header Parser
630  struct hp_settings hp_settings = HP_SETTINGS_DEFAULT;
631  hp_settings.data = (*req);
633  if ((rc = hp_create(&(*req)->header_parser, &hp_settings, context))) goto error;
634 
635  // Create linked maps
636  if ((rc = hpd_map_alloc(&(*req)->arguments))) goto error;
637  if ((rc = hpd_map_alloc(&(*req)->headers))) goto error;
638  if ((rc = hpd_map_alloc(&(*req)->cookies))) goto error;
639 
640  // Other field to init
641  (*req)->url = NULL;
642  (*req)->data = NULL;
643 
644  return HPD_E_SUCCESS;
645 
646  error:
647  if ((rc2 = http_request_destroy(*req)))
648  HPD_LOG_ERROR(context, "Failed to destroy request (code: %d)\n", rc2);
649  return rc;
650 }
651 
661 {
662  if (!req) return HPD_E_NULL;
663 
664  hpd_error_t rc = HPD_E_SUCCESS, tmp;
665 
666  // Call callback
668  if (settings->on_req_destroy)
669  settings->on_req_destroy(req->webserver, req, settings->httpd_ctx, &req->data);
670 
671  // Free request
672  if ((tmp = up_destroy(req->url_parser)) && !rc) rc = tmp;
673  if ((tmp = hpd_map_free(req->arguments)) && !rc) rc = tmp;
674  if ((tmp = hpd_map_free(req->headers)) && !rc) rc = tmp;
675  if ((tmp = hpd_map_free(req->cookies)) && !rc) rc = tmp;
676  if ((tmp = hp_destroy(req->header_parser)) && !rc) rc = tmp;
677  free(req->url);
678  free(req);
679 
680  return rc;
681 }
682 
697 hpd_error_t http_request_parse(hpd_httpd_request_t *req, const char *buf, size_t len)
698 {
699  size_t read = http_parser_execute(&req->parser, &parser_settings, buf, len);
700 
701  enum http_errno err = HTTP_PARSER_ERRNO(&req->parser);
702 
703  switch (err) {
704  case HPE_OK:
705  break;
706  case HPE_CB_message_begin:
707  case HPE_CB_url:
708  case HPE_CB_header_field:
709  case HPE_CB_header_value:
710  case HPE_CB_headers_complete:
711  case HPE_CB_body:
712  case HPE_CB_message_complete:
713  case HPE_CB_status:
714  case HPE_CB_chunk_header:
715  case HPE_CB_chunk_complete:
716  if (req->state == S_STOP) break;
717  case HPE_INVALID_EOF_STATE:
718  case HPE_HEADER_OVERFLOW:
719  case HPE_CLOSED_CONNECTION:
720  case HPE_INVALID_VERSION:
721  case HPE_INVALID_STATUS:
722  case HPE_INVALID_METHOD:
723  case HPE_INVALID_URL:
724  case HPE_INVALID_HOST:
725  case HPE_INVALID_PORT:
726  case HPE_INVALID_PATH:
727  case HPE_INVALID_QUERY_STRING:
728  case HPE_INVALID_FRAGMENT:
729  case HPE_LF_EXPECTED:
730  case HPE_INVALID_HEADER_TOKEN:
731  case HPE_INVALID_CONTENT_LENGTH:
732  case HPE_UNEXPECTED_CONTENT_LENGTH:
733  case HPE_INVALID_CHUNK_SIZE:
734  case HPE_INVALID_CONSTANT:
735  case HPE_INVALID_INTERNAL_STATE:
736  case HPE_STRICT:
737  case HPE_PAUSED:
738  case HPE_UNKNOWN:
739  HPD_LOG_RETURN(req->context, HPD_E_ARGUMENT, "HTTP Parser failed with message: %s (code: %i).",
740  http_errno_description(err), err);
741  }
742 
743  if (read != len && req->state != S_STOP)
744  HPD_LOG_RETURN(req->context, HPD_E_STATE, "Unexpected state.");
745 
746  if (req->parser.upgrade)
747  HPD_LOG_RETURN(req->context, HPD_E_ARGUMENT, "Do not support HTTP upgrade messages.");
748 
749  return HPD_E_SUCCESS;
750 }
751 
760 {
761  if (!req) return HPD_E_NULL;
762  if (!method) HPD_LOG_RETURN_E_NULL(req->context);
763 
764  (*method) = req->method;
765  return HPD_E_SUCCESS;
766 }
767 
776 {
777  if (!req) return HPD_E_NULL;
778  if (!url) HPD_LOG_RETURN_E_NULL(req->context);
779 
780  (*url) = req->url;
781  return HPD_E_SUCCESS;
782 }
783 
792 {
793  if (!req) return HPD_E_NULL;
794  if (!headers) HPD_LOG_RETURN_E_NULL(req->context);
795 
796  (*headers) = req->headers;
797  return HPD_E_SUCCESS;
798 }
799 
810 {
811  if (!req) return HPD_E_NULL;
812  if (!key || !value) HPD_LOG_RETURN_E_NULL(req->context);
813 
814  return hpd_map_get(req->headers, key, value);
815 }
816 
825 {
826  if (!req) return HPD_E_NULL;
827  if (!arguments) HPD_LOG_RETURN_E_NULL(req->context);
828 
829  (*arguments) = req->arguments;
830  return HPD_E_SUCCESS;
831 }
832 
842 {
843  if (!req) return HPD_E_NULL;
844  if (!key || !val) HPD_LOG_RETURN_E_NULL(req->context);
845 
846  return hpd_map_get(req->arguments, key, val);
847 }
848 
857 {
858  if (!req) return HPD_E_NULL;
859  if (!cookies) HPD_LOG_RETURN_E_NULL(req->context);
860 
861  (*cookies) = req->cookies;
862  return HPD_E_SUCCESS;
863 }
864 
875 {
876  if (!req) return HPD_E_NULL;
877  if (!key || !val) HPD_LOG_RETURN_E_NULL(req->context);
878 
879  return hpd_map_get(req->cookies, key, val);
880 }
881 
890 {
891  if (!req) return HPD_E_NULL;
892  if (!conn) HPD_LOG_RETURN_E_NULL(req->context);
893 
894  (*conn) = req->conn;
895  return HPD_E_SUCCESS;
896 }
897 
906 {
907  if (!req) return HPD_E_NULL;
908  if (!ip) HPD_LOG_RETURN_E_NULL(req->context);
909 
910  return hpd_tcpd_conn_get_ip(req->conn, ip);
911 }
912 
925 {
926  if (!req) return HPD_E_NULL;
927 
928  return hpd_tcpd_conn_keep_open(req->conn);
929 }
930 
932 {
933  if (!req) return HPD_E_NULL;
934  if (!context) HPD_LOG_RETURN_E_NULL(req->context);
935 
936  (*context) = req->context;
937  return HPD_E_SUCCESS;
938 }
struct hp * header_parser
Header Parser.
hpd_error_t hp_on_header_field(struct hp *instance, const char *field_chunk, size_t length)
hpd_map_t * cookies
Cookie Pairs.
#define HPD_LOG_RETURN(CONTEXT, E, FMT,...)
hpd_error_t hp_destroy(struct hp *instance)
static hpd_error_t header_parser_field_value_pair_complete(void *data, const char *field, size_t field_length, const char *value, size_t value_length)
Callback for the header parser.
hpd_tcpd_conn_t * conn
Connection to client.
hpd_error_t hpd_httpd_request_get_method(hpd_httpd_request_t *req, hpd_httpd_method_t *method)
Get the method of the http request.
up_string_cb on_path_complete
hpd_httpd_data_f on_req_hdr_field
Definition: hpd_httpd.h:107
data field
An URL Parser instance.
data value
An error has happened.
Definition: httpd_request.c:47
hpd_error_t hpd_httpd_request_get_header(hpd_httpd_request_t *req, const char *key, const char **value)
Get a specific header of a request.
#define HP_SETTINGS_DEFAULT
static int parser_hdr_value(http_parser *parser, const char *buf, size_t len)
Header value callback for http_parser.
static int parser_hdr_field(http_parser *parser, const char *buf, size_t len)
Header field callback for http_parser.
static int parser_msg_cmpl(http_parser *parser)
Messages complete callback for http_parser.
hpd_error_t hpd_map_get_n(hpd_map_t *map, const char *k, size_t k_len, const char **v)
Definition: map.c:107
hpd_httpd_t * webserver
HTTP Webserver.
The initial state.
Definition: httpd_request.c:38
char * url
free(data.url)
hpd_error_t http_request_get_context(hpd_httpd_request_t *req, const hpd_module_t **context)
hpd_map_t * headers
Header Pairs.
hpd_error_t hpd_httpd_request_get_cookies(hpd_httpd_request_t *req, hpd_map_t **cookies)
Get a all cookies for a request.
hpd_error_t up_add_chunk(struct up *instance, const char *chunk, size_t len)
Parse a chunk of an URL.
static int parser_msg_begin(http_parser *parser)
Message begin callback for http_parser.
struct hp_settings settings
Message begun received.
Definition: httpd_request.c:39
hpd_error_t hpd_map_free(hpd_map_t *map)
Definition: map.c:79
Received all headers.
Definition: httpd_request.c:43
static hpd_error_t url_parser_path_complete(void *data, const char *parsedSegment, size_t segment_length)
Callback for URL parser.
hpd_error_t hpd_tcpd_conn_keep_open(hpd_tcpd_conn_t *conn)
Disable timeout on connection.
Definition: tcpd.c:479
hpd_httpd_settings_t * settings
Settings.
hpd_error_t hpd_tcpd_conn_get_ip(hpd_tcpd_conn_t *conn, const char **ip)
Get the IP address of the client.
Definition: tcpd.c:459
An http request.
hpd_error_t http_request_get_connection(hpd_httpd_request_t *req, hpd_tcpd_conn_t **conn)
Get the connection of a request.
Received all of message.
Definition: httpd_request.c:45
hpd_error_t hpd_httpd_request_get_url(hpd_httpd_request_t *req, const char **url)
Get the URL of this request.
hpd_error_t hpd_httpd_request_get_cookie(hpd_httpd_request_t *req, const char *key, const char **val)
Get a specific cookie for a request.
hpd_error_t hpd_map_set_n(hpd_map_t *map, const char *k, size_t k_len, const char *v, size_t v_len)
Definition: map.c:195
#define UP_SETTINGS_DEFAULT
struct up * url_parser
URL Parser.
hpd_httpd_nodata_f on_req_url_cmpl
Definition: hpd_httpd.h:106
data key
hp_string_cb on_field_value_pair
enum state state
Current state.
hpd_error_t up_destroy(struct up *instance)
Destroy URL parser instance.
void * data
User data.
up_pair_cb on_key_value
enum hpd_error hpd_error_t
Definition: hpd_types.h:167
#define HPD_LOG_RETURN_E_ALLOC(CONTEXT)
hpd_httpd_nodata_f on_req_begin
Definition: hpd_httpd.h:104
hpd_error_t hpd_httpd_request_get_argument(hpd_httpd_request_t *req, const char *key, const char **val)
Get a specific argument of a request.
hpd_map_t * arguments
URL Arguments.
hpd_error_t http_request_destroy(hpd_httpd_request_t *req)
Destroy a ws_request.
#define HPD_LOG_RETURN_E_NULL(CONTEXT)
http_parser parser
HTTP parser.
hpd_httpd_method_t method
hpd_httpd_nodata_f on_req_hdr_cmpl
Definition: hpd_httpd.h:109
hpd_error_t hpd_httpd_request_keep_open(hpd_httpd_request_t *req)
Keep the connection for a request open.
hpd_error_t hpd_map_get(hpd_map_t *map, const char *k, const char **v)
Definition: map.c:92
All data to represent a connection.
Definition: tcpd_intern.h:56
struct data data
Settings struct for webserver.
Definition: hpd_httpd.h:100
hpd_error_t hp_create(struct hp **instance, struct hp_settings *settings, const hpd_module_t *context)
hpd_error_t http_request_create(hpd_httpd_request_t **req, hpd_httpd_t *httpd, hpd_httpd_settings_t *settings, hpd_tcpd_conn_t *conn, const hpd_module_t *context)
Create a new ws_request.
static int parser_url(http_parser *parser, const char *buf, size_t len)
URL callback for http_parser.
enum hpd_httpd_return hpd_httpd_return_t
Receiving body.
Definition: httpd_request.c:44
hpd_error_t up_complete(struct up *instance)
Informs the parser that the URL is complete.
static int parser_body(http_parser *parser, const char *buf, size_t len)
Body callback for http_parser.
hpd_error_t hpd_httpd_request_get_headers(hpd_httpd_request_t *req, hpd_map_t **headers)
Get a linked map of all headers for a request.
hpd_error_t hpd_map_alloc(hpd_map_t **map)
Definition: map.c:40
hpd_error_t http_request_parse(hpd_httpd_request_t *req, const char *buf, size_t len)
Parse a new chunk of the message.
hpd_httpd_nodata_f on_req_destroy
Definition: hpd_httpd.h:112
hpd_httpd_nodata_f on_req_cmpl
Definition: hpd_httpd.h:111
httpd instance struct
Definition: httpd.c:38
state
The possible states of a request.
Definition: httpd_request.c:37
const hpd_module_t * context
Receiving a header field.
Definition: httpd_request.c:41
hpd_error_t hpd_httpd_request_get_arguments(hpd_httpd_request_t *req, hpd_map_t **arguments)
Get a linked map of all URL arguements for a request.
Settings struct for the URL Parser.
hpd_error_t hp_on_header_complete(struct hp *instance)
Callback requested a stop.
Definition: httpd_request.c:46
hpd_httpd_data_f on_req_body
Definition: hpd_httpd.h:110
static http_parser_settings parser_settings
Global settings for http_parser.
hpd_error_t up_create(struct up **instance, struct up_settings *settings, const hpd_module_t *context, void *data)
Create URL parser instance.
enum hpd_httpd_method hpd_httpd_method_t
Receiving a header value.
Definition: httpd_request.c:42
static int parser_hdr_cmpl(http_parser *parser)
Header complete callback for http_parser.
#define HPD_LOG_ERROR(CONTEXT, FMT,...)
hpd_error_t hpd_httpd_request_get_ip(hpd_httpd_request_t *req, const char **ip)
Get the IP of a request.
hpd_httpd_data_f on_req_url
Definition: hpd_httpd.h:105
hpd_httpd_data_f on_req_hdr_value
Definition: hpd_httpd.h:108
static hpd_error_t url_parser_key_value(void *data, const char *key, size_t key_len, const char *value, size_t value_len)
Callback for URL parser.
hpd_error_t hp_on_header_value(struct hp *instance, const char *value_chunk, size_t length)
struct hpd_map hpd_map_t
Definition: hpd_map.h:40
const hpd_module_t * context
Receiving URL.
Definition: httpd_request.c:40