src/server/proxy/httpclient.c

changeset 692
32faa1d6a744
parent 691
4d8a55a7618b
equal deleted inserted replaced
691:4d8a55a7618b 692:32faa1d6a744
272 if(client->req_content_length != 0) { 272 if(client->req_content_length != 0) {
273 if(client_send_request_body(client)) { 273 if(client_send_request_body(client)) {
274 return client->error == 0; 274 return client->error == 0;
275 } 275 }
276 } 276 }
277
278 client->transfer_buffer_pos = 0;
279 client->transfer_buffer_len = 0;
277 } 280 }
278 281
279 // writing complete, switch to read events 282 // writing complete, switch to read events
280 event->events = EVENT_POLLIN; 283 event->events = EVENT_POLLIN;
281 client->stage = 1; 284 client->stage = 1;
282 client->transfer_buffer_pos = 0;
283 client->transfer_buffer_len = 0;
284 285
285 if(client_read_response_header(client)) { 286 if(client_read_response_header(client)) {
286 return client->error == 0; 287 return client->error == 0;
287 } 288 }
288 if(client_read_response_body(client)) { 289 if(client_read_response_body(client)) {
655 656
656 typedef struct TestResponse { 657 typedef struct TestResponse {
657 int status; 658 int status;
658 char *msg; 659 char *msg;
659 CxBuffer *response; 660 CxBuffer *response;
661 int error_interval;
662 int error_test;
660 } TestResponse; 663 } TestResponse;
661 664
662 static int test_response_start(HttpClient *client, int status, char *msg, void *userdata) { 665 static int test_response_start(HttpClient *client, int status, char *msg, void *userdata) {
663 TestResponse *test = userdata; 666 TestResponse *test = userdata;
664 test->status = status; 667 test->status = status;
666 return 0; 669 return 0;
667 } 670 }
668 671
669 static ssize_t test_response_body_write(HttpClient *client, void *buf, size_t size, void *userdata) { 672 static ssize_t test_response_body_write(HttpClient *client, void *buf, size_t size, void *userdata) {
670 TestResponse *test = userdata; 673 TestResponse *test = userdata;
674 if(test->error_interval > 0 && test->error_test >= test->error_interval) {
675 test->error_test = 0;
676 return HTTP_CLIENT_CALLBACK_WOULD_BLOCK;
677 }
678 test->error_test++;
679
671 cxBufferWrite(buf, 1, size, test->response); 680 cxBufferWrite(buf, 1, size, test->response);
672 return size; 681 return size;
673 } 682 }
674 683
675 684
940 cxBufferFree(req); 949 cxBufferFree(req);
941 cxBufferFree(buf); 950 cxBufferFree(buf);
942 } 951 }
943 } 952 }
944 953
945 static CX_TEST_SUBROUTINE(test_http_client_io, cxstring response, int status_code, const char *msg, CxBuffer *out_buf, size_t write_blocksz) { 954 static CX_TEST_SUBROUTINE(test_http_client_io, cxstring response, int status_code, const char *msg, CxBuffer *out_buf, size_t write_blocksz, int error_interval) {
946 EventHandler dummy; 955 EventHandler dummy;
947 HttpClient *client = http_client_new(&dummy); 956 HttpClient *client = http_client_new(&dummy);
948 957
949 int fds[2]; 958 int fds[2];
950 util_socketpair(fds); 959 util_socketpair(fds);
963 972
964 size_t req_header_len = client->transfer_buffer_len; 973 size_t req_header_len = client->transfer_buffer_len;
965 974
966 TestResponse testr = { 0 }; 975 TestResponse testr = { 0 };
967 testr.response = out_buf; 976 testr.response = out_buf;
977 testr.error_interval = error_interval;
968 client->response_start = test_response_start; 978 client->response_start = test_response_start;
969 client->response_start_userdata = &testr; 979 client->response_start_userdata = &testr;
970 client->response_body_write = test_response_body_write; 980 client->response_body_write = test_response_body_write;
971 client->response_body_write_userdata = &testr; 981 client->response_body_write_userdata = &testr;
972 982
996 const char *response_str = response.ptr; 1006 const char *response_str = response.ptr;
997 size_t response_str_len = response.length; 1007 size_t response_str_len = response.length;
998 size_t response_str_pos = 0; 1008 size_t response_str_pos = 0;
999 1009
1000 // send response and do IO 1010 // send response and do IO
1001 while(response_str_pos < response_str_len) { 1011 int in_progress = 1;
1012 while(in_progress) {
1002 size_t len = response_str_len - response_str_pos; 1013 size_t len = response_str_len - response_str_pos;
1003 if(len > write_blocksz) { 1014 if(len > 0) {
1004 len = write_blocksz; 1015 if(len > write_blocksz) {
1005 } 1016 len = write_blocksz;
1006 ssize_t w = write(sock, response_str + response_str_pos, len); 1017 }
1007 if(w == 0) { 1018 ssize_t w = write(sock, response_str + response_str_pos, len);
1008 break; 1019 if(w == 0) {
1009 } 1020 break;
1010 CX_TEST_ASSERT(w > 0); 1021 }
1011 response_str_pos += w; 1022 CX_TEST_ASSERT(w > 0);
1012 1023 response_str_pos += w;
1024 }
1025
1013 ret = client_io(&dummy, &event); 1026 ret = client_io(&dummy, &event);
1027 if(ret == 0) {
1028 in_progress = 0;
1029 }
1014 1030
1015 CX_TEST_ASSERT(!client->error); 1031 CX_TEST_ASSERT(!client->error);
1016 } 1032 }
1017 CX_TEST_ASSERT(response_str_pos == response_str_len); 1033 CX_TEST_ASSERT(response_str_pos == response_str_len);
1018 CX_TEST_ASSERT(testr.status == status_code); 1034 CX_TEST_ASSERT(testr.status == status_code);
1024 close(fds[0]); 1040 close(fds[0]);
1025 close(fds[1]); 1041 close(fds[1]);
1026 http_client_free(client); 1042 http_client_free(client);
1027 } 1043 }
1028 1044
1029 static CX_TEST_SUBROUTINE(test_http_client_io_simple, size_t blocksz) { 1045 static CX_TEST_SUBROUTINE(test_http_client_io_simple, size_t blocksz, int error_interval) {
1030 cxstring response_str = cx_str( 1046 cxstring response_str = cx_str(
1031 "HTTP/1.1 200 OK\r\n" 1047 "HTTP/1.1 200 OK\r\n"
1032 "Host: localhost\r\n" 1048 "Host: localhost\r\n"
1033 "Content-length: 13\r\n" 1049 "Content-length: 13\r\n"
1034 "\r\n" 1050 "\r\n"
1035 "Hello World!\n"); 1051 "Hello World!\n");
1036 CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS); 1052 CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS);
1037 1053
1038 CX_TEST_CALL_SUBROUTINE(test_http_client_io, response_str, 200, "OK", buf, blocksz); 1054 CX_TEST_CALL_SUBROUTINE(test_http_client_io, response_str, 200, "OK", buf, blocksz, error_interval);
1039 CX_TEST_ASSERT(buf->size == 13); 1055 CX_TEST_ASSERT(buf->size == 13);
1040 CX_TEST_ASSERT(!cx_strcmp(cx_strn(buf->space, buf->size), "Hello World!\n")); 1056 CX_TEST_ASSERT(!cx_strcmp(cx_strn(buf->space, buf->size), "Hello World!\n"));
1041 1057
1042 cxBufferFree(buf); 1058 cxBufferFree(buf);
1043 } 1059 }
1044 1060
1045 static CX_TEST(test_http_client_io_simple_1b) { 1061 static CX_TEST(test_http_client_io_simple_1b) {
1046 CX_TEST_DO { 1062 CX_TEST_DO {
1047 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 1); 1063 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 1, 0);
1048 } 1064 }
1049 } 1065 }
1050 1066
1051 static CX_TEST(test_http_client_io_simple_2b) { 1067 static CX_TEST(test_http_client_io_simple_2b) {
1052 CX_TEST_DO { 1068 CX_TEST_DO {
1053 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 2); 1069 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 2, 0);
1054 } 1070 }
1055 } 1071 }
1056 1072
1057 static CX_TEST(test_http_client_io_simple_3b) { 1073 static CX_TEST(test_http_client_io_simple_3b) {
1058 CX_TEST_DO { 1074 CX_TEST_DO {
1059 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 3); 1075 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 3, 0);
1060 } 1076 }
1061 } 1077 }
1062 1078
1063 static CX_TEST(test_http_client_io_simple_16b) { 1079 static CX_TEST(test_http_client_io_simple_16b) {
1064 CX_TEST_DO { 1080 CX_TEST_DO {
1065 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 16); 1081 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 16, 0);
1066 } 1082 }
1067 } 1083 }
1068 1084
1069 static CX_TEST(test_http_client_io_simple_512b) { 1085 static CX_TEST(test_http_client_io_simple_512b) {
1070 CX_TEST_DO { 1086 CX_TEST_DO {
1071 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 512); 1087 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 512, 0);
1072 } 1088 }
1073 } 1089 }
1074 1090
1075 static CX_TEST_SUBROUTINE(test_http_client_io_large, size_t blocksz) { 1091 static CX_TEST_SUBROUTINE(test_http_client_io_large, size_t blocksz) {
1076 int ctlen = 1024*1024*32; 1092 int ctlen = 1024*1024*32;
1087 resp->pos += ctlen; 1103 resp->pos += ctlen;
1088 resp->size += ctlen; 1104 resp->size += ctlen;
1089 1105
1090 CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS); 1106 CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS);
1091 1107
1092 CX_TEST_CALL_SUBROUTINE(test_http_client_io, cx_strn(resp->space, resp->size), 200, "OK", buf, blocksz); 1108 CX_TEST_CALL_SUBROUTINE(test_http_client_io, cx_strn(resp->space, resp->size), 200, "OK", buf, blocksz, 0);
1093 CX_TEST_ASSERT(buf->size == ctlen); 1109 CX_TEST_ASSERT(buf->size == ctlen);
1094 CX_TEST_ASSERT(!memcmp(buf->space, resp->space + content_start, ctlen)); 1110 CX_TEST_ASSERT(!memcmp(buf->space, resp->space + content_start, ctlen));
1095 1111
1096 cxBufferFree(resp); 1112 cxBufferFree(resp);
1097 cxBufferFree(buf); 1113 cxBufferFree(buf);
1107 CX_TEST_DO { 1123 CX_TEST_DO {
1108 CX_TEST_CALL_SUBROUTINE(test_http_client_io_large, 1024); 1124 CX_TEST_CALL_SUBROUTINE(test_http_client_io_large, 1024);
1109 } 1125 }
1110 } 1126 }
1111 1127
1112 static CX_TEST_SUBROUTINE(test_http_client_io_chunked_transfer, size_t blocksz) { 1128 static CX_TEST_SUBROUTINE(test_http_client_io_chunked_transfer, size_t blocksz, int error_interval) {
1113 cxstring response_str = cx_str( 1129 cxstring response_str = cx_str(
1114 "HTTP/1.1 200 OK\r\n" 1130 "HTTP/1.1 200 OK\r\n"
1115 "Host: localhost\r\n" 1131 "Host: localhost\r\n"
1116 "Transfer-encoding: chunked\r\n" 1132 "Transfer-encoding: chunked\r\n"
1117 "\r\n" 1133 "\r\n"
1119 "Hello World!\n" 1135 "Hello World!\n"
1120 "\r\n" 1136 "\r\n"
1121 "0\r\n\r\n"); 1137 "0\r\n\r\n");
1122 CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS); 1138 CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS);
1123 1139
1124 CX_TEST_CALL_SUBROUTINE(test_http_client_io, response_str, 200, "OK", buf, blocksz); 1140 CX_TEST_CALL_SUBROUTINE(test_http_client_io, response_str, 200, "OK", buf, blocksz, error_interval);
1125 CX_TEST_ASSERT(buf->size == 13); 1141 CX_TEST_ASSERT(buf->size == 13);
1126 CX_TEST_ASSERT(!cx_strcmp(cx_strn(buf->space, buf->size), "Hello World!\n")); 1142 CX_TEST_ASSERT(!cx_strcmp(cx_strn(buf->space, buf->size), "Hello World!\n"));
1127 1143
1128 cxBufferFree(buf); 1144 cxBufferFree(buf);
1129 } 1145 }
1130 1146
1131 static CX_TEST(test_http_client_io_chunked_transfer_1b) { 1147 static CX_TEST(test_http_client_io_chunked_transfer_1b) {
1132 CX_TEST_DO { 1148 CX_TEST_DO {
1133 CX_TEST_CALL_SUBROUTINE(test_http_client_io_chunked_transfer, 1); 1149 CX_TEST_CALL_SUBROUTINE(test_http_client_io_chunked_transfer, 1, 0);
1134 } 1150 }
1135 } 1151 }
1136 1152
1137 static CX_TEST(test_http_client_io_chunked_transfer_2b) { 1153 static CX_TEST(test_http_client_io_chunked_transfer_2b) {
1138 CX_TEST_DO { 1154 CX_TEST_DO {
1139 CX_TEST_CALL_SUBROUTINE(test_http_client_io_chunked_transfer, 2); 1155 CX_TEST_CALL_SUBROUTINE(test_http_client_io_chunked_transfer, 2, 0);
1140 } 1156 }
1141 } 1157 }
1142 1158
1143 static CX_TEST(test_http_client_io_chunked_transfer_8b) { 1159 static CX_TEST(test_http_client_io_chunked_transfer_8b) {
1144 CX_TEST_DO { 1160 CX_TEST_DO {
1145 CX_TEST_CALL_SUBROUTINE(test_http_client_io_chunked_transfer, 16); 1161 CX_TEST_CALL_SUBROUTINE(test_http_client_io_chunked_transfer, 16, 0);
1146 } 1162 }
1147 } 1163 }
1148 1164
1149 static CX_TEST(test_http_client_io_chunked_transfer_64b) { 1165 static CX_TEST(test_http_client_io_chunked_transfer_64b) {
1150 CX_TEST_DO { 1166 CX_TEST_DO {
1151 CX_TEST_CALL_SUBROUTINE(test_http_client_io_chunked_transfer, 64); 1167 CX_TEST_CALL_SUBROUTINE(test_http_client_io_chunked_transfer, 64, 0);
1152 } 1168 }
1153 } 1169 }
1154 1170
1155 static CX_TEST_SUBROUTINE(test_http_client_io_large_chunked_transfer, size_t blocksz) { 1171 static CX_TEST_SUBROUTINE(test_http_client_io_large_chunked_transfer, size_t blocksz, int error_interval) {
1156 int chunk1 = 1024*1024*2; 1172 int chunk1 = 1024*1024*2;
1157 int chunk2 = 1024*128; 1173 int chunk2 = 1024*128;
1158 int chunk3 = 123; 1174 int chunk3 = 123;
1159 int chunk4 = 1024*1024*5; 1175 int chunk4 = 1024*1024*5;
1160 int chunk5 = 1024*16; 1176 int chunk5 = 1024*16;
1202 cxBufferPutString(resp, "\r\n0\r\n\r\n"); 1218 cxBufferPutString(resp, "\r\n0\r\n\r\n");
1203 1219
1204 1220
1205 CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS); 1221 CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS);
1206 1222
1207 CX_TEST_CALL_SUBROUTINE(test_http_client_io, cx_strn(resp->space, resp->size), 200, "OK", buf, blocksz); 1223 CX_TEST_CALL_SUBROUTINE(test_http_client_io, cx_strn(resp->space, resp->size), 200, "OK", buf, blocksz, error_interval);
1208 CX_TEST_ASSERT(buf->size == ctlen); 1224 CX_TEST_ASSERT(buf->size == ctlen);
1209 CX_TEST_ASSERT(!memcmp(buf->space, resp->space + chunk1_pos, chunk1)); 1225 CX_TEST_ASSERT(!memcmp(buf->space, resp->space + chunk1_pos, chunk1));
1210 CX_TEST_ASSERT(!memcmp(buf->space + chunk1, resp->space + chunk2_pos, chunk2)); 1226 CX_TEST_ASSERT(!memcmp(buf->space + chunk1, resp->space + chunk2_pos, chunk2));
1211 CX_TEST_ASSERT(!memcmp(buf->space + chunk1 + chunk2, resp->space + chunk3_pos, chunk3)); 1227 CX_TEST_ASSERT(!memcmp(buf->space + chunk1 + chunk2, resp->space + chunk3_pos, chunk3));
1212 CX_TEST_ASSERT(!memcmp(buf->space + chunk1 + chunk2 + chunk3, resp->space + chunk4_pos, chunk4)); 1228 CX_TEST_ASSERT(!memcmp(buf->space + chunk1 + chunk2 + chunk3, resp->space + chunk4_pos, chunk4));
1216 cxBufferFree(buf); 1232 cxBufferFree(buf);
1217 } 1233 }
1218 1234
1219 static CX_TEST(test_http_client_io_large_chunked_transfer_1024b) { 1235 static CX_TEST(test_http_client_io_large_chunked_transfer_1024b) {
1220 CX_TEST_DO { 1236 CX_TEST_DO {
1221 CX_TEST_CALL_SUBROUTINE(test_http_client_io_large_chunked_transfer, 1024); 1237 CX_TEST_CALL_SUBROUTINE(test_http_client_io_large_chunked_transfer, 1024, 0);
1238 }
1239 }
1240
1241 static CX_TEST(test_http_client_io_write_error1) {
1242 CX_TEST_DO {
1243 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 1, 1);
1244 }
1245 }
1246
1247 static CX_TEST(test_http_client_io_write_error2) {
1248 CX_TEST_DO {
1249 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 1, 2);
1250 }
1251 }
1252
1253 static CX_TEST(test_http_client_io_write_error3) {
1254 CX_TEST_DO {
1255 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 1, 3);
1256 }
1257 }
1258
1259 static CX_TEST(test_http_client_io_write_blsz8_error1) {
1260 CX_TEST_DO {
1261 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 8, 1);
1262 }
1263 }
1264
1265 static CX_TEST(test_http_client_io_write_blsz8_error2) {
1266 CX_TEST_DO {
1267 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 8, 2);
1268 }
1269 }
1270
1271 static CX_TEST(test_http_client_io_write_blsz8_error3) {
1272 CX_TEST_DO {
1273 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 8, 3);
1222 } 1274 }
1223 } 1275 }
1224 1276
1225 void http_client_add_tests(CxTestSuite *suite) { 1277 void http_client_add_tests(CxTestSuite *suite) {
1226 cx_test_register(suite, test_http_client_send_request); 1278 cx_test_register(suite, test_http_client_send_request);
1238 cx_test_register(suite, test_http_client_io_chunked_transfer_1b); 1290 cx_test_register(suite, test_http_client_io_chunked_transfer_1b);
1239 cx_test_register(suite, test_http_client_io_chunked_transfer_2b); 1291 cx_test_register(suite, test_http_client_io_chunked_transfer_2b);
1240 cx_test_register(suite, test_http_client_io_chunked_transfer_8b); 1292 cx_test_register(suite, test_http_client_io_chunked_transfer_8b);
1241 cx_test_register(suite, test_http_client_io_chunked_transfer_64b); 1293 cx_test_register(suite, test_http_client_io_chunked_transfer_64b);
1242 cx_test_register(suite, test_http_client_io_large_chunked_transfer_1024b); 1294 cx_test_register(suite, test_http_client_io_large_chunked_transfer_1024b);
1243 } 1295 cx_test_register(suite, test_http_client_io_write_error1);
1296 cx_test_register(suite, test_http_client_io_write_error2);
1297 cx_test_register(suite, test_http_client_io_write_error3);
1298 cx_test_register(suite, test_http_client_io_write_blsz8_error1);
1299 cx_test_register(suite, test_http_client_io_write_blsz8_error2);
1300 cx_test_register(suite, test_http_client_io_write_blsz8_error3);
1301 }

mercurial