Seastar
High performance C++ framework for concurrent servers
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
api_docs.hh
1/*
2 * This file is open source software, licensed to you under the terms
3 * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
4 * distributed with this work for additional information regarding copyright
5 * ownership. You may not use this file except in compliance with the License.
6 *
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing,
12 * software distributed under the License is distributed on an
13 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 * KIND, either express or implied. See the License for the
15 * specific language governing permissions and limitations
16 * under the License.
17 */
18/*
19 * Copyright 2015 Cloudius Systems
20 */
21
22#pragma once
23#include <seastar/json/json_elements.hh>
24#include <seastar/json/formatter.hh>
25#include <seastar/http/routes.hh>
26#include <seastar/http/transformers.hh>
27#include <string>
28#include <seastar/util/noncopyable_function.hh>
29
30namespace seastar {
31
32namespace httpd {
33
34struct api_doc : public json::json_base {
37
38 void register_params() {
39 add(&path, "path");
40 add(&description, "description");
41
42 }
43 api_doc() {
44 register_params();
45 }
46 api_doc(const api_doc & e)
48 {
49 register_params();
50 path = e.path;
51 description = e.description;
52 }
53 template<class T>
54 api_doc& operator=(const T& e) {
55 path = e.path;
56 description = e.description;
57 return *this;
58 }
59 api_doc& operator=(const api_doc& e) {
60 path = e.path;
61 description = e.description;
62 return *this;
63 }
64};
65
66struct api_docs : public json::json_base {
70
71 void register_params() {
72 add(&apiVersion, "apiVersion");
73 add(&swaggerVersion, "swaggerVersion");
74 add(&apis, "apis");
75
76 }
77 api_docs() {
78 apiVersion = "0.0.1";
79 swaggerVersion = "1.2";
80 register_params();
81 }
82 api_docs(const api_docs & e)
83 : apiVersion{e.apiVersion}
84 , swaggerVersion{e.swaggerVersion}
85 , apis{e.apis}
86 {
87 register_params();
88 }
89 template<class T>
90 api_docs& operator=(const T& e) {
91 apis = e.apis;
92 return *this;
93 }
94 api_docs& operator=(const api_docs& e) {
95 apis = e.apis;
96 return *this;
97 }
98};
99
101protected:
102 sstring _base_path;
103 sstring _file_directory;
104 routes& _routes;
105
106public:
107 api_registry_base(routes& routes, const sstring& file_directory,
108 const sstring& base_path)
109 : _base_path(base_path), _file_directory(file_directory), _routes(
110 routes) {
111 }
112
113 void set_route(handler_base* h) {
114 _routes.put(GET, _base_path, h);
115 }
116 virtual ~api_registry_base() = default;
117};
118
120 api_docs _docs;
121public:
122 api_registry(routes& routes, const sstring& file_directory,
123 const sstring& base_path)
124 : api_registry_base(routes, file_directory, base_path) {
125 set_route(this);
126 }
127
129 std::unique_ptr<http::request> req, std::unique_ptr<http::reply> rep) override {
130 rep->_content = json::formatter::to_json(_docs);
131 rep->done("json");
132 return make_ready_future<std::unique_ptr<http::reply>>(std::move(rep));
133 }
134
135 void reg(const sstring& api, const sstring& description,
136 const sstring& alternative_path = "") {
137 api_doc doc;
138 doc.description = description;
139 doc.path = "/" + api;
140 _docs.apis.push(doc);
141 sstring path =
142 (alternative_path == "") ?
143 _file_directory + api + ".json" : alternative_path;
144 file_handler* index = new file_handler(path,
145 new content_replace("json"));
146 _routes.put(GET, _base_path + "/" + api, index);
147 }
148};
149
151protected:
152 sstring _file_directory;
153 sstring _base_path;
154 static const sstring DEFAULT_DIR;
155 static const sstring DEFAULT_PATH;
156public:
157 api_registry_builder_base(const sstring& file_directory = DEFAULT_DIR,
158 const sstring& base_path = DEFAULT_PATH)
159 : _file_directory(file_directory), _base_path(base_path) {
160 }
161};
162
164public:
165 api_registry_builder(const sstring& file_directory = DEFAULT_DIR,
166 const sstring& base_path = DEFAULT_PATH)
167 : api_registry_builder_base(file_directory, base_path) {
168 }
169
170 void set_api_doc(routes& r) {
171 new api_registry(r, _file_directory, _base_path);
172 }
173
174 void register_function(routes& r, const sstring& api,
175 const sstring& description, const sstring& alternative_path = "") {
176 auto h = r.get_exact_match(GET, _base_path);
177 if (h) {
178 // if a handler is found, it was added there by the api_registry_builder
179 // with the set_api_doc method, so we know it's the type
180 static_cast<api_registry*>(h)->reg(api, description, alternative_path);
181 };
182 }
183};
184
186
191doc_entry get_file_reader(sstring file_name);
192
236 std::vector<doc_entry> _apis;
237 content_replace _transform;
238 std::vector<doc_entry> _definitions;
239
240public:
241 future<> write(output_stream<char>&&, std::unique_ptr<http::request> req);
242
243 void add_api(doc_entry&& f) {
244 _apis.emplace_back(std::move(f));
245 }
246
247 void add_definition(doc_entry&& f) {
248 _definitions.emplace_back(std::move(f));
249 }
250};
251
253 api_docs_20 _docs;
254public:
255 api_registry_20(routes& routes, const sstring& file_directory,
256 const sstring& base_path)
257 : api_registry_base(routes, file_directory, base_path) {
258 set_route(this);
259 }
260
262 std::unique_ptr<http::request> req, std::unique_ptr<http::reply> rep) override {
263 rep->write_body("json", [this, req = std::move(req)] (output_stream<char>&& os) mutable {
264 return _docs.write(std::move(os), std::move(req));
265 });
266 return make_ready_future<std::unique_ptr<http::reply>>(std::move(rep));
267 }
268
269 virtual void reg(doc_entry&& f) {
270 _docs.add_api(std::move(f));
271 }
272
273 virtual void add_definition(doc_entry&& f) {
274 _docs.add_definition(std::move(f));
275 }
276};
277
279 api_registry_20* get_register_base(routes& r) {
280 auto h = r.get_exact_match(GET, _base_path);
281 if (h) {
282 // if a handler is found, it was added there by the api_registry_builder
283 // with the set_api_doc method, so we know it's the type
284 return static_cast<api_registry_20*>(h);
285 }
286 return nullptr;
287 }
288
289public:
290 api_registry_builder20(const sstring& file_directory = DEFAULT_DIR,
291 const sstring& base_path = DEFAULT_PATH)
292 : api_registry_builder_base(file_directory, base_path) {
293 }
294
295 void set_api_doc(routes& r) {
296 new api_registry_20(r, _file_directory, _base_path);
297 }
298
305 auto h = get_register_base(r);
306 if (h) {
307 h->reg(std::move(f));
308 }
309 }
313 void register_api_file(routes& r, const sstring& api) {
314 register_function(r, get_file_reader(_file_directory + "/" + api + ".json"));
315 }
316
317
322 auto h = get_register_base(r);
323 if (h) {
324 h->add_definition(std::move(f));
325 }
326
327 }
328
332 void add_definitions_file(routes& r, const sstring& file) {
333 add_definition(r, get_file_reader(_file_directory + file + ".def.json" ));
334 }
335
336};
337
338}
339
340}
Definition: file.hh:177
A representation of a possibly not-yet-computed value.
Definition: future.hh:1240
An api doc that support swagger version 2.0.
Definition: api_docs.hh:235
Definition: api_docs.hh:252
future< std::unique_ptr< http::reply > > handle(const sstring &path, std::unique_ptr< http::request > req, std::unique_ptr< http::reply > rep) override
Definition: api_docs.hh:261
Definition: api_docs.hh:100
Definition: api_docs.hh:278
void add_definitions_file(routes &r, const sstring &file)
Definition: api_docs.hh:332
void register_api_file(routes &r, const sstring &api)
register an API
Definition: api_docs.hh:313
void register_function(routes &r, doc_entry &&f)
register a doc_entry This doc_entry can be used to either take the definition from a file or generate...
Definition: api_docs.hh:304
void add_definition(routes &r, doc_entry &&f)
Definition: api_docs.hh:321
Definition: api_docs.hh:163
Definition: api_docs.hh:119
future< std::unique_ptr< http::reply > > handle(const sstring &path, std::unique_ptr< http::request > req, std::unique_ptr< http::reply > rep) override
Definition: api_docs.hh:128
Definition: transformers.hh:44
Definition: file_handler.hh:150
Definition: handlers.hh:42
Definition: routes.hh:81
handler_base * get_exact_match(operation_type type, const sstring &url) const
Definition: routes.hh:161
routes & put(operation_type type, const sstring &url, handler_base *handler)
Definition: json_elements.hh:160
Seastar API namespace.
Definition: abort_on_ebadf.hh:26
Definition: noncopyable_function.hh:37
Definition: api_docs.hh:34
Definition: api_docs.hh:66
Definition: json_elements.hh:228
virtual void add(json_base_element *element, std::string name, bool mandatory=false)