From b2e94fc73c1c51d1dc8c0f790aba3e9cb355671d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Tue, 2 May 2017 16:34:41 +0300 Subject: [PATCH] MXS-1220: Add versioned URLs Added versioning to URLs. This should allow somewhat safe modification to the API after it has been finished. --- server/core/admin.cc | 7 ++++- server/core/httprequest.cc | 38 ++++++++++++++++++---------- server/core/httpresponse.cc | 5 ++++ server/core/maxscale/httprequest.hh | 13 +++++++++- server/core/maxscale/httpresponse.hh | 1 + 5 files changed, 49 insertions(+), 15 deletions(-) diff --git a/server/core/admin.cc b/server/core/admin.cc index c54072b85..558b8a0fc 100644 --- a/server/core/admin.cc +++ b/server/core/admin.cc @@ -102,7 +102,12 @@ int Client::process(string url, string method, const char* upload_data, size_t * } HttpRequest request(m_connection, url, method, json); - HttpResponse reply = resource_handle_request(request); + HttpResponse reply(MHD_HTTP_NOT_FOUND); + + if (request.validate_api_version()) + { + reply = resource_handle_request(request); + } string data; diff --git a/server/core/httprequest.cc b/server/core/httprequest.cc index 12301c0f8..f8580411b 100644 --- a/server/core/httprequest.cc +++ b/server/core/httprequest.cc @@ -74,20 +74,12 @@ static void process_uri(string& uri, std::deque& uri_parts) my_uri.erase(my_uri.begin()); } - if (my_uri.length() == 0) + while (my_uri.length() > 0) { - /** Special handling for the / resource */ - uri_parts.push_back(""); - } - else - { - while (my_uri.length() > 0) - { - size_t pos = my_uri.find("/"); - string part = pos == string::npos ? my_uri : my_uri.substr(0, pos); - my_uri.erase(0, pos == string::npos ? pos : pos + 1); - uri_parts.push_back(part); - } + size_t pos = my_uri.find("/"); + string part = pos == string::npos ? my_uri : my_uri.substr(0, pos); + my_uri.erase(0, pos == string::npos ? pos : pos + 1); + uri_parts.push_back(part); } } @@ -102,9 +94,29 @@ HttpRequest::HttpRequest(struct MHD_Connection *connection, string url, string m m_hostname = mxs_admin_https_enabled() ? HttpRequest::HTTPS_PREFIX : HttpRequest::HTTP_PREFIX; m_hostname += get_header(HTTP_HOST_HEADER); + + if (m_hostname[m_hostname.size() - 1] != '/') + { + m_hostname += "/"; + } + + m_hostname += MXS_REST_API_VERSION; } HttpRequest::~HttpRequest() { } +bool HttpRequest::validate_api_version() +{ + bool rval = false; + + if (m_resource_parts.size() > 0 && + m_resource_parts[0] == MXS_REST_API_VERSION) + { + m_resource_parts.pop_front(); + rval = true; + } + + return rval; +} diff --git a/server/core/httpresponse.cc b/server/core/httpresponse.cc index e0c6e4982..8708d7c11 100644 --- a/server/core/httpresponse.cc +++ b/server/core/httpresponse.cc @@ -33,6 +33,11 @@ HttpResponse::HttpResponse(int code, json_t* response): 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"); + + if (m_body) + { + add_header(HTTP_RESPONSE_HEADER_CONTENT_TYPE, "application/json"); + } } HttpResponse::HttpResponse(const HttpResponse& response): diff --git a/server/core/maxscale/httprequest.hh b/server/core/maxscale/httprequest.hh index 6986d676a..e99875c3d 100644 --- a/server/core/maxscale/httprequest.hh +++ b/server/core/maxscale/httprequest.hh @@ -26,6 +26,9 @@ #include "http.hh" +// The API version part of the URL +#define MXS_REST_API_VERSION "v1" + static int value_iterator(void *cls, enum MHD_ValueKind kind, const char *key, @@ -160,6 +163,14 @@ public: { return m_hostname.c_str(); } + + /** + * @brief Drop the API version prefix + * + * @return True if prefix is present and was successfully removed + */ + bool validate_api_version(); + private: /** Constants */ @@ -173,5 +184,5 @@ private: std::deque m_resource_parts; /**< @c m_resource split into parts */ std::string m_verb; /**< Request method */ std::string m_hostname; /**< The value of the Host header */ - struct MHD_Connection* m_connection; + struct MHD_Connection* m_connection; }; diff --git a/server/core/maxscale/httpresponse.hh b/server/core/maxscale/httpresponse.hh index 3bf96672d..4e5801f45 100644 --- a/server/core/maxscale/httpresponse.hh +++ b/server/core/maxscale/httpresponse.hh @@ -30,6 +30,7 @@ #define HTTP_RESPONSE_HEADER_LAST_MODIFIED "Last-Modified" #define HTTP_RESPONSE_HEADER_ETAG "ETag" #define HTTP_RESPONSE_HEADER_ACCEPT "Accept" +#define HTTP_RESPONSE_HEADER_CONTENT_TYPE "Content-Type" typedef std::map Headers;