#include #include #include #include #include "utils.hpp" #include "404.hpp" extern "C" { int proxy_image(struct http_request*); static int proxy_start(struct http_request*); static int proxy_end(struct http_request*); } static struct http_state proxy_states[] = { KORE_HTTP_STATE(proxy_start), KORE_HTTP_STATE(proxy_end) }; int proxy_image(struct http_request* req) { return http_state_run(proxy_states, 2, req); } static int proxy_start(struct http_request* req) { // /proxy/ const char* filename = &(req->path[7]); std::string url = "https://i.imgur.com/"; url.append(filename); struct kore_curl* client = (kore_curl*)http_state_create(req, sizeof(*client), NULL); if (!kore_curl_init(client, url.c_str(), KORE_CURL_ASYNC)) { http_state_cleanup(req); kore_log(LOG_NOTICE, "failed to initialize curl client"); std::string error_page = build_error_page("Failed to initialize curl client"); http_response(req, 500, error_page.c_str(), error_page.length()); return HTTP_STATE_COMPLETE; } const char* header_value; if (http_request_header(req, "Content-Range", &header_value) == KORE_RESULT_OK) { kore_curl_http_set_header(client, "Content-Range", header_value); } if (http_request_header(req, "If-None-Match", &header_value) == KORE_RESULT_OK) { kore_curl_http_set_header(client, "If-None-Match", header_value); } if (http_request_header(req, "If-Match", &header_value) == KORE_RESULT_OK) { kore_curl_http_set_header(client, "If-Match", header_value); } if (http_request_header(req, "If-Modified-Since", &header_value) == KORE_RESULT_OK) { kore_curl_http_set_header(client, "If-Modified-Since", header_value); } if (http_request_header(req, "If-Unmodified-Since", &header_value) == KORE_RESULT_OK) { kore_curl_http_set_header(client, "If-Unmodified-Since", header_value); } // hmm if (http_request_header(req, "Cache-Control", &header_value) == KORE_RESULT_OK) { kore_curl_http_set_header(client, "Cache-Control", header_value); } kore_curl_http_setup(client, HTTP_METHOD_GET, NULL, 0); kore_curl_bind_request(client, req); kore_curl_run(client); req->fsm_state = 1; return HTTP_STATE_RETRY; } static int proxy_end(struct http_request* req) { struct kore_curl* client = (kore_curl*)http_state_get(req); if (!kore_curl_success(client)) { kore_curl_logerror(client); std::string error = "Failed to contact Imgur: "; error.append(kore_curl_strerror(client)); kore_curl_cleanup(client); http_state_cleanup(req); std::string error_page = build_error_page(error.c_str()); http_response(req, 500, error_page.c_str(), error_page.length()); return HTTP_STATE_COMPLETE; } // imgur redirects to https://imgur.com/ when image 404s if (client->http.status == 302) { kore_curl_cleanup(client); http_state_cleanup(req); not_found(req); return HTTP_STATE_COMPLETE; } const char* header_value; if (kore_curl_http_get_header(client, "Range", &header_value) == KORE_RESULT_OK) { http_response_header(req, "Range", header_value); } if (kore_curl_http_get_header(client, "Accept-Ranges", &header_value) == KORE_RESULT_OK) { http_response_header(req, "Accept-Ranges", header_value); } if (kore_curl_http_get_header(client, "ETag", &header_value) == KORE_RESULT_OK) { http_response_header(req, "ETag", header_value); } if (kore_curl_http_get_header(client, "Content-Type", &header_value) == KORE_RESULT_OK) { http_response_header(req, "Content-Type", header_value); } if (kore_curl_http_get_header(client, "Cache-Control", &header_value) == KORE_RESULT_OK) { http_response_header(req, "Cache-Control", header_value); } const u_int8_t* body; size_t len; kore_curl_response_as_bytes(client, &body, &len); http_response(req, client->http.status, body, len); kore_curl_cleanup(client); http_state_cleanup(req); return HTTP_STATE_COMPLETE; }