Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions onnxruntime/hosting/environment.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ namespace hosting {
class HostingEnvironment {
public:
HostingEnvironment();
HostingEnvironment(const HostingEnvironment&) = delete;

const onnxruntime::logging::Logger& GetLogger();
std::shared_ptr<onnxruntime::InferenceSession> GetSession() const;
Expand Down
40 changes: 19 additions & 21 deletions onnxruntime/hosting/http/http_server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,14 @@
#include <functional>
#include <iostream>
#include <memory>
#include <string>
#include <thread>
#include <vector>
#include <boost/asio.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/beast/http.hpp>

#include "context.h"
#include "session.h"
#include "listener.h"
#include "routes.h"
#include "util.h"

#include "http_server.h"

Expand All @@ -29,42 +25,44 @@ namespace hosting {
using handler_fn = std::function<void(std::string, std::string, std::string, HttpContext&)>;

App::App() {
Comment thread
tmccrmck marked this conversation as resolved.
// TODO: defaults should come from central place
address_ = boost::asio::ip::make_address_v4("0.0.0.0");
port_ = 8080;
threads_ = std::thread::hardware_concurrency();
http_details.address = boost::asio::ip::make_address_v4("0.0.0.0");
http_details.port = 8001;
http_details.threads = std::thread::hardware_concurrency();
}

App& App::Bind(net::ip::address address, unsigned short port) {
address_ = std::move(address);
port_ = port;
http_details.address = std::move(address);
http_details.port = port;
return *this;
}

App& App::NumThreads(int threads) {
threads_ = threads;
http_details.threads = threads;
Comment thread
tmccrmck marked this conversation as resolved.
return *this;
}

App& App::Post(const std::string& route, const handler_fn& fn) {
routes->RegisterController(http::verb::post, route, fn);
App& App::RegisterStartup(const start_fn& on_start) {
on_start_ = on_start;
return *this;
}

App& App::RegisterPost(const std::string& route, const handler_fn& fn) {
routes_->RegisterController(http::verb::post, route, fn);
return *this;
}

App& App::Run() {
net::io_context ioc{threads_};
net::io_context ioc{http_details.threads};
// Create and launch a listening port
std::make_shared<Listener>(routes, ioc, tcp::endpoint{address_, port_})->Run();
std::make_shared<Listener>(routes_, ioc, tcp::endpoint{http_details.address, http_details.port})->Run();

// TODO: use logger
std::cout << "Listening at: \n"
<< std::endl;
std::cout << "\thttp://" << address_ << ":" << port_ << std::endl;
// Run user on start function
on_start_(http_details);

// Run the I/O service on the requested number of threads
std::vector<std::thread> v;
v.reserve(threads_ - 1);
for (auto i = threads_ - 1; i > 0; --i) {
v.reserve(http_details.threads - 1);
for (auto i = http_details.threads - 1; i > 0; --i) {
v.emplace_back(
[&ioc] {
ioc.run();
Expand Down
18 changes: 12 additions & 6 deletions onnxruntime/hosting/http/http_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ namespace http = beast::http; // from <boost/beast/http.hpp>
namespace net = boost::asio; // from <boost/asio.hpp>
using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>

using handler_fn = std::function<void(std::string, std::string, std::string, HttpContext&)>;
struct Details {
net::ip::address address;
unsigned short port;
int threads;
};

using start_fn = std::function<void(Details&)>;

// Accepts incoming connections and launches the sessions
// Each method returns the app itself so methods can be chained
Expand All @@ -34,14 +40,14 @@ class App {

App& Bind(net::ip::address address, unsigned short port);
App& NumThreads(int threads);
App& Post(const std::string& route, const handler_fn& fn);
App& RegisterStartup(const start_fn& fn);
App& RegisterPost(const std::string& route, const handler_fn& fn);
App& Run();

private:
const std::shared_ptr<Routes> routes = std::make_shared<Routes>();
net::ip::address address_;
unsigned short port_;
int threads_;
const std::shared_ptr<Routes> routes_ = std::make_shared<Routes>();
start_fn on_start_ = {};
Details http_details{};
};
} // namespace hosting
} // namespace onnxruntime
Expand Down
2 changes: 1 addition & 1 deletion onnxruntime/hosting/http/listener.cc
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#include "session.h"
#include "listener.h"
#include "session.h"
#include "util.h"

namespace onnxruntime {
Expand Down
1 change: 1 addition & 0 deletions onnxruntime/hosting/http/listener.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <memory>

#include <boost/asio/ip/tcp.hpp>

#include "routes.h"
#include "util.h"

Expand Down
31 changes: 9 additions & 22 deletions onnxruntime/hosting/http/predict_request_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,25 @@
namespace onnxruntime {
namespace hosting {

namespace beast = boost::beast;
namespace http = beast::http;

void BadRequest(HttpContext& context, const std::string& error_message) {
auto json_error = R"({"error_code": 400, "error_message": )" + error_message + " }";

http::response<http::string_body> res{http::status::bad_request, context.request.version()};
res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
res.set(http::field::content_type, "application/json");
res.keep_alive(context.request.keep_alive());
res.body() = std::string(json_error);
res.prepare_payload();
context.response = res;
context.response.result(400);
context.response.body() = std::string(json_error);
}

// TODO: decide whether this should be a class
void Predict(const std::string& name,
const std::string& version,
const std::string& action,
HttpContext& context,
HostingEnvironment& env) {
std::shared_ptr<HostingEnvironment> env) {
PredictRequest predictRequest{};
auto logger = env.GetLogger();
auto logger = env->GetLogger();

LOGS(logger, VERBOSE) << "Name: " << name
<< "Version: " << version
<< "Action: " << action;
LOGS(logger, VERBOSE) << "Name: " << name;
LOGS(logger, VERBOSE) << "Version: " << version;
LOGS(logger, VERBOSE) << "Action: " << action;

auto body = context.request.body();
auto status = GetRequestFromJson(body, predictRequest);
Expand All @@ -43,13 +35,8 @@ void Predict(const std::string& name,
return BadRequest(context, status.error_message());
}

http::response<http::string_body> res{std::piecewise_construct,
std::make_tuple(body),
std::make_tuple(http::status::ok, context.request.version())};
res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
res.set(http::field::content_type, "application/json");
res.keep_alive(context.request.keep_alive());
context.response = res;
context.response.result(200);
context.response.body() = body;
};

} // namespace hosting
Expand Down
2 changes: 1 addition & 1 deletion onnxruntime/hosting/http/predict_request_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ void Predict(const std::string& name,
const std::string& version,
const std::string& action,
HttpContext& context,
HostingEnvironment& env);
std::shared_ptr<HostingEnvironment> env);

} // namespace hosting
} // namespace onnxruntime
2 changes: 0 additions & 2 deletions onnxruntime/hosting/http/routes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ http::status Routes::ParseUrl(http::verb method,
}

if (func_table.empty()) {
std::cout << "Unsupported method: [" << method << "]" << std::endl;
Comment thread
tmccrmck marked this conversation as resolved.
return http::status::method_not_allowed;
}

Expand All @@ -62,7 +61,6 @@ http::status Routes::ParseUrl(http::verb method,
}

if (!found_match) {
std::cerr << "Path not found: [" << url << "]" << std::endl;
Comment thread
tmccrmck marked this conversation as resolved.
return http::status::not_found;
}

Expand Down
1 change: 1 addition & 0 deletions onnxruntime/hosting/http/routes.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class Routes {
private:
std::vector<std::pair<std::string, handler_fn>> post_fn_table;
std::vector<std::pair<std::string, handler_fn>> get_fn_table;
// TODO: server error callback
};

} //namespace hosting
Expand Down
25 changes: 10 additions & 15 deletions onnxruntime/hosting/http/session.cc
Original file line number Diff line number Diff line change
Expand Up @@ -87,35 +87,30 @@ void HttpSession::Send(Msg&& msg) {

http::async_write(self_->socket_, *ptr,
net::bind_executor(strand_,
[self_, close = ptr->need_eof()](beast::error_code ec, std::size_t bytes) {
[ self_, close = ptr->need_eof() ](beast::error_code ec, std::size_t bytes) {
self_->OnWrite(ec, bytes, close);
}));
}

template <typename Body, typename Allocator>
void HttpSession::HandleRequest(boost::beast::http::request<Body, boost::beast::http::basic_fields<Allocator> >&& req) {
void HttpSession::HandleRequest(http::request<Body, http::basic_fields<Allocator> >&& req) {
HttpContext context{};
context.request = req;
context.request = std::move(req);

std::string path = req.target().to_string();
std::string model_name;
std::string model_version;
std::string action;
// TODO: set request id
std::string path = context.request.target().to_string();
std::string model_name, model_version, action;
Comment thread
tmccrmck marked this conversation as resolved.
handler_fn func;
http::status status = routes_->ParseUrl(req.method(), path, model_name, model_version, action, func);
http::status status = routes_->ParseUrl(context.request.method(), path, model_name, model_version, action, func);

if (http::status::ok == status && func != nullptr) {
func(model_name, model_version, action, context);
} else {
http::response<http::string_body> res{status, req.version()};
res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
res.set(http::field::content_type, "text/plain");
res.keep_alive(req.keep_alive());
res.body() = std::string("Something failed\n");
res.prepare_payload();
context.response = res;
context.response.result(status);
}

context.response.keep_alive(context.request.keep_alive());
context.response.prepare_payload();
return Send(std::move(context.response));
}

Expand Down
23 changes: 14 additions & 9 deletions onnxruntime/hosting/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,27 @@ int main(int argc, char* argv[]) {
exit(EXIT_FAILURE);
}

hosting::HostingEnvironment env;
auto logger = env.GetLogger();

// TODO: below code snippet just trying to show case how to use the "env". Move later.
auto env = std::make_shared<hosting::HostingEnvironment>();
auto logger = env->GetLogger();
LOGS(logger, VERBOSE) << "Logging manager initialized.";
LOGS(logger, VERBOSE) << "Model path: " << config.model_path;
auto status = env.GetSession()->Load(config.model_path);
auto status = env->GetSession()->Load(config.model_path);
LOGS(logger, VERBOSE) << "Load Model Status: " << status.Code() << " ---- Error: [" << status.ErrorMessage() << "]";

auto const boost_address = boost::asio::ip::make_address(config.address);

hosting::App app{};
app.Post(R"(/v1/models/([^/:]+)(?:/versions/(\d+))?:(classify|regress|predict))",
[&env](const std::string& name, const std::string& version, const std::string& action, hosting::HttpContext& context) {
hosting::Predict(name, version, action, context, env);
});

app.RegisterStartup(
[&env](const auto& details) {
auto logger = env->GetLogger();
LOGS(logger, VERBOSE) << "Listening at: " << "http://" << details.address << ":" << details.port;
});

app.RegisterPost(R"(/v1/models/([^/:]+)(?:/versions/(\d+))?:(classify|regress|predict))",
[env](const auto& name, const auto& version, const auto& action, auto& context) {
hosting::Predict(name, version, action, context, env);
});

app.Bind(boost_address, config.http_port)
.NumThreads(config.num_http_threads)
Expand Down