diff options
-rw-r--r-- | regress/fcgi-test.c | 95 | ||||
-rw-r--r-- | regress/lib.sh | 27 | ||||
-rw-r--r-- | regress/tests.sh | 17 |
3 files changed, 124 insertions, 15 deletions
diff --git a/regress/fcgi-test.c b/regress/fcgi-test.c index 8f2f9ec..ed6ec4e 100644 --- a/regress/fcgi-test.c +++ b/regress/fcgi-test.c @@ -43,6 +43,10 @@ #define SUM(a, b) (((a) << 8) + (b)) +#ifndef nitems +#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) +#endif + struct fcgi_header { uint8_t version; uint8_t type; @@ -63,6 +67,11 @@ struct fcgi_end_req_body { unsigned char reserved[3]; }; +struct param { + char name[32]; + char value[128]; +}; + static int prepare_header(struct fcgi_header *h, int type, int id, size_t size, size_t padding) @@ -156,12 +165,65 @@ assert_record(int fd, int type) consume(fd, hdr.padding); } +static int +parse_len(int sock) +{ + unsigned char c, x[3]; + + must_read(sock, &c, 1); + if (c >> 7 == 0) + return (c); + + must_read(sock, &x, sizeof(x)); + return (((c & 0x7F) << 24) | (x[0] << 16) | (x[1] << 8) | x[2]); +} + +static void +parse_params(int sock, struct param *param, struct fcgi_header *hdr) +{ + int tot; + int nlen, vlen; + + tot = SUM(hdr->content_len1, hdr->content_len0); + tot -= sizeof(*hdr); + + nlen = parse_len(sock); + vlen = parse_len(sock); + + if (nlen + vlen != tot) + errx(1, "unexpected length, name=%d val=%d exp=%d", + nlen, vlen, tot); + + if ((size_t)nlen > sizeof(param->name) - 1 || + (size_t)vlen > sizeof(param->value) - 1) + errx(1, "parameter name or value too long"); + + memset(param, 0, sizeof(*param)); + must_read(sock, param->name, nlen); + must_read(sock, param->value, vlen); + + if (!strcmp(param->name, "SERVER_NAME")) + strlcpy(param->value, "<redacted>", sizeof(param->value)); + + consume(sock, hdr->padding); +} + +static int +param_cmp(const void *a, const void *b) +{ + const struct param *x = a, *y = b; + + return (strcmp(x->name, y->name)); +} + int main(int argc, char **argv) { struct fcgi_header hdr; struct fcgi_end_req_body end; struct sockaddr_un sun; + struct param params[64]; + size_t i, nparam; const char *path; const char *msg; size_t len; @@ -201,37 +263,58 @@ main(int argc, char **argv) assert_record(s, FCGI_BEGIN_REQUEST); /* read params */ + nparam = 0; for (;;) { read_header(s, &hdr); - consume(s, SUM(hdr.content_len1, hdr.content_len0)); - consume(s, hdr.padding); - if (hdr.type != FCGI_PARAMS) errx(1, "got %d; expecting PARAMS", hdr.type); if (hdr.content_len0 == 0 && hdr.content_len1 == 0 && - hdr.padding == 0) + hdr.padding == 0) { + consume(s, SUM(hdr.content_len1, hdr.content_len0)); + consume(s, hdr.padding); break; + } + + if (nparam == nitems(params)) + errx(1, "too many parameters"); + + parse_params(s, ¶ms[nparam++], &hdr); } assert_record(s, FCGI_STDIN); - msg = "20 text/gemini\r\n# hello from fastcgi!\n"; + msg = "20 text/gemini\r\n"; len = strlen(msg); prepare_header(&hdr, FCGI_STDOUT, 1, len, 0); must_write(s, &hdr, sizeof(hdr)); must_write(s, msg, len); - msg = "some more content in the page...\n"; + msg = "Here's the parameters I've got:\n"; len = strlen(msg); prepare_header(&hdr, FCGI_STDOUT, 1, len, 0); must_write(s, &hdr, sizeof(hdr)); must_write(s, msg, len); + qsort(params, nparam, sizeof(params[0]), param_cmp); + for (i = 0; i < nparam; ++i) { + char line[256]; + int r; + + r = snprintf(line, sizeof(line), "* %s=%s\n", + params[i].name, params[i].value); + if (r < 0 || (size_t)r >= sizeof(line)) + errx(1, "line too short"); + + prepare_header(&hdr, FCGI_STDOUT, 1, r, 0); + must_write(s, &hdr, sizeof(hdr)); + must_write(s, line, r); + } + prepare_header(&hdr, FCGI_END_REQUEST, 1, sizeof(end), 0); write(s, &hdr, sizeof(hdr)); memset(&end, 0, sizeof(end)); diff --git a/regress/lib.sh b/regress/lib.sh index d5e9609..9abfa1e 100644 --- a/regress/lib.sh +++ b/regress/lib.sh @@ -9,6 +9,31 @@ current_test= server_name= gghost= +fcgi_content() { + remote_host=::1 + if [ "$HAVE_IPV6" != yes ]; then + remote_host=127.0.0.1 + fi + + cat <<EOF +Here's the parameters I've got: +* AUTH_TYPE= +* GATEWAY_INTERFACE=CGI/1.1 +* GEMINI_URL_PATH=${fcgi_path_info##/} +* PATH_INFO=$fcgi_path_info +* PATH_TRANSLATED=$fcgi_path +* QUERY_STRING= +* REMOTE_ADDR=$remote_host +* REMOTE_HOST=$remote_host +* REQUEST_METHOD=GET +* SCRIPT_NAME= +* SERVER_NAME=<redacted> +* SERVER_PORT=$port +* SERVER_PROTOCOL=GEMINI +* SERVER_SOFTWARE=$($gmid -V | awk '{print $2 "/" $3}') +EOF +} + run_test() { ggflags= host="$REGRESS_HOST" @@ -16,6 +41,8 @@ run_test() { proxy_port=10966 proxy= config_common="log syslog off" + fcgi_path_info=/ + fcgi_path="$PWD/testdata/" hdr= body= dont_check_server_alive=no diff --git a/regress/tests.sh b/regress/tests.sh index b5fa93e..b2fe511 100644 --- a/regress/tests.sh +++ b/regress/tests.sh @@ -306,12 +306,10 @@ test_fastcgi() { setup_simple_test 'prefork 1' 'fastcgi socket "'$PWD'/fcgi.sock"' - msg=$(printf "# hello from fastcgi!\nsome more content in the page...") - i=0 while [ $i -lt 10 ]; do fetch / - check_reply "20 text/gemini" "$msg" + check_reply "20 text/gemini" "$(fcgi_content)" if [ $? -ne 0 ]; then kill $fcgi_pid return 1 @@ -327,15 +325,16 @@ test_fastcgi() { test_fastcgi_inside_location() { ./fcgi-test fcgi.sock & fcgi_pid=$! + fcgi_path_info="/foo" + fcgi_path="$PWD/testdata/foo" setup_simple_test 'prefork 1' 'fastcgi socket "'$PWD'/fcgi.sock" location "/dir/*" { fastcgi off }' - msg=$(printf "# hello from fastcgi!\nsome more content in the page...") fetch /foo - if ! check_reply "20 text/gemini" "$msg"; then + if ! check_reply "20 text/gemini" "$(fcgi_content)"; then kill $fcgi_pid return 1 fi @@ -353,6 +352,8 @@ test_fastcgi_inside_location() { test_fastcgi_location_match() { ./fcgi-test fcgi.sock & fcgi_pid=$! + fcgi_path_info="/foo" + fcgi_path="$PWD/testdata/foo" setup_simple_test 'prefork 1' ' location "/dir/*" { @@ -362,9 +363,8 @@ test_fastcgi_location_match() { fastcgi socket "'$PWD'/fcgi.sock" }' - msg=$(printf "# hello from fastcgi!\nsome more content in the page...") fetch /foo - if ! check_reply "20 text/gemini" "$msg"; then + if ! check_reply "20 text/gemini" "$(fcgi_content)"; then kill $fcgi_pid return 1 fi @@ -387,9 +387,8 @@ test_fastcgi_deprecated_syntax() { # backward compatibility works. setup_simple_test 'prefork 1' 'fastcgi "'$PWD'/fcgi.sock"' - msg=$(printf "# hello from fastcgi!\nsome more content in the page...") fetch / - check_reply "20 text/gemini" "$msg" + check_reply "20 text/gemini" "$(fcgi_content)" if [ $? -ne 0 ]; then kill $fcgi_pid return 1 |