Set original response content type when proxying to leader.

This commit is contained in:
kishorenc 2020-08-06 18:18:55 +05:30
parent fd81cbb976
commit 7b7af9453d
4 changed files with 44 additions and 22 deletions

View File

@ -1,6 +1,7 @@
#pragma once
#include <string>
#include <map>
#include <curl/curl.h>
/*
@ -17,9 +18,9 @@ private:
static size_t curl_write (void *contents, size_t size, size_t nmemb, std::string *s);
static CURL* init_curl(const std::string & url, std::string & buffer);
static CURL* init_curl(const std::string& url, std::string& response);
static long perform_curl(CURL *curl);
static long perform_curl(CURL *curl, std::map<std::string, std::string>& res_headers);
public:
static HttpClient & get_instance() {
@ -32,13 +33,17 @@ public:
void init(const std::string & api_key);
static long get_response(const std::string & url, std::string & response, long timeout_ms=4000);
static long get_response(const std::string& url, std::string& response,
std::map<std::string, std::string>& res_headers, long timeout_ms=4000);
static long delete_response(const std::string & url, std::string & response, long timeout_ms=120000);
static long delete_response(const std::string& url, std::string& response,
std::map<std::string, std::string>& res_headers, long timeout_ms=120000);
static long post_response(const std::string & url, const std::string & body, std::string & response,
long timeout_ms=4000);
std::map<std::string, std::string>& res_headers, long timeout_ms=4000);
static long put_response(const std::string & url, const std::string & body, std::string & response,
long timeout_ms=4000);
std::map<std::string, std::string>& res_headers, long timeout_ms=4000);
static void extract_response_headers(CURL* curl, std::map<std::string, std::string> &res_headers);
};

View File

@ -7,7 +7,8 @@
std::string HttpClient::api_key = "";
std::string HttpClient::ca_cert_path = "";
long HttpClient::post_response(const std::string &url, const std::string &body, std::string &response, long timeout_ms) {
long HttpClient::post_response(const std::string &url, const std::string &body, std::string &response,
std::map<std::string, std::string>& res_headers, long timeout_ms) {
CURL *curl = init_curl(url, response);
if(curl == nullptr) {
return 500;
@ -15,10 +16,11 @@ long HttpClient::post_response(const std::string &url, const std::string &body,
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str());
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, timeout_ms);
return perform_curl(curl);
return perform_curl(curl, res_headers);
}
long HttpClient::put_response(const std::string &url, const std::string &body, std::string &response, long timeout_ms) {
long HttpClient::put_response(const std::string &url, const std::string &body, std::string &response,
std::map<std::string, std::string>& res_headers, long timeout_ms) {
CURL *curl = init_curl(url, response);
if(curl == nullptr) {
return 500;
@ -27,10 +29,11 @@ long HttpClient::put_response(const std::string &url, const std::string &body, s
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str());
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, timeout_ms);
return perform_curl(curl);
return perform_curl(curl, res_headers);
}
long HttpClient::delete_response(const std::string &url, std::string &response, long timeout_ms) {
long HttpClient::delete_response(const std::string &url, std::string &response,
std::map<std::string, std::string>& res_headers, long timeout_ms) {
CURL *curl = init_curl(url, response);
if(curl == nullptr) {
return 500;
@ -38,17 +41,18 @@ long HttpClient::delete_response(const std::string &url, std::string &response,
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, timeout_ms);
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
return perform_curl(curl);
return perform_curl(curl, res_headers);
}
long HttpClient::get_response(const std::string &url, std::string &response, long timeout_ms) {
long HttpClient::get_response(const std::string &url, std::string &response,
std::map<std::string, std::string>& res_headers, long timeout_ms) {
CURL *curl = init_curl(url, response);
if(curl == nullptr) {
return 500;
}
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, timeout_ms);
return perform_curl(curl);
return perform_curl(curl, res_headers);
}
void HttpClient::init(const std::string &api_key) {
@ -74,7 +78,7 @@ void HttpClient::init(const std::string &api_key) {
}
}
long HttpClient::perform_curl(CURL *curl) {
long HttpClient::perform_curl(CURL *curl, std::map<std::string, std::string>& res_headers) {
struct curl_slist *chunk = nullptr;
std::string api_key_header = std::string("x-typesense-api-key: ") + HttpClient::api_key;
chunk = curl_slist_append(chunk, api_key_header.c_str());
@ -89,18 +93,26 @@ long HttpClient::perform_curl(CURL *curl) {
long http_code = 500;
curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &http_code);
extract_response_headers(curl, res_headers);
curl_easy_cleanup(curl);
return http_code == 0 ? 500 : http_code;
}
CURL *HttpClient::init_curl(const std::string &url, std::string &buffer) {
void HttpClient::extract_response_headers(CURL* curl, std::map<std::string, std::string> &res_headers) {
char* content_type;
curl_easy_getinfo (curl, CURLINFO_CONTENT_TYPE, &content_type);
res_headers.emplace("content-type", content_type);
}
CURL *HttpClient::init_curl(const std::string& url, std::string& response) {
CURL *curl = curl_easy_init();
if(curl == nullptr) {
nlohmann::json res;
res["message"] = "Failed to initialize HTTP client.";
buffer = res.dump();
response = res.dump();
return nullptr;
}
@ -118,7 +130,7 @@ CURL *HttpClient::init_curl(const std::string &url, std::string &buffer) {
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HttpClient::curl_write);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
return curl;
}

View File

@ -379,7 +379,7 @@ int HttpServer::catch_all_handler(h2o_handler_t *_self, h2o_req_t *req) {
}
// for writes, we defer to replication_state
if(http_method != "GET") {
if(http_method == "POST" || http_method == "PUT" || http_method == "DELETE") {
self->http_server->get_replication_state()->write(request, response);
return 0;
}

View File

@ -114,17 +114,22 @@ void ReplicationState::write(http_req* request, http_res* response) {
const std::string & path = std::string(raw_req->path.base, raw_req->path.len);
std::string url = scheme + "://" + leader_host_port + path;
std::map<std::string, std::string> res_headers;
if(request->http_method == "POST") {
std::string api_res;
long status = HttpClient::post_response(url, request->body, api_res);
long status = HttpClient::post_response(url, request->body, api_res, res_headers);
response->content_type_header = res_headers["content-type"];
response->set_body(status, api_res);
} else if(request->http_method == "PUT") {
std::string api_res;
long status = HttpClient::put_response(url, request->body, api_res);
long status = HttpClient::put_response(url, request->body, api_res, res_headers);
response->content_type_header = res_headers["content-type"];
response->set_body(status, api_res);
} else if(request->http_method == "DELETE") {
std::string api_res;
long status = HttpClient::delete_response(url, api_res);
long status = HttpClient::delete_response(url, api_res, res_headers);
response->content_type_header = res_headers["content-type"];
response->set_body(status, api_res);
} else {
const std::string& err = "Forwarding for http method not implemented: " + request->http_method;