| 683 | static const char* verbs[] = { "GET", "HEAD", "POST" }; |
| 684 | |
| 685 | static cc_result HttpBackend_Do(struct HttpRequest* req) { |
| 686 | struct HttpClientState state; |
| 687 | cc_result res; |
| 688 | HttpClientState_Init(&state, req); |
| 689 | |
| 690 | for (;;) { |
| 691 | Platform_Log4("Fetching %c%s%s (%c)", state.url.https ? "https://" : "http://", |
| 692 | &state.url.address, &state.url.resource, verbs[req->requestType]); |
| 693 | |
| 694 | res = HttpBackend_PerformRequest(&state); |
| 695 | /* TODO: Can we handle this while preserving the TCP connection */ |
| 696 | if (res == SSL_ERR_CONTEXT_DEAD && !state.retried) { |
| 697 | Platform_LogConst("Resetting connection due to SSL context being dropped.."); |
| 698 | res = HttpBackend_PerformRequest(&state); |
| 699 | state.retried = true; |
| 700 | } |
| 701 | if (res == HTTP_ERR_NO_RESPONSE && !state.retried) { |
| 702 | Platform_LogConst("Resetting connection due to empty response.."); |
| 703 | res = HttpBackend_PerformRequest(&state); |
| 704 | state.retried = true; |
| 705 | } |
| 706 | if (res == ReturnCode_SocketDropped && !state.retried) { |
| 707 | Platform_LogConst("Resetting connection due to being dropped.."); |
| 708 | res = HttpBackend_PerformRequest(&state); |
| 709 | state.retried = true; |
| 710 | } |
| 711 | |
| 712 | if (res || !HttpClient_IsRedirect(req)) break; |
| 713 | if (state.redirects >= 20) return HTTP_ERR_REDIRECTS; |
| 714 | |
| 715 | /* TODO FOLLOW LOCATION PROPERLY */ |
| 716 | state.redirects++; |
| 717 | res = HttpClient_HandleRedirect(&state); |
| 718 | if (res) break; |
| 719 | HttpClientState_Reset(&state); |
| 720 | } |
| 721 | return res; |
| 722 | } |
| 723 | |
| 724 | static cc_bool HttpBackend_DescribeError(cc_result res, cc_string* dst) { |
| 725 | return SSLBackend_DescribeError(res, dst); |
no test coverage detected