added hio_parse_http_status_header_value()

This commit is contained in:
hyung-hwan 2023-03-06 00:40:29 +09:00
parent 47b1ac034d
commit 490591ca32
7 changed files with 73 additions and 94 deletions

View File

@ -110,12 +110,18 @@ enum hio_http_status_t
HIO_HTTP_STATUS_MOVED_PERMANENTLY = 301, HIO_HTTP_STATUS_MOVED_PERMANENTLY = 301,
HIO_HTTP_STATUS_MOVED_TEMPORARILY = 302, HIO_HTTP_STATUS_MOVED_TEMPORARILY = 302,
HIO_HTTP_STATUS_NOT_MODIFIED = 304, 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_BAD_REQUEST = 400,
HIO_HTTP_STATUS_UNAUTHORIZED = 401, HIO_HTTP_STATUS_UNAUTHORIZED = 401,
HIO_HTTP_STATUS_PAYMENT_REQUIRED = 402,
HIO_HTTP_STATUS_FORBIDDEN = 403, HIO_HTTP_STATUS_FORBIDDEN = 403,
HIO_HTTP_STATUS_NOT_FOUND = 404, HIO_HTTP_STATUS_NOT_FOUND = 404,
HIO_HTTP_STATUS_METHOD_NOT_ALLOWED = 405, 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_LENGTH_REQUIRED = 411,
HIO_HTTP_STATUS_RANGE_NOT_SATISFIABLE = 416, HIO_HTTP_STATUS_RANGE_NOT_SATISFIABLE = 416,
HIO_HTTP_STATUS_EXPECTATION_FAILED = 417, HIO_HTTP_STATUS_EXPECTATION_FAILED = 417,

View File

@ -358,6 +358,12 @@ HIO_EXPORT hio_oow_t hio_escape_html_bcstr (
hio_oow_t len 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 */ /* HTTP SERVER SERVICE */
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */

View File

@ -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_svc_htts_cli_t* cli = cgi->task_client;
hio_bch_t dtbuf[64]; hio_bch_t dtbuf[64];
int status_code = HIO_HTTP_STATUS_OK; 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) 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; cgi->res_mode_to_cli = CGI_RES_MODE_LENGTH;
} }
if (req->attr.status) if (req->attr.status) hio_parse_http_status_header_value(req->attr.status, &status_code, &status_desc);
{
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;
}
}
hio_svc_htts_fmtgmtime (cli->htts, HIO_NULL, dtbuf, HIO_COUNTOF(dtbuf)); 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 (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, "%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, "%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, "Server: %hs\r\nDate: %hs\r\n", cli->htts->server_name, dtbuf) == (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; if (hio_htre_walkheaders(req, peer_capture_response_header, cli) <= -1) return -1;
switch (cgi->res_mode_to_cli) switch (cgi->res_mode_to_cli)

View File

@ -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_svc_htts_cli_t* cli = fcgi->task_client;
hio_bch_t dtbuf[64]; hio_bch_t dtbuf[64];
int status_code = HIO_HTTP_STATUS_OK; 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) 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; fcgi->res_mode_to_cli = FCGI_RES_MODE_LENGTH;
} }
if (req->attr.status) if (req->attr.status) hio_parse_http_status_header_value(req->attr.status, &status_code, &status_desc);
{
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;
}
}
hio_svc_htts_fmtgmtime (cli->htts, HIO_NULL, dtbuf, HIO_COUNTOF(dtbuf)); 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 (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, "%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, "%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, "Server: %hs\r\nDate: %hs\r\n", cli->htts->server_name, dtbuf) == (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; if (hio_htre_walkheaders(req, peer_capture_response_header, cli) <= -1) return -1;

View File

@ -158,7 +158,10 @@ static int file_send_final_status_to_client (file_t* file, int status_code, int
status_msg = ""; 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. */ /* 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; 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;

View File

@ -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; if (status_code != HIO_HTTP_STATUS_OK) content_len = 0;
content_text = ""; 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; 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); return hio_dev_sck_writetosidechan(htts->l.sck[idx], dptr, dlen);
} }

View File

@ -63,18 +63,18 @@ const hio_bch_t* hio_http_status_to_bcstr (int code)
case 303: msg = "See Other"; break; case 303: msg = "See Other"; break;
case HIO_HTTP_STATUS_NOT_MODIFIED: msg = "Not Modified"; break; case HIO_HTTP_STATUS_NOT_MODIFIED: msg = "Not Modified"; break;
case 305: msg = "Use Proxy"; break; case 305: msg = "Use Proxy"; break;
case 307: msg = "Temporary Redirect"; break; case HIO_HTTP_STATUS_TEMPORARY_REDIRECT: msg = "Temporary Redirect"; break;
case 308: msg = "Permanent 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_BAD_REQUEST: msg = "Bad Request"; break;
case HIO_HTTP_STATUS_UNAUTHORIZED: msg = "Unauthorized"; 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_FORBIDDEN: msg = "Forbidden"; break;
case HIO_HTTP_STATUS_NOT_FOUND: msg = "Not Found"; break; case HIO_HTTP_STATUS_NOT_FOUND: msg = "Not Found"; break;
case HIO_HTTP_STATUS_METHOD_NOT_ALLOWED: msg = "Method Not Allowed"; break; case HIO_HTTP_STATUS_METHOD_NOT_ALLOWED: msg = "Method Not Allowed"; break;
case 406: msg = "Not Acceptable"; break; case HIO_HTTP_STATUS_NOT_ACCEPTABLE: msg = "Not Acceptable"; break;
case 407: msg = "Proxy Authentication Required"; break; case HIO_HTTP_STATUS_PROXY_AUTH_REQUIRED: msg = "Proxy Authentication Required"; break;
case 408: msg = "Request Timeout"; break; case HIO_HTTP_STATUS_REQUEST_TIMEOUT: msg = "Request Timeout"; break;
case 409: msg = "Conflict"; break; case 409: msg = "Conflict"; break;
case 410: msg = "Gone"; break; case 410: msg = "Gone"; break;
case HIO_HTTP_STATUS_LENGTH_REQUIRED: msg = "Length Required"; 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; 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 */
}