1
0
mirror of https://gitlab.xiph.org/xiph/icecast-common.git synced 2024-11-03 04:17:20 -05:00

Feature: Added all known HTTP methods and improved API

This commit is contained in:
Philipp Schafft 2018-10-31 12:26:50 +00:00
parent 30632c2cc8
commit 1aa0a9977b
2 changed files with 239 additions and 112 deletions

View File

@ -59,63 +59,190 @@ static void _httpp_set_param_nocopy(igloo_avl_tree *tree, char *name, char *valu
static void _httpp_set_param(igloo_avl_tree *tree, const char *name, const char *value); static void _httpp_set_param(igloo_avl_tree *tree, const char *name, const char *value);
static igloo_http_var_t *igloo__httpp_get_param_var(igloo_avl_tree *tree, const char *name); static igloo_http_var_t *igloo__httpp_get_param_var(igloo_avl_tree *tree, const char *name);
static const struct http_method {
const char *name;
const igloo_httpp_request_type_e req;
const igloo_httpp_request_info_t info;
} igloo_httpp__methods[] = {
/* RFC 7231 */
{"GET", igloo_httpp_req_get,
igloo_HTTPP_REQUEST_IS_SAFE|igloo_HTTPP_REQUEST_IS_IDEMPOTENT|igloo_HTTPP_REQUEST_IS_CACHEABLE|igloo_HTTPP_REQUEST_HAS_RESPONSE_BODY|igloo_HTTPP_REQUEST_HAS_OPTIONAL_REQUEST_BODY
},
{"HEAD", igloo_httpp_req_head,
igloo_HTTPP_REQUEST_IS_SAFE|igloo_HTTPP_REQUEST_IS_IDEMPOTENT|igloo_HTTPP_REQUEST_IS_CACHEABLE
},
{"POST", igloo_httpp_req_post,
igloo_HTTPP_REQUEST_IS_CACHEABLE|igloo_HTTPP_REQUEST_HAS_RESPONSE_BODY|igloo_HTTPP_REQUEST_HAS_REQUEST_BODY
},
{"PUT", igloo_httpp_req_put,
igloo_HTTPP_REQUEST_IS_IDEMPOTENT|igloo_HTTPP_REQUEST_HAS_RESPONSE_BODY|igloo_HTTPP_REQUEST_HAS_REQUEST_BODY
},
{"DELETE", igloo_httpp_req_delete,
igloo_HTTPP_REQUEST_IS_IDEMPOTENT|igloo_HTTPP_REQUEST_HAS_RESPONSE_BODY
},
{"CONNECT", igloo_httpp_req_connect,
igloo_HTTPP_REQUEST_HAS_RESPONSE_BODY|igloo_HTTPP_REQUEST_HAS_REQUEST_BODY
},
{"OPTIONS", igloo_httpp_req_options,
igloo_HTTPP_REQUEST_IS_SAFE|igloo_HTTPP_REQUEST_IS_IDEMPOTENT|igloo_HTTPP_REQUEST_HAS_RESPONSE_BODY|igloo_HTTPP_REQUEST_HAS_OPTIONAL_REQUEST_BODY
},
{"TRACE", igloo_httpp_req_trace,
igloo_HTTPP_REQUEST_IS_SAFE|igloo_HTTPP_REQUEST_IS_IDEMPOTENT|igloo_HTTPP_REQUEST_HAS_RESPONSE_BODY
},
/* RFC 5789 */
{"PATCH", igloo_httpp_req_patch,
igloo_HTTPP_REQUEST_HAS_REQUEST_BODY|igloo_HTTPP_REQUEST_HAS_RESPONSE_BODY
},
/* Icecast specific */
{"SOURCE", igloo_httpp_req_source,
igloo_HTTPP_REQUEST_HAS_RESPONSE_BODY|igloo_HTTPP_REQUEST_HAS_REQUEST_BODY
},
{"PLAY", igloo_httpp_req_play,
igloo_HTTPP_REQUEST_IS_SAFE|igloo_HTTPP_REQUEST_HAS_RESPONSE_BODY|igloo_HTTPP_REQUEST_HAS_OPTIONAL_REQUEST_BODY
},
{"STATS", igloo_httpp_req_stats,
igloo_HTTPP_REQUEST_IS_SAFE|igloo_HTTPP_REQUEST_HAS_RESPONSE_BODY|igloo_HTTPP_REQUEST_HAS_OPTIONAL_REQUEST_BODY
},
/* Other RFCs */
/*
* tr -d \\r < www.iana.org/assignments/http-methods/methods.csv | while IFS=, read m s i r; do printf " {\"%-21s igloo_httpp_req_%s,\n /%c Safe: %s, Idempotent: %s, Reference: %s %c/\n igloo_HTTPP_REQUEST_INVALID\n },\n" "$m"\", $(tr A-Z- a-z_ <<<"$m") '*' "$s" "$i" "$r" '*'; done
*/
{"ACL", igloo_httpp_req_acl,
/* Safe: no, Idempotent: yes, Reference: "[RFC3744, Section 8.1]" */
igloo_HTTPP_REQUEST_INVALID
},
{"BASELINE-CONTROL", igloo_httpp_req_baseline_control,
/* Safe: no, Idempotent: yes, Reference: "[RFC3253, Section 12.6]" */
igloo_HTTPP_REQUEST_INVALID
},
{"BIND", igloo_httpp_req_bind,
/* Safe: no, Idempotent: yes, Reference: "[RFC5842, Section 4]" */
igloo_HTTPP_REQUEST_INVALID
},
{"CHECKIN", igloo_httpp_req_checkin,
/* Safe: no, Idempotent: yes, Reference: "[RFC3253, Section 4.4, Section 9.4]" */
igloo_HTTPP_REQUEST_INVALID
},
{"CHECKOUT", igloo_httpp_req_checkout,
/* Safe: no, Idempotent: yes, Reference: "[RFC3253, Section 4.3, Section 8.8]" */
igloo_HTTPP_REQUEST_INVALID
},
{"COPY", igloo_httpp_req_copy,
/* Safe: no, Idempotent: yes, Reference: "[RFC4918, Section 9.8]" */
igloo_HTTPP_REQUEST_INVALID
},
{"LABEL", igloo_httpp_req_label,
/* Safe: no, Idempotent: yes, Reference: "[RFC3253, Section 8.2]" */
igloo_HTTPP_REQUEST_INVALID
},
{"LINK", igloo_httpp_req_link,
/* Safe: no, Idempotent: yes, Reference: "[RFC2068, Section 19.6.1.2]" */
igloo_HTTPP_REQUEST_INVALID
},
{"LOCK", igloo_httpp_req_lock,
/* Safe: no, Idempotent: no, Reference: "[RFC4918, Section 9.10]" */
igloo_HTTPP_REQUEST_INVALID
},
{"MERGE", igloo_httpp_req_merge,
/* Safe: no, Idempotent: yes, Reference: "[RFC3253, Section 11.2]" */
igloo_HTTPP_REQUEST_INVALID
},
{"MKACTIVITY", igloo_httpp_req_mkactivity,
/* Safe: no, Idempotent: yes, Reference: "[RFC3253, Section 13.5]" */
igloo_HTTPP_REQUEST_INVALID
},
{"MKCALENDAR", igloo_httpp_req_mkcalendar,
/* Safe: no, Idempotent: yes, Reference: "[RFC4791, Section 5.3.1][RFC8144, Section 2.3]" */
igloo_HTTPP_REQUEST_INVALID
},
{"MKCOL", igloo_httpp_req_mkcol,
/* Safe: no, Idempotent: yes, Reference: "[RFC4918, Section 9.3][RFC5689, Section 3][RFC8144, Section 2.3]" */
igloo_HTTPP_REQUEST_INVALID
},
{"MKREDIRECTREF", igloo_httpp_req_mkredirectref,
/* Safe: no, Idempotent: yes, Reference: "[RFC4437, Section 6]" */
igloo_HTTPP_REQUEST_INVALID
},
{"MKWORKSPACE", igloo_httpp_req_mkworkspace,
/* Safe: no, Idempotent: yes, Reference: "[RFC3253, Section 6.3]" */
igloo_HTTPP_REQUEST_INVALID
},
{"MOVE", igloo_httpp_req_move,
/* Safe: no, Idempotent: yes, Reference: "[RFC4918, Section 9.9]" */
igloo_HTTPP_REQUEST_INVALID
},
{"ORDERPATCH", igloo_httpp_req_orderpatch,
/* Safe: no, Idempotent: yes, Reference: "[RFC3648, Section 7]" */
igloo_HTTPP_REQUEST_INVALID
},
{"PRI", igloo_httpp_req_pri,
/* Safe: yes, Idempotent: yes, Reference: "[RFC7540, Section 3.5]" */
igloo_HTTPP_REQUEST_INVALID
},
{"PROPFIND", igloo_httpp_req_propfind,
/* Safe: yes, Idempotent: yes, Reference: "[RFC4918, Section 9.1][RFC8144, Section 2.1]" */
igloo_HTTPP_REQUEST_INVALID
},
{"PROPPATCH", igloo_httpp_req_proppatch,
/* Safe: no, Idempotent: yes, Reference: "[RFC4918, Section 9.2][RFC8144, Section 2.2]" */
igloo_HTTPP_REQUEST_INVALID
},
{"REBIND", igloo_httpp_req_rebind,
/* Safe: no, Idempotent: yes, Reference: "[RFC5842, Section 6]" */
igloo_HTTPP_REQUEST_INVALID
},
{"REPORT", igloo_httpp_req_report,
/* Safe: yes, Idempotent: yes, Reference: "[RFC3253, Section 3.6][RFC8144, Section 2.1]" */
igloo_HTTPP_REQUEST_INVALID
},
{"SEARCH", igloo_httpp_req_search,
/* Safe: yes, Idempotent: yes, Reference: "[RFC5323, Section 2]" */
igloo_HTTPP_REQUEST_INVALID
},
{"UNBIND", igloo_httpp_req_unbind,
/* Safe: no, Idempotent: yes, Reference: "[RFC5842, Section 5]" */
igloo_HTTPP_REQUEST_INVALID
},
{"UNCHECKOUT", igloo_httpp_req_uncheckout,
/* Safe: no, Idempotent: yes, Reference: "[RFC3253, Section 4.5]" */
igloo_HTTPP_REQUEST_INVALID
},
{"UNLINK", igloo_httpp_req_unlink,
/* Safe: no, Idempotent: yes, Reference: "[RFC2068, Section 19.6.1.3]" */
igloo_HTTPP_REQUEST_INVALID
},
{"UNLOCK", igloo_httpp_req_unlock,
/* Safe: no, Idempotent: yes, Reference: "[RFC4918, Section 9.11]" */
igloo_HTTPP_REQUEST_INVALID
},
{"UPDATE", igloo_httpp_req_update,
/* Safe: no, Idempotent: yes, Reference: "[RFC3253, Section 7.1]" */
igloo_HTTPP_REQUEST_INVALID
},
{"UPDATEREDIRECTREF", igloo_httpp_req_updateredirectref,
/* Safe: no, Idempotent: yes, Reference: "[RFC4437, Section 7]" */
igloo_HTTPP_REQUEST_INVALID
},
{"VERSION-CONTROL", igloo_httpp_req_version_control,
/* Safe: no, Idempotent: yes, Reference: "[RFC3253, Section 3.5]" */
igloo_HTTPP_REQUEST_INVALID
},
};
igloo_httpp_request_info_t igloo_httpp_request_info(igloo_httpp_request_type_e req) igloo_httpp_request_info_t igloo_httpp_request_info(igloo_httpp_request_type_e req)
{ {
#if 0 size_t i;
#define igloo_HTTPP_REQUEST_IS_SAFE ((igloo_httpp_request_info_t)0x0001U)
#define igloo_HTTPP_REQUEST_IS_IDEMPOTENT ((igloo_httpp_request_info_t)0x0002U)
#define igloo_HTTPP_REQUEST_IS_CACHEABLE ((igloo_httpp_request_info_t)0x0004U)
#define igloo_HTTPP_REQUEST_HAS_RESPONSE_BODY ((igloo_httpp_request_info_t)0x0010U)
#define igloo_HTTPP_REQUEST_HAS_REQUEST_BODY ((igloo_httpp_request_info_t)0x0100U)
#define igloo_HTTPP_REQUEST_HAS_OPTIONAL_REQUEST_BODY ((igloo_httpp_request_info_t)0x0200U)
#endif
switch (req) {
/* offical methods */
case igloo_httpp_req_get:
return igloo_HTTPP_REQUEST_IS_SAFE|igloo_HTTPP_REQUEST_IS_IDEMPOTENT|igloo_HTTPP_REQUEST_IS_CACHEABLE|igloo_HTTPP_REQUEST_HAS_RESPONSE_BODY|igloo_HTTPP_REQUEST_HAS_OPTIONAL_REQUEST_BODY;
break;
case igloo_httpp_req_post:
return igloo_HTTPP_REQUEST_IS_CACHEABLE|igloo_HTTPP_REQUEST_HAS_RESPONSE_BODY|igloo_HTTPP_REQUEST_HAS_REQUEST_BODY;
break;
case igloo_httpp_req_put:
return igloo_HTTPP_REQUEST_IS_IDEMPOTENT|igloo_HTTPP_REQUEST_HAS_RESPONSE_BODY|igloo_HTTPP_REQUEST_HAS_REQUEST_BODY;
break;
case igloo_httpp_req_head:
return igloo_HTTPP_REQUEST_IS_SAFE|igloo_HTTPP_REQUEST_IS_IDEMPOTENT|igloo_HTTPP_REQUEST_IS_CACHEABLE;
break;
case igloo_httpp_req_options:
return igloo_HTTPP_REQUEST_IS_SAFE|igloo_HTTPP_REQUEST_IS_IDEMPOTENT|igloo_HTTPP_REQUEST_HAS_RESPONSE_BODY|igloo_HTTPP_REQUEST_HAS_OPTIONAL_REQUEST_BODY;
break;
case igloo_httpp_req_delete:
return igloo_HTTPP_REQUEST_IS_IDEMPOTENT|igloo_HTTPP_REQUEST_HAS_RESPONSE_BODY;
break;
case igloo_httpp_req_trace:
return igloo_HTTPP_REQUEST_IS_SAFE|igloo_HTTPP_REQUEST_IS_IDEMPOTENT|igloo_HTTPP_REQUEST_HAS_RESPONSE_BODY;
break;
case igloo_httpp_req_connect:
return igloo_HTTPP_REQUEST_HAS_RESPONSE_BODY|igloo_HTTPP_REQUEST_HAS_REQUEST_BODY;
break;
/* Icecast specific methods */ for (i = 0; i < (sizeof(igloo_httpp__methods)/sizeof(*igloo_httpp__methods)); i++) {
case igloo_httpp_req_source: if (igloo_httpp__methods[i].req == req) {
return igloo_HTTPP_REQUEST_HAS_RESPONSE_BODY|igloo_HTTPP_REQUEST_HAS_REQUEST_BODY; return igloo_httpp__methods[i].info;
break;
case igloo_httpp_req_play:
return igloo_HTTPP_REQUEST_IS_SAFE|igloo_HTTPP_REQUEST_HAS_RESPONSE_BODY|igloo_HTTPP_REQUEST_HAS_OPTIONAL_REQUEST_BODY;
break;
case igloo_httpp_req_stats:
return igloo_HTTPP_REQUEST_IS_SAFE|igloo_HTTPP_REQUEST_HAS_RESPONSE_BODY|igloo_HTTPP_REQUEST_HAS_OPTIONAL_REQUEST_BODY;
break;
/* Virtual and other methods */
case igloo_httpp_req_none:
case igloo_httpp_req_unknown:
default:
return igloo_HTTPP_REQUEST_HAS_RESPONSE_BODY|igloo_HTTPP_REQUEST_HAS_OPTIONAL_REQUEST_BODY;
break;
} }
} }
return igloo_HTTPP_REQUEST_INVALID;
}
igloo_http_parser_t *igloo_httpp_create_parser(void) igloo_http_parser_t *igloo_httpp_create_parser(void)
{ {
igloo_http_parser_t *parser = calloc(1, sizeof(igloo_http_parser_t)); igloo_http_parser_t *parser = calloc(1, sizeof(igloo_http_parser_t));
@ -495,42 +622,9 @@ int igloo_httpp_parse(igloo_http_parser_t *parser, const char *http_data, unsign
} }
if (parser->req_type != igloo_httpp_req_none && parser->req_type != igloo_httpp_req_unknown) { if (parser->req_type != igloo_httpp_req_none && parser->req_type != igloo_httpp_req_unknown) {
switch (parser->req_type) { const char *method = igloo_httpp_method_to_str(parser->req_type);
case igloo_httpp_req_get: if (method) {
igloo_httpp_setvar(parser, igloo_HTTPP_VAR_REQ_TYPE, "GET"); igloo_httpp_setvar(parser, igloo_HTTPP_VAR_REQ_TYPE, method);
break;
case igloo_httpp_req_post:
igloo_httpp_setvar(parser, igloo_HTTPP_VAR_REQ_TYPE, "POST");
break;
case igloo_httpp_req_put:
igloo_httpp_setvar(parser, igloo_HTTPP_VAR_REQ_TYPE, "PUT");
break;
case igloo_httpp_req_head:
igloo_httpp_setvar(parser, igloo_HTTPP_VAR_REQ_TYPE, "HEAD");
break;
case igloo_httpp_req_options:
igloo_httpp_setvar(parser, igloo_HTTPP_VAR_REQ_TYPE, "OPTIONS");
break;
case igloo_httpp_req_delete:
igloo_httpp_setvar(parser, igloo_HTTPP_VAR_REQ_TYPE, "DELETE");
break;
case igloo_httpp_req_trace:
igloo_httpp_setvar(parser, igloo_HTTPP_VAR_REQ_TYPE, "TRACE");
break;
case igloo_httpp_req_connect:
igloo_httpp_setvar(parser, igloo_HTTPP_VAR_REQ_TYPE, "CONNECT");
break;
case igloo_httpp_req_source:
igloo_httpp_setvar(parser, igloo_HTTPP_VAR_REQ_TYPE, "SOURCE");
break;
case igloo_httpp_req_play:
igloo_httpp_setvar(parser, igloo_HTTPP_VAR_REQ_TYPE, "PLAY");
break;
case igloo_httpp_req_stats:
igloo_httpp_setvar(parser, igloo_HTTPP_VAR_REQ_TYPE, "STATS");
break;
default:
break;
} }
} else { } else {
free(data); free(data);
@ -921,31 +1015,28 @@ static int igloo__free_vars(void *key)
return 1; return 1;
} }
igloo_httpp_request_type_e igloo_httpp_str_to_method(const char * method) { igloo_httpp_request_type_e igloo_httpp_str_to_method(const char * method)
if (strcasecmp("GET", method) == 0) { {
return igloo_httpp_req_get; size_t i;
} else if (strcasecmp("POST", method) == 0) {
return igloo_httpp_req_post; for (i = 0; i < (sizeof(igloo_httpp__methods)/sizeof(*igloo_httpp__methods)); i++) {
} else if (strcasecmp("PUT", method) == 0) { if (strcasecmp(igloo_httpp__methods[i].name, method) == 0) {
return igloo_httpp_req_put; return igloo_httpp__methods[i].req;
} else if (strcasecmp("HEAD", method) == 0) {
return igloo_httpp_req_head;
} else if (strcasecmp("OPTIONS", method) == 0) {
return igloo_httpp_req_options;
} else if (strcasecmp("DELETE", method) == 0) {
return igloo_httpp_req_delete;
} else if (strcasecmp("TRACE", method) == 0) {
return igloo_httpp_req_trace;
} else if (strcasecmp("CONNECT", method) == 0) {
return igloo_httpp_req_connect;
} else if (strcasecmp("SOURCE", method) == 0) {
return igloo_httpp_req_source;
} else if (strcasecmp("PLAY", method) == 0) {
return igloo_httpp_req_play;
} else if (strcasecmp("STATS", method) == 0) {
return igloo_httpp_req_stats;
} else {
return igloo_httpp_req_unknown;
} }
} }
return igloo_httpp_req_unknown;
}
const char * igloo_httpp_method_to_str(igloo_httpp_request_type_e method)
{
size_t i;
for (i = 0; i < (sizeof(igloo_httpp__methods)/sizeof(*igloo_httpp__methods)); i++) {
if (igloo_httpp__methods[i].req == method) {
return igloo_httpp__methods[i].name;
}
}
return NULL;
}

View File

@ -62,17 +62,52 @@ typedef enum httpp_request_type_tag {
igloo_httpp_req_delete, igloo_httpp_req_delete,
igloo_httpp_req_trace, igloo_httpp_req_trace,
igloo_httpp_req_connect, igloo_httpp_req_connect,
igloo_httpp_req_patch,
/* Icecast SOURCE, to be replaced with PUT some day */ /* Icecast SOURCE, to be replaced with PUT some day */
igloo_httpp_req_source, igloo_httpp_req_source,
/* XXX: ??? */ /* XXX: ??? */
igloo_httpp_req_play, igloo_httpp_req_play,
/* Icecast 2.x STATS, to request a live stream of stats events */ /* Icecast 2.x STATS, to request a live stream of stats events */
igloo_httpp_req_stats, igloo_httpp_req_stats,
/* Other:
* Source: https://www.iana.org/assignments/http-methods/methods.csv, 2018-10-31
*/
igloo_httpp_req_acl,
igloo_httpp_req_baseline_control,
igloo_httpp_req_bind,
igloo_httpp_req_checkin,
igloo_httpp_req_checkout,
igloo_httpp_req_copy,
igloo_httpp_req_label,
igloo_httpp_req_link,
igloo_httpp_req_lock,
igloo_httpp_req_merge,
igloo_httpp_req_mkactivity,
igloo_httpp_req_mkcalendar,
igloo_httpp_req_mkcol,
igloo_httpp_req_mkredirectref,
igloo_httpp_req_mkworkspace,
igloo_httpp_req_move,
igloo_httpp_req_orderpatch,
igloo_httpp_req_pri,
igloo_httpp_req_propfind,
igloo_httpp_req_proppatch,
igloo_httpp_req_rebind,
igloo_httpp_req_report,
igloo_httpp_req_search,
igloo_httpp_req_unbind,
igloo_httpp_req_uncheckout,
igloo_httpp_req_unlink,
igloo_httpp_req_unlock,
igloo_httpp_req_update,
igloo_httpp_req_updateredirectref,
igloo_httpp_req_version_control,
/* Used if request method is unknown. MUST BE LAST ONE IN LIST. */ /* Used if request method is unknown. MUST BE LAST ONE IN LIST. */
igloo_httpp_req_unknown igloo_httpp_req_unknown
} igloo_httpp_request_type_e; } igloo_httpp_request_type_e;
typedef unsigned int igloo_httpp_request_info_t; typedef unsigned int igloo_httpp_request_info_t;
#define igloo_HTTPP_REQUEST_INVALID ((igloo_httpp_request_info_t)0x1000U)
#define igloo_HTTPP_REQUEST_IS_SAFE ((igloo_httpp_request_info_t)0x0001U) #define igloo_HTTPP_REQUEST_IS_SAFE ((igloo_httpp_request_info_t)0x0001U)
#define igloo_HTTPP_REQUEST_IS_IDEMPOTENT ((igloo_httpp_request_info_t)0x0002U) #define igloo_HTTPP_REQUEST_IS_IDEMPOTENT ((igloo_httpp_request_info_t)0x0002U)
#define igloo_HTTPP_REQUEST_IS_CACHEABLE ((igloo_httpp_request_info_t)0x0004U) #define igloo_HTTPP_REQUEST_IS_CACHEABLE ((igloo_httpp_request_info_t)0x0004U)
@ -127,6 +162,7 @@ int igloo_httpp_release(igloo_http_parser_t *parser);
/* util functions */ /* util functions */
igloo_httpp_request_type_e igloo_httpp_str_to_method(const char * method); igloo_httpp_request_type_e igloo_httpp_str_to_method(const char * method);
const char * igloo_httpp_method_to_str(igloo_httpp_request_type_e method);
#ifdef __cplusplus #ifdef __cplusplus
} }