| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <stdint.h> |
| #include <errno.h> |
| |
| #include "htparse.h" |
| |
| static int |
| _on_msg_start(htparser * p) { |
| printf("START {\n"); |
| return 0; |
| } |
| |
| static int |
| _on_msg_end(htparser * p) { |
| printf("}\n"); |
| return 0; |
| } |
| |
| static int |
| _path(htparser * p, const char * data, size_t len) { |
| printf("\tpath = '%.*s'\n", (int)len, data); |
| return 0; |
| } |
| |
| static int |
| _method(htparser * p, const char * data, size_t len) { |
| printf("\tmethod = '%.*s'\n", (int)len, data); |
| return 0; |
| } |
| |
| static int |
| _uri(htparser * p, const char * data, size_t len) { |
| printf("\turi = '%.*s'\n", (int)len, data); |
| return 0; |
| } |
| |
| static int |
| _args(htparser * p, const char * data, size_t len) { |
| printf("\targs = '%.*s'\n", (int)len, data); |
| return 0; |
| } |
| |
| static int |
| _hdrs_end(htparser * p) { |
| printf("\t}\n"); |
| return 0; |
| } |
| |
| static int |
| _hdrs_start(htparser * p) { |
| printf("\thdrs {\n"); |
| return 0; |
| } |
| |
| static int |
| _hdr_key(htparser * p, const char * data, size_t len) { |
| printf("\t\thdr_key = '%.*s'\n", (int)len, data); |
| return 0; |
| } |
| |
| static int |
| _hdr_val(htparser * p, const char * data, size_t len) { |
| printf("\t\thdr_val = '%.*s'\n", (int)len, data); |
| return 0; |
| } |
| |
| static int |
| _read_body(htparser * p, const char * data, size_t len) { |
| printf("\t'%.*s'\n", (int)len, data); |
| return 0; |
| } |
| |
| static int |
| _on_new_chunk(htparser * p) { |
| printf("\t--payload--\n"); |
| /* printf("..chunk..\n"); */ |
| return 0; |
| } |
| |
| static void |
| _test(htparser * p, htparse_hooks * hooks, const char * l) { |
| printf("---- test ----\n"); |
| printf("%zu, %s\n", strlen(l), l); |
| |
| htparser_init(p); |
| printf("%zu == %zu\n", htparser_run(p, hooks, l, strlen(l)), strlen(l)); |
| |
| if (htparser_get_error(p)) { |
| printf("ERROR: %s\n", htparser_get_strerror(p)); |
| } |
| |
| printf("\n"); |
| } |
| |
| static void |
| _test_fragments(htparser * p, htparse_hooks * hooks, const char ** fragments) { |
| int i = 0; |
| |
| printf("---- test fragment ----\n"); |
| htparser_init(p); |
| |
| while (1) { |
| const char * l = fragments[i++]; |
| |
| if (l == NULL) { |
| break; |
| } |
| |
| htparser_run(p, hooks, l, strlen(l)); |
| |
| if (htparser_get_error(p)) { |
| printf("ERROR: %s\n", htparser_get_strerror(p)); |
| } |
| } |
| |
| printf("\n"); |
| } |
| |
| static const char * test_fragment_1[] = { |
| "GET \0", |
| " /fjdksf\0", |
| "jfkdslfds H\0", |
| "TTP/1.\0", |
| "1\r\0", |
| "\n\0", |
| "\r\0", |
| "\n\0", |
| NULL |
| }; |
| |
| static const char * test_fragment_2[] = { |
| "POST /\0", |
| "h?a=b HTTP/1.0\r\n\0", |
| "Content-Len\0", |
| "gth\0", |
| ": 1\0", |
| "0\r\n\0", |
| "\r\n\0", |
| "12345\0", |
| "67890\0", |
| NULL |
| }; |
| |
| static const char * test_chunk_fragment_1[] = { |
| "POST /stupid HTTP/1.1\r\n", |
| "Transfer-Encoding: chunked\r\n", |
| "\r\n", |
| "25\r\n", |
| "This is the data in the first chunk\r\n", |
| "\r\n", |
| "1C\r\n", |
| "and this is the second one\r\n", |
| "\r\n", |
| "3\r\n", |
| "con\r\n", |
| "8\r\n", |
| "sequence\r\n", |
| "0\r\n", |
| "\r\n", |
| NULL |
| }; |
| |
| static const char * test_chunk_fragment_2[] = { |
| "POST /stupid HTTP/1.1\r\n", |
| "Transfer-Encoding: chunked\r\n", |
| "\r\n", |
| "25\r\n", |
| "This is the data in the first chunk\r\n", |
| "\r\n", |
| "1C\r\n", |
| "and this is the second one\r\n", |
| "\r\n", |
| "3\r\n", |
| "c", |
| "on\r\n", |
| "8\r\n", |
| "sequence\r\n", |
| "0\r\n", |
| "\r\n", |
| "GET /foo?bar/baz? HTTP/1.0\r\n", |
| "Host: stupid.com\r\n", |
| "\r\n", |
| NULL |
| }; |
| int |
| main(int argc, char ** argv) { |
| htparser * p = htparser_new(); |
| htparse_hooks hooks = { |
| .on_msg_begin = _on_msg_start, |
| .method = _method, |
| .scheme = NULL, |
| .host = NULL, |
| .port = NULL, |
| .path = _path, |
| .args = _args, |
| .uri = _uri, |
| .on_hdrs_begin = _hdrs_start, |
| .hdr_key = _hdr_key, |
| .hdr_val = _hdr_val, |
| .on_hdrs_complete = _hdrs_end, |
| .on_new_chunk = _on_new_chunk, |
| .body = _read_body, |
| .on_msg_complete = _on_msg_end |
| }; |
| |
| const char * test_1 = "GET / HTTP/1.0\r\n\r\n"; |
| const char * test_2 = "GET /hi?a=b&c=d HTTP/1.1\r\n\r\n"; |
| const char * test_3 = "GET /hi/die/?a=b&c=d HTTP/1.1\r\n\r\n"; |
| const char * test_4 = "POST /fjdls HTTP/1.0\r\n" |
| "Content-Length: 4\r\n" |
| "\r\n" |
| "abcd"; |
| const char * test_7 = "POST /derp HTTP/1.1\r\n" |
| "Transfer-Encoding: chunked\r\n\r\n" |
| "1e\r\nall your base are belong to us\r\n" |
| "0\r\n" |
| "\r\n\0"; |
| const char * test_8 = "GET /DIE HTTP/1.1\r\n" |
| "HERP: DE\r\n" |
| "\tRP\r\nthings:stuff\r\n\r\n"; |
| const char * test_9 = "GET /big_content_len HTTP/1.1\r\n" |
| "Content-Length: 18446744073709551615\r\n\r\n"; |
| |
| const char * test_fail = "GET /JF HfD]\r\n\r\n"; |
| |
| _test(p, &hooks, test_1); |
| _test(p, &hooks, test_2); |
| _test(p, &hooks, test_3); |
| _test(p, &hooks, test_4); |
| _test(p, &hooks, test_7); |
| _test(p, &hooks, test_8); |
| _test(p, &hooks, test_9); |
| _test(p, &hooks, test_fail); |
| |
| _test_fragments(p, &hooks, test_fragment_1); |
| _test_fragments(p, &hooks, test_fragment_2); |
| _test_fragments(p, &hooks, test_chunk_fragment_1); |
| _test_fragments(p, &hooks, test_chunk_fragment_2); |
| |
| return 0; |
| } /* main */ |
| |