Skip to content

Commit deecb21

Browse files
authored
Add controller. (#2)
* Add controller. * Update readme.
1 parent 2c02ddb commit deecb21

File tree

10 files changed

+331
-119
lines changed

10 files changed

+331
-119
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
[submodule "3rdparty/drogon"]
22
path = 3rdparty/drogon
33
url = https://github.com/drogonframework/drogon.git
4+
[submodule "3rdparty/magic_enum"]
5+
path = 3rdparty/magic_enum
6+
url = https://github.com/Neargye/magic_enum.git

3rdparty/magic_enum

Submodule magic_enum added at 126539e

CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,13 @@ option(BUILD_EXAMPLES "Build examples" OFF)
1313
option(BUILD_CTL "Build drogon_ctl" OFF)
1414
add_subdirectory(3rdparty/drogon)
1515

16+
add_subdirectory(3rdparty/magic_enum)
17+
1618
set(Boost_USE_STATIC_LIBS ON)
1719
find_package(Boost REQUIRED COMPONENTS program_options)
1820

21+
22+
add_subdirectory(src)
23+
1924
add_executable(simple_inference_server main.cpp)
20-
target_link_libraries(simple_inference_server drogon Boost::program_options)
25+
target_link_libraries(simple_inference_server Boost::program_options libsimple_inference_server)

main.cpp

Lines changed: 6 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -4,118 +4,11 @@
44
#include <spdlog/spdlog.h>
55
#include <fstream>
66

7+
#include "src/Controller.h"
78

8-
using namespace drogon;
9-
10-
11-
struct GlobalConfig
12-
{
13-
std::filesystem::path invokePath;
14-
std::filesystem::path indexPath;
15-
} globalConfig;
16-
17-
bool invokeProcessing( const std::filesystem::path& input, const std::filesystem::path& output )
18-
{
19-
auto exitCode = system( fmt::format( "{} {} {}", globalConfig.invokePath.string(), input.string(), output.string() ).c_str() );
20-
return exitCode == 0;
21-
}
229

23-
std::string getInputFileName( const std::string& taskId )
24-
{
25-
return taskId + ".input.zip";
26-
}
27-
std::filesystem::path getInputPath( const std::string& taskId )
28-
{
29-
return std::filesystem::path{ app().getUploadPath() } / getInputFileName( taskId );
30-
}
31-
std::filesystem::path getOutputPath( const std::string& taskId )
32-
{
33-
return std::filesystem::path{ app().getUploadPath() } / ( taskId + ".zip" );
34-
}
35-
36-
37-
Task<HttpResponsePtr> trackResultHandler( HttpRequestPtr req )
38-
{
39-
const auto maybeTask = req->getOptionalParameter<std::string>( "task" );
40-
const auto maybeOutput = maybeTask.transform( getOutputPath );
41-
42-
if ( !maybeOutput || !std::filesystem::exists( *maybeOutput ) )
43-
{
44-
auto resp = HttpResponse::newHttpResponse();
45-
resp->setBody( "The task is not available (yet)" );
46-
resp->setStatusCode( HttpStatusCode::k200OK );
47-
resp->addHeader( "Refresh", "10" );
48-
co_return resp;
49-
}
50-
51-
auto resp = HttpResponse::newHttpResponse();
52-
resp->setBody( fmt::format( "Result can be downloaded <a href=\"./get_result?task={}\">here</a>", *maybeTask ) );
53-
resp->setStatusCode( HttpStatusCode::k200OK );
54-
co_return resp;
55-
}
56-
57-
Task<HttpResponsePtr> getResultHandler( HttpRequestPtr req )
58-
{
59-
const auto maybeTask = req->getOptionalParameter<std::string>( "task" );
60-
const auto maybeOutput = maybeTask.transform( getOutputPath );
61-
if ( !maybeOutput || !std::filesystem::exists( *maybeOutput ) )
62-
{
63-
co_return HttpResponse::newNotFoundResponse();
64-
}
65-
66-
auto resp = HttpResponse::newFileResponse( *maybeOutput, maybeOutput->filename() );
67-
co_return resp;
68-
}
69-
70-
Task<HttpResponsePtr> submitTaskHandler( HttpRequestPtr req )
71-
{
72-
MultiPartParser filesUpload;
73-
if ( filesUpload.parse(req) != 0 || filesUpload.getFiles().size() != 1 )
74-
{
75-
auto resp = HttpResponse::newHttpResponse();
76-
resp->setBody( "Must only be one file" );
77-
resp->setStatusCode( k403Forbidden );
78-
co_return resp;
79-
}
80-
81-
auto file = filesUpload.getFiles()[0];
82-
if ( !file.getFileName().ends_with( ".zip" ) )
83-
{
84-
auto resp = HttpResponse::newHttpResponse();
85-
resp->setBody( "Must be zip file" );
86-
resp->setStatusCode( k403Forbidden );
87-
co_return resp;
88-
}
89-
90-
const auto taskId = drogon::utils::getUuid();
91-
file.saveAs( getInputFileName( taskId ) );
92-
93-
app().getLoop()->queueInLoop( [taskId]
94-
{
95-
const auto inputPath = getInputPath( taskId );
96-
const auto outputPath = getOutputPath( taskId );
97-
invokeProcessing( inputPath, outputPath );
98-
} );
10+
using namespace drogon;
9911

100-
auto resp = HttpResponse::newHttpResponse();
101-
resp->setStatusCode( HttpStatusCode::k202Accepted );
102-
resp->setBody( fmt::format( "Your requested has been accepted. You can track it <a href=\"./track_result?task={}\">here</a>",
103-
taskId ) );
104-
co_return resp;
105-
}
106-
107-
Task<HttpResponsePtr> rootHandler( HttpRequestPtr req )
108-
{
109-
auto resp = HttpResponse::newHttpResponse( HttpStatusCode::k200OK, CT_TEXT_HTML );
110-
if ( exists( globalConfig.indexPath ) )
111-
{
112-
std::ifstream fin( globalConfig.indexPath );
113-
std::stringstream buffer;
114-
buffer << fin.rdbuf();
115-
resp->setBody( buffer.str() );
116-
}
117-
co_return resp;
118-
}
11912

12013
// Fix parsing std::filesystem::path with spaces (see https://github.com/boostorg/program_options/issues/69)
12114
namespace boost
@@ -133,12 +26,13 @@ int main( int argc, char** argv )
13326
std::string host;
13427
std::filesystem::path certPath, keyPath;
13528
int port;
29+
Controller::Config config;
13630

13731
po::options_description desc( "Simple Inference Server" );
13832
desc.add_options()
13933
( "help,h", "Display help message" )
140-
( "invokePath", po::value( &globalConfig.invokePath )->required(), "Path to the script that will be invoked" )
141-
( "indexPath", po::value( &globalConfig.indexPath )->default_value( {} ), "Path to the index.html" )
34+
( "invokePath", po::value( &config.invokePath )->required(), "Path to the script that will be invoked" )
35+
( "indexPath", po::value( &config.indexPath )->default_value( {} ), "Path to the index.html" )
14236
( "host", po::value( &host )->default_value( "127.0.0.1" ), "Host to bind to" )
14337
( "port", po::value( &port )->default_value( 7654 ), "Port to bind to" )
14438
( "cert", po::value( &certPath )->default_value( {} ), "Path to SSL certificate" )
@@ -163,11 +57,6 @@ int main( int argc, char** argv )
16357
return -1;
16458
}
16559

166-
app().registerHandler( "/track_result", std::function{ trackResultHandler } );
167-
app().registerHandler( "/get_result", std::function{ getResultHandler } );
168-
app().registerHandler( "/submit", std::function{ submitTaskHandler }, {Post } );
169-
app().registerHandler( "/", std::function{ rootHandler } );
170-
17160
const bool useSSL = exists( certPath ) && exists( keyPath );
17261
if ( useSSL && !app().supportSSL() )
17362
{
@@ -185,6 +74,7 @@ int main( int argc, char** argv )
18574
app()
18675
.setClientMaxBodySize( 1024*1024*1024 ) // 1gb
18776
.addListener( host, port, useSSL, certPath, keyPath )
77+
.registerController( std::make_shared<Controller>( config ) )
18878
.run();
18979

19080
return 0;

readme.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ It is useful when you have an early-stage prototype, and you want to share it wi
88
## Workflow
99

1010
- Accepts `POST` request with a single `.zip` file to the endpoint `/submit`
11-
- Displays the URL to track the task if it was accepted (`/track_result?task=...`)
12-
- When processing is finished, the track page displays the URL to download result (`get_result?task=...`)
11+
- Displays the URL to track the job if it was accepted (`/get_job_info?job_id=...`)
12+
- When processing is finished, the track page displays the URL to download result (`/get_result?job_id=...`)
1313

1414
## Usage
1515

src/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
project(libsimple_inference_server)
2+
3+
4+
file(GLOB source *.cpp)
5+
add_library(libsimple_inference_server STATIC ${source})
6+
target_link_libraries(libsimple_inference_server drogon magic_enum::magic_enum)

0 commit comments

Comments
 (0)