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)
12114namespace 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 ;
0 commit comments