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.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
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
19 * Copyright 2015 Cloudius Systems
22 #include <seastar/http/httpd.hh>
23 #include <seastar/http/handlers.hh>
24 #include <seastar/http/function_handlers.hh>
25 #include <seastar/http/file_handler.hh>
26 #include <seastar/core/seastar.hh>
27 #include <seastar/core/reactor.hh>
28 #include "demo.json.hh"
29 #include <seastar/http/api_docs.hh>
30 #include <seastar/core/thread.hh>
31 #include <seastar/core/prometheus.hh>
32 #include <seastar/core/print.hh>
33 #include <seastar/net/inet_address.hh>
34 #include "../lib/stop_signal.hh"
36 namespace bpo
= boost::program_options
;
38 using namespace seastar
;
39 using namespace httpd
;
41 class handl
: public httpd::handler_base
{
43 virtual future
<std::unique_ptr
<http::reply
> > handle(const sstring
& path
,
44 std::unique_ptr
<http::request
> req
, std::unique_ptr
<http::reply
> rep
) {
45 rep
->_content
= "hello";
47 return make_ready_future
<std::unique_ptr
<http::reply
>>(std::move(rep
));
51 void set_routes(routes
& r
) {
52 function_handler
* h1
= new function_handler([](const_req req
) {
55 function_handler
* h2
= new function_handler([](std::unique_ptr
<http::request
> req
) {
56 return make_ready_future
<json::json_return_type
>("json-future");
58 r
.add(operation_type::GET
, url("/"), h1
);
59 r
.add(operation_type::GET
, url("/jf"), h2
);
60 r
.add(operation_type::GET
, url("/file").remainder("path"),
61 new directory_handler("/"));
62 demo_json::hello_world
.set(r
, [] (const_req req
) {
63 demo_json::my_object obj
;
64 obj
.var1
= req
.param
.at("var1");
65 obj
.var2
= req
.param
.at("var2");
66 demo_json::ns_hello_world::query_enum v
= demo_json::ns_hello_world::str2query_enum(req
.query_parameters
.at("query_enum"));
67 // This demonstrate enum conversion
73 int main(int ac
, char** av
) {
74 httpd::http_server_control prometheus_server
;
75 prometheus::config pctx
;
78 app
.add_options()("port", bpo::value
<uint16_t>()->default_value(10000), "HTTP Server port");
79 app
.add_options()("prometheus_port", bpo::value
<uint16_t>()->default_value(9180), "Prometheus port. Set to zero in order to disable.");
80 app
.add_options()("prometheus_address", bpo::value
<sstring
>()->default_value("0.0.0.0"), "Prometheus address");
81 app
.add_options()("prometheus_prefix", bpo::value
<sstring
>()->default_value("seastar_httpd"), "Prometheus metrics prefix");
83 return app
.run_deprecated(ac
, av
, [&] {
84 return seastar::async([&] {
85 seastar_apps_lib::stop_signal stop_signal
;
86 auto&& config
= app
.configuration();
87 httpd::http_server_control prometheus_server
;
89 uint16_t pport
= config
["prometheus_port"].as
<uint16_t>();
91 prometheus::config pctx
;
92 net::inet_address
prom_addr(config
["prometheus_address"].as
<sstring
>());
94 pctx
.metric_help
= "seastar::httpd server statistics";
95 pctx
.prefix
= config
["prometheus_prefix"].as
<sstring
>();
97 std::cout
<< "starting prometheus API server" << std::endl
;
98 prometheus_server
.start("prometheus").get();
100 prometheus::start(prometheus_server
, pctx
).get();
102 prometheus_server
.listen(socket_address
{prom_addr
, pport
}).handle_exception([prom_addr
, pport
] (auto ep
) {
103 std::cerr
<< seastar::format("Could not start Prometheus API server on {}:{}: {}\n", prom_addr
, pport
, ep
);
104 return make_exception_future
<>(ep
);
108 uint16_t port
= config
["port"].as
<uint16_t>();
109 auto server
= new http_server_control();
110 auto rb
= make_shared
<api_registry_builder
>("apps/httpd/");
111 server
->start().get();
112 server
->set_routes(set_routes
).get();
113 server
->set_routes([rb
](routes
& r
){rb
->set_api_doc(r
);}).get();
114 server
->set_routes([rb
](routes
& r
) {rb
->register_function(r
, "demo", "hello world application");}).get();
115 server
->listen(port
).get();
117 std::cout
<< "Seastar HTTP server listening on port " << port
<< " ...\n";
118 engine().at_exit([&prometheus_server
, server
, pport
] {
119 return [pport
, &prometheus_server
] {
121 std::cout
<< "Stoppping Prometheus server" << std::endl
;
122 return prometheus_server
.stop();
124 return make_ready_future
<>();
125 }().finally([server
] {
126 std::cout
<< "Stoppping HTTP server" << std::endl
;
127 return server
->stop();
131 stop_signal
.wait().get();