diff --git a/server/core/admin.cc b/server/core/admin.cc index 692278de2..9af7373ba 100644 --- a/server/core/admin.cc +++ b/server/core/admin.cc @@ -11,7 +11,7 @@ * Public License. */ -#include +#include "maxscale/admin.hh" #include #include @@ -24,10 +24,11 @@ #include #include -#include "maxscale/admin.hh" #include "maxscale/resource.hh" #include "maxscale/http.hh" +using std::string; + static struct MHD_Daemon* http_daemon = NULL; int kv_iter(void *cls, @@ -35,7 +36,7 @@ int kv_iter(void *cls, const char *key, const char *value) { - size_t* rval = (size_t*) cls; + size_t* rval = (size_t*)cls; if (strcmp(key, "Content-Length") == 0) { @@ -46,16 +47,17 @@ int kv_iter(void *cls, return MHD_YES; } -static inline size_t request_data_length(struct MHD_Connection *connection) +static inline size_t request_data_length(MHD_Connection *connection) { size_t rval = 0; MHD_get_connection_values(connection, MHD_HEADER_KIND, kv_iter, &rval); return rval; } -static bool modifies_data(struct MHD_Connection *connection, string method) +static bool modifies_data(MHD_Connection *connection, string method) { - return (method == "POST" || method == "PUT" || method == "PATCH") && + return (method == MHD_HTTP_METHOD_POST || method == MHD_HTTP_METHOD_PUT || + method == MHD_HTTP_METHOD_PATCH || method == MHD_HTTP_METHOD_DELETE) && request_data_length(connection); } @@ -75,7 +77,7 @@ int Client::process(string url, string method, const char* upload_data, size_t * if (m_data.length() && (json = json_loadb(m_data.c_str(), m_data.size(), 0, &err)) == NULL) { - struct MHD_Response *response = + MHD_Response *response = MHD_create_response_from_buffer(0, NULL, MHD_RESPMEM_PERSISTENT); MHD_queue_response(m_connection, MHD_HTTP_BAD_REQUEST, response); MHD_destroy_response(response); @@ -95,19 +97,16 @@ int Client::process(string url, string method, const char* upload_data, size_t * data = mxs::json_dump(js, flags); } - struct MHD_Response *response = + MHD_Response *response = MHD_create_response_from_buffer(data.size(), (void*)data.c_str(), MHD_RESPMEM_MUST_COPY); - string http_date = http_get_date(); + const Headers& headers = reply.get_headers(); - MHD_add_response_header(response, "Date", http_date.c_str()); - - // TODO: calculate modification times - MHD_add_response_header(response, "Last-Modified", http_date.c_str()); - - // This ETag is the base64 encoding of `not-yet-implemented` - MHD_add_response_header(response, "ETag", "bm90LXlldC1pbXBsZW1lbnRlZAo"); + for (Headers::const_iterator it = headers.begin(); it != headers.end(); it++) + { + MHD_add_response_header(response, it->first.c_str(), it->second.c_str()); + } int rval = MHD_queue_response(m_connection, reply.get_code(), response); MHD_destroy_response(response); @@ -116,7 +115,7 @@ int Client::process(string url, string method, const char* upload_data, size_t * } void close_client(void *cls, - struct MHD_Connection *connection, + MHD_Connection *connection, void **con_cls, enum MHD_RequestTerminationCode toe) { @@ -124,7 +123,7 @@ void close_client(void *cls, delete client; } -bool do_auth(struct MHD_Connection *connection) +bool do_auth(MHD_Connection *connection) { const char *admin_user = config_get_global_options()->admin_user; const char *admin_pw = config_get_global_options()->admin_password; @@ -138,7 +137,7 @@ bool do_auth(struct MHD_Connection *connection) { rval = false; static char error_resp[] = "Access denied\r\n"; - struct MHD_Response *resp = + MHD_Response *resp = MHD_create_response_from_buffer(sizeof(error_resp) - 1, error_resp, MHD_RESPMEM_PERSISTENT); @@ -150,7 +149,7 @@ bool do_auth(struct MHD_Connection *connection) } int handle_client(void *cls, - struct MHD_Connection *connection, + MHD_Connection *connection, const char *url, const char *method, const char *version, diff --git a/server/core/httpresponse.cc b/server/core/httpresponse.cc index 414a6710e..e0c6e4982 100644 --- a/server/core/httpresponse.cc +++ b/server/core/httpresponse.cc @@ -28,13 +28,18 @@ HttpResponse::HttpResponse(int code, json_t* response): m_body(response), m_code(code) { + string http_date = http_get_date(); + add_header(HTTP_RESPONSE_HEADER_DATE, http_date); + add_header(HTTP_RESPONSE_HEADER_LAST_MODIFIED, http_date); + // This ETag is the base64 encoding of `not-yet-implemented` + add_header(HTTP_RESPONSE_HEADER_ETAG, "bm90LXlldC1pbXBsZW1lbnRlZAo"); } HttpResponse::HttpResponse(const HttpResponse& response): - m_body(response.m_body), - m_code(response.m_code) + m_body(json_incref(response.m_body)), + m_code(response.m_code), + m_headers(response.m_headers) { - json_incref(m_body); } HttpResponse& HttpResponse::operator=(const HttpResponse& response) @@ -42,6 +47,7 @@ HttpResponse& HttpResponse::operator=(const HttpResponse& response) json_t* body = m_body; m_body = json_incref(response.m_body); m_code = response.m_code; + m_headers = response.m_headers; json_decref(body); return *this; } @@ -59,7 +65,23 @@ json_t* HttpResponse::get_response() const return m_body; } +void HttpResponse::drop_response() +{ + json_decref(m_body); + m_body = NULL; +} + int HttpResponse::get_code() const { return m_code; } + +void HttpResponse::add_header(const string& key, const string& value) +{ + m_headers[key] = value; +} + +const Headers& HttpResponse::get_headers() const +{ + return m_headers; +} diff --git a/server/core/maxscale/admin.hh b/server/core/maxscale/admin.hh index a31006524..d9bc3f765 100644 --- a/server/core/maxscale/admin.hh +++ b/server/core/maxscale/admin.hh @@ -19,8 +19,6 @@ #include -using std::string; - class Client { public: @@ -30,7 +28,7 @@ public: * * @param connection The connection handle for this client */ - Client(struct MHD_Connection *connection): + Client(MHD_Connection *connection): m_connection(connection) { } @@ -52,11 +50,11 @@ public: * * @return MHD_YES on success, MHD_NO on error */ - int process(string url, string method, const char* data, size_t *size); + int process(std::string url, std::string method, const char* data, size_t *size); private: - struct MHD_Connection* m_connection; /**< Connection handle */ - string m_data; /**< Uploaded data */ + MHD_Connection* m_connection; /**< Connection handle */ + std::string m_data; /**< Uploaded data */ }; /** diff --git a/server/core/maxscale/httprequest.hh b/server/core/maxscale/httprequest.hh index 9bb0fc1b6..7863dc002 100644 --- a/server/core/maxscale/httprequest.hh +++ b/server/core/maxscale/httprequest.hh @@ -119,7 +119,7 @@ public: * * @return Raw JSON body or NULL if no body is defined */ - json_t* get_json() + json_t* get_json() const { return m_json.get(); } diff --git a/server/core/maxscale/httpresponse.hh b/server/core/maxscale/httpresponse.hh index 79498f0ac..3bf96672d 100644 --- a/server/core/maxscale/httpresponse.hh +++ b/server/core/maxscale/httpresponse.hh @@ -23,6 +23,16 @@ #include "http.hh" +/** + * A list of default headers that are generated with each response + */ +#define HTTP_RESPONSE_HEADER_DATE "Date" +#define HTTP_RESPONSE_HEADER_LAST_MODIFIED "Last-Modified" +#define HTTP_RESPONSE_HEADER_ETAG "ETag" +#define HTTP_RESPONSE_HEADER_ACCEPT "Accept" + +typedef std::map Headers; + class HttpResponse { public: @@ -45,6 +55,13 @@ public: */ json_t* get_response() const; + /** + * @brief Drop response body + * + * This discards the message body. + */ + void drop_response(); + /** * @brief Get the HTTP response code * @@ -52,7 +69,23 @@ public: */ int get_code() const; + /** + * @brief Add an extra header to this response + * + * @param key Header name + * @param value Header value + */ + void add_header(const std::string& key, const std::string& value); + + /** + * @brief Get request headers + * + * @return Headers of this request + */ + const Headers& get_headers() const; + private: json_t* m_body; /**< Message body */ int m_code; /**< The HTTP code for the response */ + Headers m_headers; /**< Extra headers */ };