108 lines
4.3 KiB
C++
108 lines
4.3 KiB
C++
#include <kore/kore.h>
|
|
#include <kore/http.h>
|
|
#include <kore/curl.h>
|
|
#include <string>
|
|
#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_ERR, "failed to initialize curl client");
|
|
std::string error_page = build_error_page("Failed to initialize curl client");
|
|
http_response_header(req, "Content-Type", "text/html");
|
|
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_header(req, "Content-Type", "text/html");
|
|
http_response(req, 500, error_page.c_str(), error_page.length());
|
|
return HTTP_STATE_COMPLETE;
|
|
}
|
|
// imgur redirects to https://imgur.com/<rest of path> 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;
|
|
}
|