src/server/proxy/httpclient.c

changeset 690
c7b73000a1ed
parent 688
02360295ec58
child 691
4d8a55a7618b
equal deleted inserted replaced
689:dc422b7fc59a 690:c7b73000a1ed
30 30
31 #include "../util/socket.h" 31 #include "../util/socket.h"
32 32
33 #include <cx/buffer.h> 33 #include <cx/buffer.h>
34 #include <cx/string.h> 34 #include <cx/string.h>
35 #include <cx/printf.h>
35 #include <stdlib.h> 36 #include <stdlib.h>
36 #include <string.h> 37 #include <string.h>
37 #include <errno.h> 38 #include <errno.h>
38 39
39 static int client_connected(EventHandler *ev, Event *event); 40 static int client_connected(EventHandler *ev, Event *event);
889 cxBufferFree(req); 890 cxBufferFree(req);
890 cxBufferFree(buf); 891 cxBufferFree(buf);
891 } 892 }
892 } 893 }
893 894
894 static CX_TEST_SUBROUTINE(test_http_client_io, const char *response_str, int status_code, const char *msg, CxBuffer *out_buf, size_t write_blocksz) { 895 static CX_TEST_SUBROUTINE(test_http_client_io, cxstring response, int status_code, const char *msg, CxBuffer *out_buf, size_t write_blocksz) {
895 EventHandler dummy; 896 EventHandler dummy;
896 HttpClient *client = http_client_new(&dummy); 897 HttpClient *client = http_client_new(&dummy);
897 898
898 int fds[2]; 899 int fds[2];
899 util_socketpair(fds); 900 util_socketpair(fds);
939 ret = client_io(&dummy, &event); 940 ret = client_io(&dummy, &event);
940 CX_TEST_ASSERT(!client->error); 941 CX_TEST_ASSERT(!client->error);
941 CX_TEST_ASSERT(ret == 1); 942 CX_TEST_ASSERT(ret == 1);
942 } 943 }
943 CX_TEST_ASSERT(req_header_pos == req_header_len); 944 CX_TEST_ASSERT(req_header_pos == req_header_len);
944 945
945 size_t response_str_len = strlen(response_str); 946 const char *response_str = response.ptr;
947 size_t response_str_len = response.length;
946 size_t response_str_pos = 0; 948 size_t response_str_pos = 0;
947 949
948 // send response and do IO 950 // send response and do IO
949 while(response_str_pos < response_str_len) { 951 while(response_str_pos < response_str_len) {
950 size_t len = response_str_len - response_str_pos; 952 size_t len = response_str_len - response_str_pos;
973 close(fds[1]); 975 close(fds[1]);
974 http_client_free(client); 976 http_client_free(client);
975 } 977 }
976 978
977 static CX_TEST_SUBROUTINE(test_http_client_io_simple, size_t blocksz) { 979 static CX_TEST_SUBROUTINE(test_http_client_io_simple, size_t blocksz) {
978 char *response_str = 980 cxstring response_str = cx_str(
979 "HTTP/1.1 200 OK\r\n" 981 "HTTP/1.1 200 OK\r\n"
980 "Host: localhost\r\n" 982 "Host: localhost\r\n"
981 "Content-length: 13\r\n" 983 "Content-length: 13\r\n"
982 "\r\n" 984 "\r\n"
983 "Hello World!\n"; 985 "Hello World!\n");
984 CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS); 986 CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS);
985 987
986 CX_TEST_CALL_SUBROUTINE(test_http_client_io, response_str, 200, "OK", buf, blocksz); 988 CX_TEST_CALL_SUBROUTINE(test_http_client_io, response_str, 200, "OK", buf, blocksz);
987 CX_TEST_ASSERT(buf->size == 13); 989 CX_TEST_ASSERT(buf->size == 13);
988 CX_TEST_ASSERT(!cx_strcmp(cx_strn(buf->space, buf->size), "Hello World!\n")); 990 CX_TEST_ASSERT(!cx_strcmp(cx_strn(buf->space, buf->size), "Hello World!\n"));
1018 CX_TEST_DO { 1020 CX_TEST_DO {
1019 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 512); 1021 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 512);
1020 } 1022 }
1021 } 1023 }
1022 1024
1025 static CX_TEST_SUBROUTINE(test_http_client_io_large, size_t blocksz) {
1026 int ctlen = 1024*1024*32;
1027 CxBuffer *resp = cxBufferCreate(NULL, NULL, ctlen + 128, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS);
1028 cx_bprintf(resp,
1029 "HTTP/1.1 200 OK\r\n"
1030 "Host: localhost\r\n"
1031 "Content-length: %d\r\n"
1032 "\r\n",
1033 ctlen);
1034 size_t content_start = resp->pos;
1035 CX_TEST_ASSERT(resp->pos + ctlen < resp->capacity);
1036 memset(resp->space + resp->pos, 'x', ctlen);
1037 resp->pos += ctlen;
1038 resp->size += ctlen;
1039
1040 CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS);
1041
1042 CX_TEST_CALL_SUBROUTINE(test_http_client_io, cx_strn(resp->space, resp->size), 200, "OK", buf, blocksz);
1043 CX_TEST_ASSERT(buf->size == ctlen);
1044 CX_TEST_ASSERT(!memcmp(buf->space, resp->space + content_start, ctlen));
1045
1046 cxBufferFree(resp);
1047 cxBufferFree(buf);
1048 }
1049
1050 static CX_TEST(test_http_client_io_large_128b) {
1051 CX_TEST_DO {
1052 CX_TEST_CALL_SUBROUTINE(test_http_client_io_large, 128);
1053 }
1054 }
1055
1056 static CX_TEST(test_http_client_io_large_4096b) {
1057 CX_TEST_DO {
1058 CX_TEST_CALL_SUBROUTINE(test_http_client_io_large, 1024);
1059 }
1060 }
1061
1023 static CX_TEST_SUBROUTINE(test_http_client_io_chunked_transfer, size_t blocksz) { 1062 static CX_TEST_SUBROUTINE(test_http_client_io_chunked_transfer, size_t blocksz) {
1024 char *response_str = 1063 cxstring response_str = cx_str(
1025 "HTTP/1.1 200 OK\r\n" 1064 "HTTP/1.1 200 OK\r\n"
1026 "Host: localhost\r\n" 1065 "Host: localhost\r\n"
1027 "Transfer-encoding: chunked\r\n" 1066 "Transfer-encoding: chunked\r\n"
1028 "\r\n" 1067 "\r\n"
1029 "d\r\n" 1068 "d\r\n"
1030 "Hello World!\n" 1069 "Hello World!\n"
1031 "\r\n" 1070 "\r\n"
1032 "0\r\n\r\n"; 1071 "0\r\n\r\n");
1033 CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS); 1072 CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS);
1034 1073
1035 CX_TEST_CALL_SUBROUTINE(test_http_client_io, response_str, 200, "OK", buf, blocksz); 1074 CX_TEST_CALL_SUBROUTINE(test_http_client_io, response_str, 200, "OK", buf, blocksz);
1036 CX_TEST_ASSERT(buf->size == 13); 1075 CX_TEST_ASSERT(buf->size == 13);
1037 CX_TEST_ASSERT(!cx_strcmp(cx_strn(buf->space, buf->size), "Hello World!\n")); 1076 CX_TEST_ASSERT(!cx_strcmp(cx_strn(buf->space, buf->size), "Hello World!\n"));
1058 } 1097 }
1059 1098
1060 static CX_TEST(test_http_client_io_chunked_transfer_64b) { 1099 static CX_TEST(test_http_client_io_chunked_transfer_64b) {
1061 CX_TEST_DO { 1100 CX_TEST_DO {
1062 CX_TEST_CALL_SUBROUTINE(test_http_client_io_chunked_transfer, 64); 1101 CX_TEST_CALL_SUBROUTINE(test_http_client_io_chunked_transfer, 64);
1102 }
1103 }
1104
1105 static CX_TEST_SUBROUTINE(test_http_client_io_large_chunked_transfer, size_t blocksz) {
1106 int chunk1 = 1024*1024*2;
1107 int chunk2 = 1024*128;
1108 int chunk3 = 123;
1109 int chunk4 = 1024*1024*5;
1110 int chunk5 = 1024*16;
1111
1112 char *chunkbuf = malloc(chunk4);
1113
1114 int ctlen = chunk1 + chunk2 + chunk3 + chunk4 + chunk5;
1115 CxBuffer *resp = cxBufferCreate(NULL, NULL, ctlen * 128, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS);
1116 cx_bprintf(resp,
1117 "HTTP/1.1 200 OK\r\n"
1118 "Transfer-encoding: chunked\r\n"
1119 "\r\n",
1120 ctlen);
1121 size_t content_start = resp->pos;
1122 CX_TEST_ASSERT(resp->pos + ctlen < resp->capacity);
1123
1124 memset(chunkbuf, 'x', chunk1);
1125 cx_bprintf(resp, "%x\r\n", chunk1);
1126 int chunk1_pos = resp->pos;
1127 cxBufferWrite(chunkbuf, 1, chunk1, resp);
1128 cxBufferPutString(resp, "\r\n");
1129
1130 memset(chunkbuf, '2', chunk2);
1131 cx_bprintf(resp, "%x\r\n", chunk2);
1132 int chunk2_pos = resp->pos;
1133 cxBufferWrite(chunkbuf, 1, chunk2, resp);
1134 cxBufferPutString(resp, "\r\n");
1135
1136 memset(chunkbuf, 'c', chunk3);
1137 cx_bprintf(resp, "%x\r\n", chunk3);
1138 int chunk3_pos = resp->pos;
1139 cxBufferWrite(chunkbuf, 1, chunk3, resp);
1140 cxBufferPutString(resp, "\r\n");
1141
1142 memset(chunkbuf, '4', chunk4);
1143 cx_bprintf(resp, "%x\r\n", chunk4);
1144 int chunk4_pos = resp->pos;
1145 cxBufferWrite(chunkbuf, 1, chunk4, resp);
1146 cxBufferPutString(resp, "\r\n");
1147
1148 memset(chunkbuf, 'z', chunk5);
1149 cx_bprintf(resp, "%x\r\n", chunk5);
1150 int chunk5_pos = resp->pos;
1151 cxBufferWrite(chunkbuf, 1, chunk5, resp);
1152 cxBufferPutString(resp, "\r\n0\r\n\r\n");
1153
1154
1155 CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS);
1156
1157 CX_TEST_CALL_SUBROUTINE(test_http_client_io, cx_strn(resp->space, resp->size), 200, "OK", buf, blocksz);
1158 CX_TEST_ASSERT(buf->size == ctlen);
1159 CX_TEST_ASSERT(!memcmp(buf->space, resp->space + chunk1_pos, chunk1));
1160 CX_TEST_ASSERT(!memcmp(buf->space + chunk1, resp->space + chunk2_pos, chunk2));
1161 CX_TEST_ASSERT(!memcmp(buf->space + chunk1 + chunk2, resp->space + chunk3_pos, chunk3));
1162 CX_TEST_ASSERT(!memcmp(buf->space + chunk1 + chunk2 + chunk3, resp->space + chunk4_pos, chunk4));
1163 CX_TEST_ASSERT(!memcmp(buf->space + chunk1 + chunk2 + chunk3 + chunk4, resp->space + chunk5_pos, chunk5));
1164
1165 cxBufferFree(resp);
1166 cxBufferFree(buf);
1167 }
1168
1169 static CX_TEST(test_http_client_io_large_chunked_transfer_1024b) {
1170 CX_TEST_DO {
1171 CX_TEST_CALL_SUBROUTINE(test_http_client_io_large_chunked_transfer, 1024);
1063 } 1172 }
1064 } 1173 }
1065 1174
1066 void http_client_add_tests(CxTestSuite *suite) { 1175 void http_client_add_tests(CxTestSuite *suite) {
1067 cx_test_register(suite, test_http_client_send_request); 1176 cx_test_register(suite, test_http_client_send_request);
1072 cx_test_register(suite, test_http_client_io_simple_1b); 1181 cx_test_register(suite, test_http_client_io_simple_1b);
1073 cx_test_register(suite, test_http_client_io_simple_2b); 1182 cx_test_register(suite, test_http_client_io_simple_2b);
1074 cx_test_register(suite, test_http_client_io_simple_3b); 1183 cx_test_register(suite, test_http_client_io_simple_3b);
1075 cx_test_register(suite, test_http_client_io_simple_16b); 1184 cx_test_register(suite, test_http_client_io_simple_16b);
1076 cx_test_register(suite, test_http_client_io_simple_512b); 1185 cx_test_register(suite, test_http_client_io_simple_512b);
1186 cx_test_register(suite, test_http_client_io_large_128b);
1187 cx_test_register(suite, test_http_client_io_large_4096b);
1077 cx_test_register(suite, test_http_client_io_chunked_transfer_1b); 1188 cx_test_register(suite, test_http_client_io_chunked_transfer_1b);
1078 cx_test_register(suite, test_http_client_io_chunked_transfer_2b); 1189 cx_test_register(suite, test_http_client_io_chunked_transfer_2b);
1079 cx_test_register(suite, test_http_client_io_chunked_transfer_8b); 1190 cx_test_register(suite, test_http_client_io_chunked_transfer_8b);
1080 cx_test_register(suite, test_http_client_io_chunked_transfer_64b); 1191 cx_test_register(suite, test_http_client_io_chunked_transfer_64b);
1081 } 1192 cx_test_register(suite, test_http_client_io_large_chunked_transfer_1024b);
1193 }

mercurial