⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 request.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 3 页
字号:
	connected = ne_sock_connect(sock, ia, 7777) == 0;    ne_addr_destroy(addr);    if (sock == NULL)	return 0;    else {	ne_sock_close(sock);	return 1;    }}/* This is a regression test for neon 0.17.0 and earlier, which goes * into an infinite loop if a request with a body is sent to a server * which simply closes the connection. */static int closed_connection(void){    int ret;    /* This spawns a server process which will run the 'serve_close'     * response function 200 times, then die. This guarantees that the     * request eventually fails... */    CALL(fail_request(1, serve_close, NULL, 1));    /* if server died -> infinite loop was detected. */    ret = !is_alive(7777);    reap_server();    ONN("server aborted, infinite loop?", ret);    return OK;}static int serve_close2(ne_socket *sock, void *userdata){    int *count = userdata;    *count += 1;    if (*count == 1)	return 0;    NE_DEBUG(NE_DBG_HTTP, "Re-entered! Buggy client.\n");    CALL(discard_request(sock));    CALL(SEND_STRING(sock, RESP200 "Content-Length: 0\r\n\r\n"));    return 0;}/* As closed_connection(); but check that the client doesn't retry * after receiving the EOF on the first request down a new * connection.  */static int close_not_retried(void){    int count = 0;    ne_session *sess = ne_session_create("http", "localhost", 7777);    CALL(spawn_server_repeat(7777, serve_close2, &count, 3));    ONN("request was retried after EOF", any_request(sess, "/foo") == NE_OK);    reap_server();    ne_session_destroy(sess);    return OK;}static enum {    prog_error, /* error */    prog_transfer, /* doing a transfer */    prog_done /* finished. */} prog_state = prog_transfer;static off_t prog_last = -1, prog_total;/* callback for send_progress. */static void s_progress(void *userdata, off_t prog, off_t total){    NE_DEBUG(NE_DBG_HTTP, 	     "progress callback: %" NE_FMT_OFF_T "/%" NE_FMT_OFF_T ".\n",	     prog, total);    switch (prog_state) {    case prog_error:    case prog_done:	return;    case prog_transfer:	if (total != prog_total) {	    t_context("total unexpected: %ld not %ld", total, prog_total);	    prog_state = prog_error;	}	else if (prog > total) {	    t_context("first progress was invalid (%ld/%ld)", prog, total);	    prog_state = prog_error;	}	else if (prog_last != -1 && prog_last > prog) {	    t_context("progess went backwards: %ld to %ld", prog_last, prog);	    prog_state = prog_error;	}	else if (prog_last == prog) {	    t_context("no progress made! %ld to %ld", prog_last, prog);	    prog_state = prog_error;	}	else if (prog == total) {	    prog_state = prog_done;	}	break;    }	        prog_last = prog;}static ssize_t provide_progress(void *userdata, char *buf, size_t bufsiz){    int *count = userdata;    if (*count >= 0 && buf != NULL) {	buf[0] = 'a';	*count -= 1;	return 1;    } else {	return 0;    }}static int send_progress(void){    static int count = 200;    ON(prepare_request(single_serve_string, 		       RESP200 "Connection: close\r\n\r\n"));    prog_total = 200;    ne_set_progress(def_sess, s_progress, NULL);    ne_set_request_body_provider(def_req, count,				 provide_progress, &count);#define sess def_sess    ONREQ(ne_request_dispatch(def_req));#undef sess        ON(finish_request());    CALL(prog_state == prog_error);    return OK;    }static int read_timeout(void){    ne_session *sess;    ne_request *req;    time_t start, finish;    int ret;    CALL(make_session(&sess, sleepy_server, NULL));        /* timeout after one second. */    ne_set_read_timeout(sess, 1);        req = ne_request_create(sess, "GET", "/timeout");    time(&start);    ret = ne_request_dispatch(req);    time(&finish);    reap_server();    ONN("request succeeded, should have timed out", ret == NE_OK);    ONV(ret != NE_TIMEOUT,	("request failed non-timeout error: %s", ne_get_error(sess)));    ONN("timeout ignored, or very slow machine", finish - start > 3);    ne_request_destroy(req);    ne_session_destroy(sess);    return OK;    }/* expect failure code 'code', for request to given hostname and port, * without running a server. */static int fail_noserver(const char *hostname, unsigned int port, int code){     ne_session *sess = ne_session_create("http", hostname, port);     int ret = any_request(sess, "/foo");     ne_session_destroy(sess);     ONV(ret == NE_OK,	 ("request to server at %s:%u succeded?!", hostname, port));     ONV(ret != code, ("request failed with %d not %d", ret, code));     return OK;}static int fail_lookup(void){    return fail_noserver("no.such.domain", 7777, NE_LOOKUP);}/* neon 0.23.0 to 0.23.3: if a nameserver lookup failed, subsequent * requests on the session would crash. */static int fail_double_lookup(void){     ne_session *sess = ne_session_create("http", "nohost.example.com", 80);     ONN("request did not give lookup failure",	 any_request(sess, "/foo") != NE_LOOKUP);     ONN("second request did not give lookup failure",	 any_request(sess, "/bar") != NE_LOOKUP);     ne_session_destroy(sess);     return OK;}static int fail_connect(void){    return fail_noserver("localhost", 7777, NE_CONNECT);}/* Test that the origin server hostname is NOT resolved for a proxied * request. */static int proxy_no_resolve(void){     ne_session *sess = ne_session_create("http", "no.such.domain", 80);     int ret;          ne_session_proxy(sess, "localhost", 7777);     CALL(spawn_server(7777, single_serve_string,		       RESP200 "Content-Length: 0\r\n\r\n"));          ret = any_request(sess, "/foo");     ne_session_destroy(sess);     ONN("origin server name resolved when proxy used", ret == NE_LOOKUP);     CALL(await_server());     return OK;}/* If the chunk size is entirely invalid, the request should be * aborted.  Fails with neon <0.22; invalid chunk sizes would be * silently treated as 'zero'. */static int fail_chunksize(void){    return fail_request(0, single_serve_string,			RESP200 TE_CHUNKED "\r\n" "ZZZZZ\r\n\r\n", 0);}/* in neon <0.22, if an error occcurred whilst reading the response * body, the connection would not be closed (though this test will * succeed in neon <0.22 since it the previous test fails). */static int abort_respbody(void){    ne_session *sess;        CALL(make_session(&sess, single_serve_string,		      RESP200 TE_CHUNKED "\r\n"		      "zzz\r\n"		      RESP200 "Content-Length: 0\r\n\r\n"));        /* connection must be aborted on the first request, since it     * contains an invalid chunk size. */    ONN("invalid chunk size was accepted?",	any_request(sess, "/foo") != NE_ERROR);    CALL(await_server());        /* second request should fail since server has gone away. */    ONN("connection was not aborted", any_request(sess, "/foo") == NE_OK);    ne_session_destroy(sess);    return OK;}static int serve_abort(ne_socket *sock, void *ud){    exit(0);}/* Test that after an aborted request on a peristent connection, a * failure of the *subsequent* request is not treated as a persistent * connection timeout and retried.  */static int retry_after_abort(void){    ne_session *sess;        /* Serve two responses down a single persistent connection, the     * second of which is invalid and will cause the request to be     * aborted. */    CALL(make_session(&sess, single_serve_string, 		      RESP200 "Content-Length: 0\r\n\r\n"		      RESP200 TE_CHUNKED "\r\n"		      "zzzzz\r\n"));    CALL(any_request(sess, "/first"));    ONN("second request should fail", any_request(sess, "/second") == NE_OK);    CALL(await_server());    /* spawn a server, abort the server immediately.  If the     * connection reset is interpreted as a p.conn timeout, a new     * connection will be attempted, which will fail with     * NE_CONNECT. */    CALL(spawn_server(7777, serve_abort, NULL));    ONN("third request was retried",	any_request(sess, "/third") == NE_CONNECT);    reap_server();    ne_session_destroy(sess);        return OK;}/* Fail to parse the response status line: check the error message is * sane.  Failed during 0.23-dev briefly, and possibly with 0.22.0 * too. */static int fail_statusline(void){    ne_session *sess;    int ret;    CALL(make_session(&sess, single_serve_string, "Fish.\r\n"));        ret = any_request(sess, "/fail");    ONV(ret != NE_ERROR, ("request failed with %d not NE_ERROR", ret));        /* FIXME: will break for i18n. */    ONV(strcmp(ne_get_error(sess), "Could not parse response status line."),	("session error was `%s'", ne_get_error(sess)));    ne_session_destroy(sess);    return OK;    }#define LEN (9000)static int fail_long_header(void){    char resp[LEN + 500] = "HTTP/1.1 200 OK\r\n"	"Server: fish\r\n";    size_t len = strlen(resp);        /* add a long header */    memset(resp + len, 'a', LEN);    resp[len + LEN] = '\0';        strcat(resp, "\r\n\r\n");    return invalid_response_gives_error(resp, "Line too long");}static int fail_corrupt_chunks(void){    static const struct {        const char *resp, *error;    } ts[] = {        /* not CRLF */        { RESP200 TE_CHUNKED "\r\n" "5\r\n" "abcdeFISH",           "delimiter was invalid" },        /* short CRLF */        { RESP200 TE_CHUNKED "\r\n" "5\r\n" "abcde\n",          "not read chunk delimiter" },        /* CR-notLF */        { RESP200 TE_CHUNKED "\r\n" "5\r\n" "abcde\rZZZ",          "delimiter was invalid" },        { NULL, NULL }    };    int n;    for (n = 0; ts[n].resp; n++)        CALL(invalid_response_gives_error(ts[n].resp, ts[n].error));    return OK;}static int versions(void){    ne_session *sess;    CALL(make_session(&sess, single_serve_string, 		      "HTTP/1.1 200 OK\r\n"		      "Content-Length: 0\r\n\r\n"		      "HTTP/1.0 200 OK\r\n"		      "Content-Length: 0\r\n\r\n"));        CALL(any_request(sess, "/http11"));	     ONN("did not detect HTTP/1.1 compliance",	ne_version_pre_http11(sess) != 0);	     CALL(any_request(sess, "/http10"));    ONN("did not detect lack of HTTP/1.1 compliance",	ne_version_pre_http11(sess) == 0);    ne_session_destroy(sess);    return OK;}struct cr_args {    const char *method, *uri;    int result;};static void hk_createreq(ne_request *req, void *userdata,			 const char *method, const char *requri){    struct cr_args *args = userdata;        args->result = 1; /* presume failure */        if (strcmp(args->method, method))	t_context("Hook got method %s not %s", method, args->method);    else if (strcmp(args->uri, requri))	t_context("Hook got Req-URI %s not %s", requri, args->uri);    else	args->result = 0;}static int hook_create_req(void){    ne_session *sess;    struct cr_args args;    CALL(make_session(&sess, single_serve_string, EMPTY_RESP EMPTY_RESP));    ne_hook_create_request(sess, hk_createreq, &args);    args.method = "GET";    args.uri = "/foo";    args.result = -1;    CALL(any_request(sess, "/foo"));        ONN("first hook never called", args.result == -1);    if (args.result) return FAIL;    args.uri = "http://localhost:7777/bar";    args.result = -1;        /* force use of absoluteURI in request-uri */    ne_session_proxy(sess, "localhost", 7777);    CALL(any_request(sess, "/bar"));        ONN("second hook never called", args.result == -1);    if (args.result) return FAIL;    ne_session_destroy(sess);    return OK;    }static int serve_check_method(ne_socket *sock, void *ud){    char *method = ud;    char buf[20];    size_t methlen = strlen(method);    if (ne_sock_read(sock, buf, methlen) != (ssize_t)methlen)        return -1;        ONN("method corrupted", memcmp(buf, method, methlen));        return single_serve_string(sock, "HTTP/1.1 204 OK\r\n\r\n");}                             /* Test that the method string passed to ne_request_create is * strdup'ed. */static int dup_method(void){    char method[] = "FOO";    ne_session *sess;    ne_request *req;    CALL(make_session(&sess, serve_check_method, method));        req = ne_request_create(sess, method, "/bar");        strcpy(method, "ZZZ");    ONREQ(ne_request_dispatch(req));    ne_request_destroy(req);    ne_session_destroy(sess);    CALL(await_server());    return OK;}ne_test tests[] = {    T(lookup_localhost),    T(single_get_clength),    T(single_get_eof),    T(single_get_chunked),    T(no_body_204),    T(no_body_205),    T(no_body_304),    T(no_body_HEAD),    T(no_body_empty_clength),    T(no_body_bad_clength),    T(no_headers),    T(chunks),    T(te_header),    T(any_te_header),    T(reason_phrase),    T(chunk_numeric),    T(chunk_extensions),    T(chunk_trailers),    T(chunk_oversize),    T(te_over_clength),    T(te_over_clength2),    T(no_body_chunks),    T(persist_http11),    T(persist_chunked),    T(persist_http10),    T(persist_timeout),    T(no_persist_http10),    T(ptimeout_eof),    T(ptimeout_eof2),    T(closed_connection),    T(close_not_retried),    T(send_progress),    T(ignore_bad_headers),    T(fold_headers),    T(fold_many_headers),    T(multi_header),    T(empty_header),    T(trailing_header),    T(ignore_header_case),    T(ignore_header_ws),    T(ignore_header_ws2),    T(ignore_header_ws3),    T(ignore_header_tabs),    T(continued_header),    T(skip_interim_1xx),    T(skip_many_1xx),    T(skip_1xx_hdrs),    T(send_bodies),    T(expect_100_once),    T(unbounded_headers),    T(unbounded_folding),    T(blank_response),    T(not_http),    T(fail_eof_continued),    T(fail_eof_headers),    T(fail_eof_chunk),    T(fail_eof_badclen),    T(fail_long_header),    T(fail_corrupt_chunks),    T(read_timeout),    T(fail_lookup),    T(fail_double_lookup),    T(fail_connect),    T(proxy_no_resolve),    T(fail_chunksize),    T(abort_respbody),    T(retry_after_abort),    T(fail_statusline),    T(dup_method),    T(versions),    T(hook_create_req),    T(NULL)};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -