From 490591ca328555f9d493f3fc4d676264c73e8dd9 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Mon, 6 Mar 2023 00:40:29 +0900 Subject: [PATCH] added hio_parse_http_status_header_value() --- lib/hio-htre.h | 6 ++++++ lib/hio-http.h | 6 ++++++ lib/http-cgi.c | 45 +++-------------------------------------- lib/http-fcgi.c | 45 +++-------------------------------------- lib/http-file.c | 5 ++++- lib/http-svr.c | 7 ++++--- lib/http.c | 53 +++++++++++++++++++++++++++++++++++++++++++------ 7 files changed, 73 insertions(+), 94 deletions(-) diff --git a/lib/hio-htre.h b/lib/hio-htre.h index 0ae1782..769498b 100644 --- a/lib/hio-htre.h +++ b/lib/hio-htre.h @@ -110,12 +110,18 @@ enum hio_http_status_t HIO_HTTP_STATUS_MOVED_PERMANENTLY = 301, HIO_HTTP_STATUS_MOVED_TEMPORARILY = 302, HIO_HTTP_STATUS_NOT_MODIFIED = 304, + HIO_HTTP_STATUS_TEMPORARY_REDIRECT = 307, + HIO_HTTP_STATUS_PERMANENT_REDIRECT = 308, HIO_HTTP_STATUS_BAD_REQUEST = 400, HIO_HTTP_STATUS_UNAUTHORIZED = 401, + HIO_HTTP_STATUS_PAYMENT_REQUIRED = 402, HIO_HTTP_STATUS_FORBIDDEN = 403, HIO_HTTP_STATUS_NOT_FOUND = 404, HIO_HTTP_STATUS_METHOD_NOT_ALLOWED = 405, + HIO_HTTP_STATUS_NOT_ACCEPTABLE = 406, + HIO_HTTP_STATUS_PROXY_AUTH_REQUIRED = 407, + HIO_HTTP_STATUS_REQUEST_TIMEOUT = 408, HIO_HTTP_STATUS_LENGTH_REQUIRED = 411, HIO_HTTP_STATUS_RANGE_NOT_SATISFIABLE = 416, HIO_HTTP_STATUS_EXPECTATION_FAILED = 417, diff --git a/lib/hio-http.h b/lib/hio-http.h index 285b055..b126495 100644 --- a/lib/hio-http.h +++ b/lib/hio-http.h @@ -358,6 +358,12 @@ HIO_EXPORT hio_oow_t hio_escape_html_bcstr ( hio_oow_t len ); +HIO_EXPORT int hio_parse_http_status_header_value ( + const hio_bch_t* status_value, /* value of the Status header */ + int* status_code, /* [OUT] parsed status code*/ + const hio_bch_t** status_desc /* [OUT] parsed status description - HIO_NULL if omitted in the value */ +); + /* ------------------------------------------------------------------------- */ /* HTTP SERVER SERVICE */ /* ------------------------------------------------------------------------- */ diff --git a/lib/http-cgi.c b/lib/http-cgi.c index dafd2f1..145b555 100644 --- a/lib/http-cgi.c +++ b/lib/http-cgi.c @@ -533,7 +533,7 @@ static int peer_htrd_peek (hio_htrd_t* htrd, hio_htre_t* req) hio_svc_htts_cli_t* cli = cgi->task_client; hio_bch_t dtbuf[64]; int status_code = HIO_HTTP_STATUS_OK; - const hio_bch_t* status_line = HIO_NULL; + const hio_bch_t* status_desc = HIO_NULL; if (req->attr.content_length) { @@ -541,53 +541,14 @@ static int peer_htrd_peek (hio_htrd_t* htrd, hio_htre_t* req) cgi->res_mode_to_cli = CGI_RES_MODE_LENGTH; } - if (req->attr.status) - { - int is_sober; - const hio_bch_t* begptr, * endptr; - hio_intmax_t v; - hio_oow_t code_len; - hio_oow_t desc_len; - - endptr = req->attr.status; - while (hio_is_bch_space(*endptr)) endptr++; - begptr = endptr; - while (hio_is_bch_digit(*endptr)) endptr++; - code_len = endptr - begptr; - - while (hio_is_bch_space(*endptr)) endptr++; - begptr = endptr; - while (*endptr != '\0') endptr++; - desc_len = endptr - begptr; - - /* the status line could be simply "Status: 302" or more verbose like "Status: 302 Moved" - * the value may contain more than numbers */ - if (code_len > 0 && desc_len > 0) - { - status_line = req->attr.status; - } - else - { - v = hio_bchars_to_intmax(req->attr.status, hio_count_bcstr(req->attr.status), HIO_BCHARS_TO_INTMAX_MAKE_OPTION(0,0,0,10), &endptr, &is_sober); - if (*endptr == '\0' && is_sober && v > 0 && v <= HIO_TYPE_MAX(int)) status_code = v; - } - } + if (req->attr.status) hio_parse_http_status_header_value(req->attr.status, &status_code, &status_desc); hio_svc_htts_fmtgmtime (cli->htts, HIO_NULL, dtbuf, HIO_COUNTOF(dtbuf)); if (hio_becs_fmt(cli->sbuf, "HTTP/%d.%d ", cgi->task_req_version.major, cgi->task_req_version.minor) == (hio_oow_t)-1) return -1; - if (status_line) - { - if (hio_becs_fcat(cli->sbuf, "%hs\r\n", status_line) == (hio_oow_t)-1) return -1; - } - else - { - if (hio_becs_fcat(cli->sbuf, "%d %hs\r\n", status_code, hio_http_status_to_bcstr(status_code)) == (hio_oow_t)-1) return -1; - } - + if (hio_becs_fcat(cli->sbuf, "%d %hs\r\n", status_code, (status_desc? status_desc: hio_http_status_to_bcstr(status_code))) == (hio_oow_t)-1) return -1; if (hio_becs_fcat(cli->sbuf, "Server: %hs\r\nDate: %hs\r\n", cli->htts->server_name, dtbuf) == (hio_oow_t)-1) return -1; - if (hio_htre_walkheaders(req, peer_capture_response_header, cli) <= -1) return -1; switch (cgi->res_mode_to_cli) diff --git a/lib/http-fcgi.c b/lib/http-fcgi.c index b123188..24fe57d 100644 --- a/lib/http-fcgi.c +++ b/lib/http-fcgi.c @@ -436,7 +436,7 @@ static int peer_htrd_peek (hio_htrd_t* htrd, hio_htre_t* req) hio_svc_htts_cli_t* cli = fcgi->task_client; hio_bch_t dtbuf[64]; int status_code = HIO_HTTP_STATUS_OK; - const hio_bch_t* status_line = HIO_NULL; + const hio_bch_t* status_desc = HIO_NULL; if (req->attr.content_length) { @@ -444,51 +444,12 @@ static int peer_htrd_peek (hio_htrd_t* htrd, hio_htre_t* req) fcgi->res_mode_to_cli = FCGI_RES_MODE_LENGTH; } - if (req->attr.status) - { - int is_sober; - const hio_bch_t* begptr, * endptr; - hio_intmax_t v; - hio_oow_t code_len; - hio_oow_t desc_len; - - endptr = req->attr.status; - while (hio_is_bch_space(*endptr)) endptr++; - begptr = endptr; - while (hio_is_bch_digit(*endptr)) endptr++; - code_len = endptr - begptr; - - while (hio_is_bch_space(*endptr)) endptr++; - begptr = endptr; - while (*endptr != '\0') endptr++; - desc_len = endptr - begptr; - - /* the status line could be simply "Status: 302" or more verbose like "Status: 302 Moved" - * the value may contain more than numbers */ - if (code_len > 0 && desc_len > 0) - { - /* use the whole line as it is - e.g. Status: 302 Moved*/ - status_line = req->attr.status; - } - else - { - v = hio_bchars_to_intmax(req->attr.status, hio_count_bcstr(req->attr.status), HIO_BCHARS_TO_INTMAX_MAKE_OPTION(0,0,0,10), &endptr, &is_sober); - if (*endptr == '\0' && is_sober && v > 0 && v <= HIO_TYPE_MAX(int)) status_code = v; - } - } + if (req->attr.status) hio_parse_http_status_header_value(req->attr.status, &status_code, &status_desc); hio_svc_htts_fmtgmtime (cli->htts, HIO_NULL, dtbuf, HIO_COUNTOF(dtbuf)); if (hio_becs_fmt(cli->sbuf, "HTTP/%d.%d ", fcgi->task_req_version.major, fcgi->task_req_version.minor) == (hio_oow_t)-1) return -1; - if (status_line) - { - if (hio_becs_fcat(cli->sbuf, "%hs\r\n", status_line) == (hio_oow_t)-1) return -1; - } - else - { - if (hio_becs_fcat(cli->sbuf, "%d %hs\r\n", status_code, hio_http_status_to_bcstr(status_code)) == (hio_oow_t)-1) return -1; - } - + if (hio_becs_fcat(cli->sbuf, "%d %hs\r\n", status_code, (status_desc? status_desc: hio_http_status_to_bcstr(status_code))) == (hio_oow_t)-1) return -1; if (hio_becs_fcat(cli->sbuf, "Server: %hs\r\nDate: %hs\r\n", cli->htts->server_name, dtbuf) == (hio_oow_t)-1) return -1; if (hio_htre_walkheaders(req, peer_capture_response_header, cli) <= -1) return -1; diff --git a/lib/http-file.c b/lib/http-file.c index 81cebda..f9828e7 100644 --- a/lib/http-file.c +++ b/lib/http-file.c @@ -158,7 +158,10 @@ static int file_send_final_status_to_client (file_t* file, int status_code, int status_msg = ""; } - if (status_code == HIO_HTTP_STATUS_MOVED_PERMANENTLY || status_code == HIO_HTTP_STATUS_MOVED_TEMPORARILY) + if (status_code == HIO_HTTP_STATUS_MOVED_PERMANENTLY || + status_code == HIO_HTTP_STATUS_MOVED_TEMPORARILY || + status_code == HIO_HTTP_STATUS_TEMPORARY_REDIRECT || + status_code == HIO_HTTP_STATUS_PERMANENT_REDIRECT) { /* don't send content body when the status code is 3xx. include the Location header only. */ if (hio_becs_fcat(cli->sbuf, "Content-Type: text/plain\r\nContent-Length: 0\r\nLocation: %hs%hs\r\n\r\n", file->task_req_qpath, (file->task_req_qpath_ending_with_slash? "": "/")) == (hio_oow_t)-1) return -1; diff --git a/lib/http-svr.c b/lib/http-svr.c index 0f1e8d4..59c1750 100644 --- a/lib/http-svr.c +++ b/lib/http-svr.c @@ -730,7 +730,10 @@ int hio_svc_https_task_sendfinal (hio_svc_htts_task_t* task, int status_code, co if (status_code != HIO_HTTP_STATUS_OK) content_len = 0; content_text = ""; } - else if (status_code == HIO_HTTP_STATUS_MOVED_PERMANENTLY || status_code == HIO_HTTP_STATUS_MOVED_TEMPORARILY) + else if (status_code == HIO_HTTP_STATUS_MOVED_PERMANENTLY || + status_code == HIO_HTTP_STATUS_MOVED_TEMPORARILY || + status_code == HIO_HTTP_STATUS_TEMPORARY_REDIRECT || + status_code == HIO_HTTP_STATUS_PERMANENT_REDIRECT) { content_len = 0; } @@ -830,5 +833,3 @@ int hio_svc_htts_writetosidechan (hio_svc_htts_t* htts, hio_oow_t idx, const voi return hio_dev_sck_writetosidechan(htts->l.sck[idx], dptr, dlen); } - - diff --git a/lib/http.c b/lib/http.c index f347727..f4bf6f2 100644 --- a/lib/http.c +++ b/lib/http.c @@ -63,18 +63,18 @@ const hio_bch_t* hio_http_status_to_bcstr (int code) case 303: msg = "See Other"; break; case HIO_HTTP_STATUS_NOT_MODIFIED: msg = "Not Modified"; break; case 305: msg = "Use Proxy"; break; - case 307: msg = "Temporary Redirect"; break; - case 308: msg = "Permanent Redirect"; break; + case HIO_HTTP_STATUS_TEMPORARY_REDIRECT: msg = "Temporary Redirect"; break; + case HIO_HTTP_STATUS_PERMANENT_REDIRECT: msg = "Permanent Redirect"; break; case HIO_HTTP_STATUS_BAD_REQUEST: msg = "Bad Request"; break; case HIO_HTTP_STATUS_UNAUTHORIZED: msg = "Unauthorized"; break; - case 402: msg = "Payment Required"; break; + case HIO_HTTP_STATUS_PAYMENT_REQUIRED: msg = "Payment Required"; break; case HIO_HTTP_STATUS_FORBIDDEN: msg = "Forbidden"; break; case HIO_HTTP_STATUS_NOT_FOUND: msg = "Not Found"; break; case HIO_HTTP_STATUS_METHOD_NOT_ALLOWED: msg = "Method Not Allowed"; break; - case 406: msg = "Not Acceptable"; break; - case 407: msg = "Proxy Authentication Required"; break; - case 408: msg = "Request Timeout"; break; + case HIO_HTTP_STATUS_NOT_ACCEPTABLE: msg = "Not Acceptable"; break; + case HIO_HTTP_STATUS_PROXY_AUTH_REQUIRED: msg = "Proxy Authentication Required"; break; + case HIO_HTTP_STATUS_REQUEST_TIMEOUT: msg = "Request Timeout"; break; case 409: msg = "Conflict"; break; case 410: msg = "Gone"; break; case HIO_HTTP_STATUS_LENGTH_REQUIRED: msg = "Length Required"; break; @@ -741,3 +741,44 @@ hio_oow_t hio_escape_html_bcstr (const hio_bch_t* str, hio_bch_t* buf, hio_oow_t return reqlen; } + +int hio_parse_http_status_header_value (const hio_bch_t* status_value, int* status_code, const hio_bch_t** status_desc) +{ + const hio_bch_t* begptr, * endptr; + int v_is_sober = 1; + hio_intmax_t v = 0; + hio_oow_t code_len; + hio_oow_t desc_len; + + endptr = status_value; + while (hio_is_bch_space(*endptr)) endptr++; + begptr = endptr; + while (hio_is_bch_digit(*endptr)) + { + v = v * 10 + (*endptr - '0'); + if (v > HIO_TYPE_MAX(int)) v_is_sober = 0; + endptr++; + } + code_len = endptr - begptr; + + while (hio_is_bch_space(*endptr)) endptr++; + begptr = endptr; + while (*endptr != '\0') endptr++; + desc_len = endptr - begptr; + + if (v_is_sober) + { + *status_code = v; + *status_desc = HIO_NULL; + if (code_len > 0 && desc_len > 0) + { + /* the status line could be simply "Status: 302" or more verbose like "Status: 302 Moved" + * the value may contain more than numbers */ + *status_desc = begptr; + } + return 0; + } + + /* no sober - do not update *status_code and *status_desc */ + return -1; /* not sober */ +}