1 module app; 2 3 // cannot use vibe.d due symbol clash for logging 4 import vibe.core.core; 5 import vibe.core.log; 6 import vibe.http.server; 7 import vibe.http.router; 8 9 import jsonizer; 10 import std.json; 11 import std.file; 12 import std.path; 13 import std.getopt; 14 15 import fileCache; 16 17 immutable string settingsFileName = "web.json"; 18 19 void loadRouteSpecs(RouteSettings[] routes, string basePath, URLRouter router) 20 { 21 auto settings = new HTTPFileServerSettings; 22 settings.cache = new FileServerCache; 23 foreach(route; routes) 24 { 25 auto targetPath = route.arg.absolutePath(basePath); 26 if(route.type == "path") 27 { 28 router.get(route.path, serveStaticFiles(targetPath, settings)); 29 } 30 else if(route.type == "file") 31 { 32 router.get(route.path, serveStaticFile(targetPath, settings)); 33 } 34 else throw new Error("Invalid type: " ~ route.type); 35 logInfo("Mapping path: " ~ route.path ~ " with " ~ targetPath); 36 } 37 } 38 39 int runServer(string settingsFileName) 40 { 41 settingsFileName = settingsFileName.absolutePath(thisExePath.dirName); 42 auto basePath = settingsFileName.dirName; 43 44 // Load settings from file 45 auto settingsFileContents = readText(settingsFileName); 46 auto json = parseJSON(settingsFileContents); 47 auto settings = json.fromJSON!Settings; 48 49 settings.logFileName = settings.logFileName.absolutePath(basePath); 50 51 // Setup loggers 52 setLogFile(settings.logFileName, settings.logLevel); 53 54 // Default vibe initialization 55 auto svrSettings = new HTTPServerSettings; 56 svrSettings.port = cast(ushort)settings.port; 57 svrSettings.useCompressionIfPossible = settings.useCompressionIfPossible; 58 svrSettings.bindAddresses = settings.bindAddresses; 59 //svrSettings.options |= HTTPServerOption.distribute; 60 61 auto router = new URLRouter; 62 logInfo("Loading routes from settings"); 63 loadRouteSpecs(settings.routes, basePath, router); 64 65 listenHTTP(svrSettings, router); 66 67 return runEventLoop(); 68 } 69 70 struct RouteSettings 71 { 72 mixin JsonizeMe; 73 74 @jsonize string type; 75 @jsonize string path; 76 @jsonize string arg; 77 } 78 79 struct Settings 80 { 81 mixin JsonizeMe; 82 83 @jsonize(JsonizeOptional.yes) int port = 3000; 84 @jsonize(JsonizeOptional.yes) string[] bindAddresses = ["::", "0.0.0.0"]; 85 @jsonize(JsonizeOptional.yes) bool useCompressionIfPossible = true; 86 @jsonize(JsonizeOptional.yes) string logFileName = "vibe.log"; 87 @jsonize(JsonizeOptional.yes) LogLevel logLevel = LogLevel.none; 88 @jsonize RouteSettings[] routes; 89 } 90 91 int main(string[] args) 92 { 93 string settingsFileNameOpt = settingsFileName; 94 auto helpInformation = getopt(args, 95 "settings", "JSON settings file name.", &settingsFileNameOpt); 96 97 if (helpInformation.helpWanted) 98 { 99 defaultGetoptPrinter( 100 "Help about this program. " 101 "Settings file path is relative to this executable", 102 helpInformation.options); 103 return 0; 104 } 105 106 logInfo("Loading info from " ~ settingsFileNameOpt); 107 108 return runServer(settingsFileNameOpt); 109 }