Files
scylladb/http/routes.hh
Amnon Heiman c129b86589 Adding the api_docs to http
This is a migration of the api_docs from OSv. It replaces the static
api-doc.json with a dynamic generated reply, this allows to register API
in run time.

The api_registry_builder is a helper class that holds the file and api
path, simplifying registring both the api_doc handler and registering
additional API.

To use the api_doc, first generate a api_registry_builder.

The registry supply two functions, one for registring the api_doc
handler and one for registering an API.

Both function are passed as an argument for the set_routes method of the
http_server_control object.

To find the handler, the get_exact_match in the routes object was needed
to become public.

Signed-off-by: Amnon Heiman <amnon@cloudius-systems.com>
2015-04-05 11:39:48 +03:00

177 lines
5.0 KiB
C++

/*
* This file is open source software, licensed to you under the terms
* of the Apache License, Version 2.0 (the "License"). See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. You may not use this file except in compliance with the License.
*
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/*
* Copyright 2015 Cloudius Systems
*/
#ifndef ROUTES_HH_
#define ROUTES_HH_
#include "matchrules.hh"
#include "handlers.hh"
#include "common.hh"
#include "reply.hh"
#include <boost/program_options/variables_map.hpp>
#include <unordered_map>
#include <vector>
#include "core/future-util.hh"
namespace httpd {
/**
* The url helps defining a route.
*/
class url {
public:
/**
* Move constructor
*/
url(url&&) = default;
/**
* Construct with a url path as it's parameter
* @param path the url path to be used
*/
url(const sstring& path)
: _path(path) {
}
/**
* Adds a parameter that matches untill the end of the URL.
* @param param the parmaeter name
* @return the current url
*/
url& remainder(const sstring& param) {
this->_param = param;
return *this;
}
sstring _path;
sstring _param;
};
/**
* routes object do the request dispatching according to the url.
* It uses two decision mechanism exact match, if a url matches exactly
* (an optional leading slash is permitted) it is choosen
* If not, the matching rules are used.
* matching rules are evaluated by their insertion order
*/
class routes {
public:
/**
* The destructor deletes the match rules and handlers
*/
~routes();
/**
* adding a handler as an exact match
* @param url the url to match (note that url should start with /)
* @param handler the desire handler
* @return it self
*/
routes& put(operation_type type, const sstring& url,
handler_base* handler) {
_map[type][url] = handler;
return *this;
}
/**
* add a rule to be used.
* rules are search only if an exact match was not found.
* rules are search by the order they were added.
* First in higher priority
* @param rule a rule to add
* @param type the operation type
* @return it self
*/
routes& add(match_rule* rule, operation_type type = GET) {
_rules[type].push_back(rule);
return *this;
}
/**
* Add a url match to a handler:
* Example routes.add(GET, url("/api").remainder("path"), handler);
* @param type
* @param url
* @param handler
* @return
*/
routes& add(operation_type type, const url& url, handler_base* handler);
/**
* the main entry point.
* the general handler calls this method with the request
* the method takes the headers from the request and find the
* right handler.
* It then call the handler with the parameters (if they exists) found in the url
* @param path the url path found
* @param req the http request
* @param rep the http reply
*/
future<std::unique_ptr<reply> > handle(const sstring& path, std::unique_ptr<request> req, std::unique_ptr<reply> rep);
/**
* Search and return an exact match
* @param url the request url
* @return the handler if exists or nullptr if it does not
*/
handler_base* get_exact_match(operation_type type, const sstring& url) {
return (_map[type].find(url) == _map[type].end()) ?
nullptr : _map[type][url];
}
private:
/**
* Search and return a handler by the operation type and url
* @param type the http operation type
* @param url the request url
* @param params a parameter object that will be filled during the match
* @return a handler based on the type/url match
*/
handler_base* get_handler(operation_type type, const sstring& url,
parameters& params);
/**
* Normalize the url to remove the last / if exists
* and get the parameter part
* @param url the full url path
* @param param_part will hold the string with the parameters
* @return the url from the request without the last /
*/
sstring normalize_url(const sstring& url);
std::unordered_map<sstring, handler_base*> _map[NUM_OPERATION];
std::vector<match_rule*> _rules[NUM_OPERATION];
};
/**
* A helper function that check if a parameter is found in the params object
* if it does not the function would throw a parameter not found exception
* @param params the parameters object
* @param param the parameter to look for
*/
void verify_param(const httpd::request& req, const sstring& param);
}
#endif /* ROUTES_HH_ */