1 module hunt.framework.provider.HttpServiceProvider; 2 3 import hunt.framework.controller.Controller; 4 import hunt.framework.config.ApplicationConfig; 5 import hunt.framework.config.ConfigManager; 6 import hunt.framework.http.HttpErrorResponseHandler; 7 import hunt.framework.Init; 8 import hunt.framework.provider.ServiceProvider; 9 import hunt.framework.routing; 10 11 import hunt.http.routing.RoutingContext; 12 import hunt.http.routing.RouterManager; 13 import hunt.http.server.HttpServer; 14 import hunt.http.server.HttpServerOptions; 15 import hunt.http.server.WebSocketHandler; 16 import hunt.http.WebSocketPolicy; 17 import hunt.http.WebSocketCommon; 18 19 import hunt.logging.ConsoleLogger; 20 21 import poodinis; 22 23 import std.array; 24 import std.exception; 25 import std.conv; 26 import std.container.array; 27 import std.file; 28 import std.path; 29 import std.socket; 30 import std.stdio; 31 import std.string; 32 import std.uni; 33 34 /** 35 * 36 */ 37 class HttpServiceProvider : ServiceProvider { 38 39 override void register() { 40 container.register!(HttpServer)(&buildServer).singleInstance(); 41 } 42 43 private HttpServer buildServer() { 44 DefaultErrorResponseHandler.Default = new HttpErrorResponseHandler(); 45 ConfigManager manager = container.resolve!ConfigManager; 46 ApplicationConfig appConfig = container.resolve!ApplicationConfig(); 47 // SimpleWebSocketHandler webSocketHandler = new SimpleWebSocketHandler(); 48 // webSocketHandler.setWebSocketPolicy(_webSocketPolicy); 49 50 //if(conf.webSocketFactory) 51 // _wfactory = conf.webSocketFactory; 52 53 // Building http server 54 // HttpServerOptions options = new HttpServerOptions(); 55 HttpServer.Builder hsb = HttpServer.builder() 56 .setListener(appConfig.http.port, appConfig.http.address) 57 .workerThreadSize(appConfig.http.workerThreads) 58 .maxRequestSize(cast(int)appConfig.http.maxHeaderSize) 59 .ioThreadSize(appConfig.http.ioThreads); 60 61 version(WITH_HUNT_TRACE) { 62 hsb.localServiceName(appConfig.application.name) 63 .isB3HeaderRequired(appConfig.trace.b3Required); 64 } 65 66 auto staticFilesConfig = appConfig.staticfiles; 67 68 RouteConfigManager routeConfig = container.resolve!RouteConfigManager(); 69 RouteItem[][RouteGroup] allRoutes = routeConfig.allRoutes; 70 71 foreach(RouteGroup group, RouteItem[] routes; allRoutes) { 72 foreach (RouteItem item; routes) { 73 addRoute(hsb, item, group); 74 } 75 76 RouteGroupType groupType = RouteGroupType.Host; 77 if (group.type == "path") { 78 groupType = RouteGroupType.Path; 79 } 80 // if(!isRootStaticPathAdded) { 81 // default static files 82 hsb.resource("/", staticFilesConfig.location, staticFilesConfig.canList, group.value, groupType); 83 // } 84 } 85 86 // default static files 87 hsb.resource("/", staticFilesConfig.location, staticFilesConfig.canList); 88 // hsb.setDefaultRequest((RoutingContext ctx) { 89 // string content = "The resource " ~ ctx.getURI().getPath() ~ " is not found"; 90 // string title = "404 - Not Found"; 91 92 // ctx.responseHeader(HttpHeader.CONTENT_TYPE, "text/html"); 93 94 // ctx.write("<!DOCTYPE html>") 95 // .write("<html>") 96 // .write("<head>") 97 // .write("<title>") 98 // .write(title) 99 // .write("</title>") 100 // .write("</head>") 101 // .write("<body>") 102 // .write("<h1> " ~ title ~ " </h1>") 103 // .write("<p>" ~ content ~ "</p>") 104 // .write("</body>") 105 // .end("</html>"); 106 // }); 107 108 return hsb.build(); 109 } 110 111 112 private void addRoute(HttpServer.Builder hsb, RouteItem item, RouteGroup group) { 113 ResourceRouteItem resourceItem = cast(ResourceRouteItem) item; 114 115 // add route for static files 116 if (resourceItem !is null) { 117 // if(resourceItem.path == "/") isRootStaticPathAdded = true; 118 if (group is null || group.type == RouteGroup.DEFAULT) { 119 hsb.resource(resourceItem.path, resourceItem.resourcePath, 120 resourceItem.canListing); 121 } else if (group.type == RouteGroup.HOST || group.type == RouteGroup.DOMAIN) { 122 hsb.resource(resourceItem.path, resourceItem.resourcePath, 123 resourceItem.canListing, group.value, RouteGroupType.Host); 124 } else if (group.type == RouteGroup.PATH) { 125 hsb.resource(resourceItem.path, resourceItem.resourcePath, 126 resourceItem.canListing, group.value, RouteGroupType.Path); 127 } else { 128 errorf("Unknown route group type: %s", group.type); 129 } 130 } else { // add route for controller action 131 string handlerKey = makeRouteHandlerKey(cast(ActionRouteItem) item, group); 132 RoutingHandler handler = getRouteHandler(handlerKey); 133 // warning(item.toString()); 134 if (handler is null) { 135 version(HUNT_DEBUG) { 136 warningf("No handler found for group route {%s}, key: %s", item.toString(), handlerKey); 137 } 138 } else { 139 version(HUNT_FM_DEBUG) 140 tracef("handler found for group route {%s}, key: %s", item.toString(), handlerKey); 141 string[] methods = item.methods; 142 version(HUNT_DEBUG) { 143 string methodsString = "[*]"; 144 if(!methods.empty) 145 methodsString = methods.to!string(); 146 } 147 148 RouterContex contex = new RouterContex(); 149 contex.routeGroup = group; 150 contex.routeItem = item; 151 152 if (group is null || group.type == RouteGroup.DEFAULT) { 153 version(HUNT_DEBUG) infof("adding %s %s into DEFAULT", methodsString, item.path); 154 hsb.addRoute([item.path], methods, handler, null, 155 RouteGroupType.Default, RouterContex.stringof, contex); 156 } else if (group.type == RouteGroup.HOST || group.type == RouteGroup.DOMAIN) { 157 version(HUNT_DEBUG) infof("adding %s %s into DOMAIN", methodsString, item.path); 158 hsb.addRoute([item.path], methods, handler, group.value, 159 RouteGroupType.Host, RouterContex.stringof, contex); 160 } else if (group.type == RouteGroup.PATH) { 161 version(HUNT_DEBUG) infof("adding %s %s into PATH", methodsString, item.path); 162 hsb.addRoute([item.path], methods, handler, group.value, 163 RouteGroupType.Path, RouterContex.stringof, contex); 164 } else { 165 errorf("Unknown route group type: %s", group.type); 166 } 167 } 168 } 169 } 170 }