1 module handy_httpd.handlers; 2 3 import std.stdio; 4 5 import handy_httpd.handler; 6 import handy_httpd.request; 7 import handy_httpd.response; 8 import handy_httpd.responses; 9 10 /** 11 * Request handler that resolves files within a given base path. 12 */ 13 class FileResolvingHandler : HttpRequestHandler { 14 import std.file; 15 import std.algorithm.searching; 16 import std.string; 17 import std.uni; 18 19 private string basePath; 20 21 this(string basePath = ".") { 22 this.basePath = basePath; 23 } 24 25 HttpResponse handle(HttpRequest request) { 26 if (request.url.canFind("/../")) { // Forbid the use of navigating to parent directories. 27 return notFound(); 28 } 29 string path = "index.html"; 30 if (request.url != "/") { 31 path = request.url[1..$]; 32 } 33 path = this.basePath ~ "/" ~ path; 34 if (!exists(path)) return notFound(); 35 return fileResponse(path, getMimeType(path)); 36 } 37 38 private string getMimeType(string filename) { 39 string[string] MIME_TYPES = [ 40 ".html": "text/html", 41 ".js": "text/javascript", 42 ".css": "text/css", 43 ".json": "application/json", 44 ".png": "image/png", 45 ".jpg": "image/jpg", 46 ".gif": "image/gif", 47 ".wav": "audio/wav", 48 ".ogg": "audio/ogg", 49 ".mp3": "audio/mpeg", 50 ".mp4": "video/mp4", 51 ".woff": "application/font-woff", 52 ".ttf": "application/font-ttf", 53 ".eot": "application/vnd.ms-fontobject", 54 ".otf": "application/font-otf", 55 ".svg": "application/image/svg+xml", 56 ".wasm": "application/wasm" 57 ]; 58 auto p = filename.lastIndexOf('.'); 59 if (p == -1) return "text/html"; 60 string extension = filename[p..$].toLower(); 61 if (extension !in MIME_TYPES) { 62 writefln!"Warning: Unknown mime type for file extension %s"(extension); 63 return "text/plain"; 64 } 65 return MIME_TYPES[extension]; 66 } 67 }