forked from scylladb/seastar
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The matcher and match rules are used to define and match a url rule. A rule define a list of string and parameters. For example, the rule /api/get/{id}/name Will be mapped by the list of matcher: str_match for /api/get param_match for the {id} and str_match for name Signed-off-by: Amnon Heiman <[email protected]>
- Loading branch information
Showing
3 changed files
with
298 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/* | ||
* 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 | ||
*/ | ||
|
||
#include "matcher.hh" | ||
|
||
#include <iostream> | ||
|
||
namespace httpd { | ||
|
||
using namespace std; | ||
|
||
/** | ||
* Search for the end of the url parameter. | ||
* @param url the url to search | ||
* @param ind the position in the url | ||
* @param entire_path when set to true, take all the reminaing url | ||
* when set to false, search for the next slash | ||
* @return the position in the url of the end of the parameter | ||
*/ | ||
static size_t find_end_param(const sstring& url, size_t ind, bool entire_path) { | ||
size_t pos = (entire_path) ? url.length() : url.find('/', ind + 1); | ||
if (pos == sstring::npos) { | ||
return url.length(); | ||
} | ||
return pos; | ||
} | ||
|
||
size_t param_matcher::match(const sstring& url, size_t ind, parameters& param) { | ||
size_t last = find_end_param(url, ind, _entire_path); | ||
if (last == ind) { | ||
/* | ||
* empty parameter allows only for the case of entire_path | ||
*/ | ||
if (_entire_path) { | ||
param[_name] = ""; | ||
return ind; | ||
} | ||
return sstring::npos; | ||
} | ||
param[_name] = url.substr(ind, last - ind); | ||
return last; | ||
} | ||
|
||
size_t str_matcher::match(const sstring& url, size_t ind, parameters& param) { | ||
if (url.length() >= _len + ind && (url.find(_cmp, ind) == ind) | ||
&& (url.length() == _len + ind || url.at(_len + ind) == '/')) { | ||
return _len + ind; | ||
} | ||
return sstring::npos; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
/* | ||
* 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 MATCHER_HH_ | ||
#define MATCHER_HH_ | ||
|
||
#include "common.hh" | ||
|
||
#include "core/sstring.hh" | ||
|
||
namespace httpd { | ||
|
||
/** | ||
* a base class for the url matching. | ||
* Each implementation check if the given url matches a criteria | ||
*/ | ||
class matcher { | ||
public: | ||
|
||
virtual ~matcher() = default; | ||
|
||
/** | ||
* check if the given url matches the rule | ||
* @param url the url to check | ||
* @param ind the position to start from | ||
* @param fill the parameters hash | ||
* @return the end of of the matched part, or sstring::npos if not matched | ||
*/ | ||
virtual size_t match(const sstring& url, size_t ind, parameters& param) = 0; | ||
}; | ||
|
||
/** | ||
* Check if the url match a parameter and fill the parameters object | ||
* | ||
* Note that a non empty url will always return true with the parameters | ||
* object filled | ||
* | ||
* Assume that the rule is /file/{path}/ and the param_matcher identify | ||
* the /{path} | ||
* | ||
* For all non empty values, match will return true. | ||
* If the entire url is /file/etc/hosts, and the part that is passed to | ||
* param_matcher is /etc/hosts, if entire_path is true, the match will be | ||
* '/etc/hosts' If entire_path is false, the match will be '/etc' | ||
*/ | ||
class param_matcher : public matcher { | ||
public: | ||
/** | ||
* Constructor | ||
* @param name the name of the parameter, will be used as the key | ||
* in the parameters object | ||
* @param entire_path when set to true, the matched parameters will | ||
* include all the remaining url until the end of it. | ||
* when set to false the match will terminate at the next slash | ||
*/ | ||
explicit param_matcher(const sstring& name, bool entire_path = false) | ||
: _name(name), _entire_path(entire_path) { | ||
} | ||
|
||
virtual size_t match(const sstring& url, size_t ind, parameters& param) | ||
override; | ||
private: | ||
sstring _name; | ||
bool _entire_path; | ||
}; | ||
|
||
/** | ||
* Check if the url match a predefine string. | ||
* | ||
* When parsing a match rule such as '/file/{path}' the str_match would parse | ||
* the '/file' part | ||
*/ | ||
class str_matcher : public matcher { | ||
public: | ||
/** | ||
* Constructor | ||
* @param cmp the string to match | ||
*/ | ||
explicit str_matcher(const sstring& cmp) | ||
: _cmp(cmp), _len(cmp.size()) { | ||
} | ||
|
||
virtual size_t match(const sstring& url, size_t ind, parameters& param) | ||
override; | ||
private: | ||
sstring _cmp; | ||
unsigned _len; | ||
}; | ||
|
||
} | ||
|
||
#endif /* MATCHER_HH_ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
/* | ||
* 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 MATCH_RULES_HH_ | ||
#define MATCH_RULES_HH_ | ||
|
||
#include "handlers.hh" | ||
#include "matcher.hh" | ||
#include "common.hh" | ||
|
||
#include "core/sstring.hh" | ||
#include <vector> | ||
|
||
namespace httpd { | ||
|
||
/** | ||
* match_rule check if a url matches criteria, that can contains | ||
* parameters. | ||
* the routes object would call the get method with a url and if | ||
* it matches, the method will return a handler | ||
* during the matching process, the method fill the parameters object. | ||
*/ | ||
class match_rule { | ||
public: | ||
/** | ||
* The destructor deletes matchers. | ||
*/ | ||
~match_rule() { | ||
for (auto m : _match_list) { | ||
delete m; | ||
} | ||
delete _handler; | ||
} | ||
|
||
/** | ||
* Constructor with a handler | ||
* @param handler the handler to return when this match rule is met | ||
*/ | ||
explicit match_rule(handler_base* handler) | ||
: _handler(handler) { | ||
} | ||
|
||
/** | ||
* Check if url match the rule and return a handler if it does | ||
* @param url a url to compare against the rule | ||
* @param params the parameters object, matches parameters will fill | ||
* the object during the matching process | ||
* @return a handler if there is a full match or nullptr if not | ||
*/ | ||
handler_base* get(const sstring& url, parameters& params) { | ||
size_t ind = 0; | ||
for (unsigned int i = 0; i < _match_list.size(); i++) { | ||
ind = _match_list.at(i)->match(url, ind, params); | ||
if (ind == sstring::npos) { | ||
return nullptr; | ||
} | ||
} | ||
return (ind + 1 >= url.length()) ? _handler : nullptr; | ||
} | ||
|
||
/** | ||
* Add a matcher to the rule | ||
* @param match the matcher to add | ||
* @return this | ||
*/ | ||
match_rule& add_matcher(matcher* match) { | ||
_match_list.push_back(match); | ||
return *this; | ||
} | ||
|
||
/** | ||
* Add a static url matcher | ||
* @param str the string to search for | ||
* @return this | ||
*/ | ||
match_rule& add_str(const sstring& str) { | ||
add_matcher(new str_matcher(str)); | ||
return *this; | ||
} | ||
|
||
/** | ||
* add a parameter matcher to the rule | ||
* @param str the parameter name | ||
* @param fullpath when set to true, parameter will included all the | ||
* remaining url until its end | ||
* @return this | ||
*/ | ||
match_rule& add_param(const sstring& str, bool fullpath = false) { | ||
add_matcher(new param_matcher(str, fullpath)); | ||
return *this; | ||
} | ||
|
||
private: | ||
std::vector<matcher*> _match_list; | ||
handler_base* _handler; | ||
}; | ||
|
||
} | ||
|
||
#endif /* MATCH_RULES_HH_ */ |