MXS-1220: Add versioned URLs
Added versioning to URLs. This should allow somewhat safe modification to the API after it has been finished.
This commit is contained in:
@ -102,7 +102,12 @@ int Client::process(string url, string method, const char* upload_data, size_t *
|
|||||||
}
|
}
|
||||||
|
|
||||||
HttpRequest request(m_connection, url, method, json);
|
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;
|
string data;
|
||||||
|
|
||||||
|
@ -74,20 +74,12 @@ static void process_uri(string& uri, std::deque<string>& uri_parts)
|
|||||||
my_uri.erase(my_uri.begin());
|
my_uri.erase(my_uri.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (my_uri.length() == 0)
|
while (my_uri.length() > 0)
|
||||||
{
|
{
|
||||||
/** Special handling for the / resource */
|
size_t pos = my_uri.find("/");
|
||||||
uri_parts.push_back("");
|
string part = pos == string::npos ? my_uri : my_uri.substr(0, pos);
|
||||||
}
|
my_uri.erase(0, pos == string::npos ? pos : pos + 1);
|
||||||
else
|
uri_parts.push_back(part);
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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 = mxs_admin_https_enabled() ? HttpRequest::HTTPS_PREFIX : HttpRequest::HTTP_PREFIX;
|
||||||
m_hostname += get_header(HTTP_HOST_HEADER);
|
m_hostname += get_header(HTTP_HOST_HEADER);
|
||||||
|
|
||||||
|
if (m_hostname[m_hostname.size() - 1] != '/')
|
||||||
|
{
|
||||||
|
m_hostname += "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
m_hostname += MXS_REST_API_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpRequest::~HttpRequest()
|
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;
|
||||||
|
}
|
||||||
|
@ -33,6 +33,11 @@ HttpResponse::HttpResponse(int code, json_t* response):
|
|||||||
add_header(HTTP_RESPONSE_HEADER_LAST_MODIFIED, http_date);
|
add_header(HTTP_RESPONSE_HEADER_LAST_MODIFIED, http_date);
|
||||||
// This ETag is the base64 encoding of `not-yet-implemented`
|
// This ETag is the base64 encoding of `not-yet-implemented`
|
||||||
add_header(HTTP_RESPONSE_HEADER_ETAG, "bm90LXlldC1pbXBsZW1lbnRlZAo");
|
add_header(HTTP_RESPONSE_HEADER_ETAG, "bm90LXlldC1pbXBsZW1lbnRlZAo");
|
||||||
|
|
||||||
|
if (m_body)
|
||||||
|
{
|
||||||
|
add_header(HTTP_RESPONSE_HEADER_CONTENT_TYPE, "application/json");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpResponse::HttpResponse(const HttpResponse& response):
|
HttpResponse::HttpResponse(const HttpResponse& response):
|
||||||
|
@ -26,6 +26,9 @@
|
|||||||
|
|
||||||
#include "http.hh"
|
#include "http.hh"
|
||||||
|
|
||||||
|
// The API version part of the URL
|
||||||
|
#define MXS_REST_API_VERSION "v1"
|
||||||
|
|
||||||
static int value_iterator(void *cls,
|
static int value_iterator(void *cls,
|
||||||
enum MHD_ValueKind kind,
|
enum MHD_ValueKind kind,
|
||||||
const char *key,
|
const char *key,
|
||||||
@ -160,6 +163,14 @@ public:
|
|||||||
{
|
{
|
||||||
return m_hostname.c_str();
|
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:
|
private:
|
||||||
|
|
||||||
/** Constants */
|
/** Constants */
|
||||||
@ -173,5 +184,5 @@ private:
|
|||||||
std::deque<std::string> m_resource_parts; /**< @c m_resource split into parts */
|
std::deque<std::string> m_resource_parts; /**< @c m_resource split into parts */
|
||||||
std::string m_verb; /**< Request method */
|
std::string m_verb; /**< Request method */
|
||||||
std::string m_hostname; /**< The value of the Host header */
|
std::string m_hostname; /**< The value of the Host header */
|
||||||
struct MHD_Connection* m_connection;
|
struct MHD_Connection* m_connection;
|
||||||
};
|
};
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#define HTTP_RESPONSE_HEADER_LAST_MODIFIED "Last-Modified"
|
#define HTTP_RESPONSE_HEADER_LAST_MODIFIED "Last-Modified"
|
||||||
#define HTTP_RESPONSE_HEADER_ETAG "ETag"
|
#define HTTP_RESPONSE_HEADER_ETAG "ETag"
|
||||||
#define HTTP_RESPONSE_HEADER_ACCEPT "Accept"
|
#define HTTP_RESPONSE_HEADER_ACCEPT "Accept"
|
||||||
|
#define HTTP_RESPONSE_HEADER_CONTENT_TYPE "Content-Type"
|
||||||
|
|
||||||
typedef std::map<std::string, std::string> Headers;
|
typedef std::map<std::string, std::string> Headers;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user