├── .editorconfig ├── .gitignore ├── LICENSE ├── README.md ├── dub.sdl ├── dub.selections.json └── source └── app.d /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*.{c,h,d,di,dd,json}] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | indent_style = space 7 | indent_size = 4 8 | trim_trailing_whitespace = true 9 | charset = utf-8 10 | 11 | [*.{d,di,dd}] 12 | indent_brace_style = allman 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .dub 2 | docs.json 3 | __dummy.html 4 | *.o 5 | *.obj 6 | serve 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Martin Nowak 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # serve [![Dub](https://img.shields.io/dub/v/serve.svg)](http://code.dlang.org/packages/serve) ![Uses vibe.d](https://img.shields.io/badge/uses-vibe.d-brightgreen.svg) 2 | A simple HTTP server for static files. 3 | 4 | ### Installation 5 | 6 | You can simply use dub to run the tool. 7 | 8 | ```sh 9 | dub fetch serve 10 | dub run serve 11 | dub run serve -- [ARGS] 12 | ``` 13 | 14 | Or you build the tool and copy/symlink it into your path. 15 | 16 | ```sh 17 | dub fetch serve 18 | dub build serve 19 | sudo mv ~/.dub/packages/serve-1.0.0/serve /usr/local/bin/ 20 | ``` 21 | 22 | ### Usage 23 | 24 | - serve the current working directory 25 | 26 | ```sh 27 | serve 28 | ``` 29 | 30 | - serve an html file with it's containing folder and open it in your browser 31 | 32 | ```sh 33 | serve path/to/index.html 34 | ``` 35 | 36 | - serve a folder 37 | 38 | ```sh 39 | serve path/to/folder 40 | ``` 41 | 42 | - use a different port than 8080 (`-p|--port`) 43 | 44 | ```sh 45 | serve -p 1234 46 | ``` 47 | 48 | - bind a different IP address than 127.0.0.1 using (`-b|--bind`) 49 | 50 | ```sh 51 | serve -b 127.0.0.1 52 | ``` 53 | 54 | - run `-h|--help` to see all options 55 | 56 | ```sh 57 | serve -h 58 | ``` 59 | -------------------------------------------------------------------------------- /dub.sdl: -------------------------------------------------------------------------------- 1 | name "serve" 2 | description "A simple HTTP server for static files." 3 | authors "Martin Nowak" 4 | copyright "Copyright © 2015-, Martin Nowak" 5 | license "MIT" 6 | dependency "vibe-d:http" version="~>0.9.3" 7 | sourcePaths "source/" 8 | versions "VibeCustomMain" 9 | targetType "executable" 10 | configuration "app" { 11 | versions "VibeNoSSL" 12 | } 13 | configuration "https" { 14 | } 15 | -------------------------------------------------------------------------------- /dub.selections.json: -------------------------------------------------------------------------------- 1 | { 2 | "fileVersion": 1, 3 | "versions": { 4 | "botan": "1.12.19", 5 | "botan-math": "1.0.3", 6 | "diet-ng": "1.7.4", 7 | "eventcore": "0.9.13", 8 | "libasync": "0.8.6", 9 | "memutils": "1.0.4", 10 | "mir-linux-kernel": "1.0.1", 11 | "openssl": "1.1.6+1.0.1g", 12 | "stdx-allocator": "2.77.5", 13 | "taggedalgebraic": "0.11.19", 14 | "vibe-core": "1.13.0", 15 | "vibe-d": "0.9.3" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /source/app.d: -------------------------------------------------------------------------------- 1 | import vibe.core.core : lowerPrivileges, runEventLoop; 2 | import vibe.http.fileserver : serveStaticFiles; 3 | import vibe.core.args, vibe.http.server, vibe.inet.url; 4 | import vibe.stream.tls : createTLSContext, TLSContextKind; 5 | import std.file, std.getopt, std.path, std.process, std.stdio, std.string; 6 | 7 | int main() 8 | { 9 | scope settings = new HTTPServerSettings; 10 | settings.port = 8080; 11 | settings.bindAddresses = ["127.0.0.1"]; 12 | bool help; 13 | readOption("bind|b", &settings.bindAddresses[0], 14 | "Sets the address used for serving. (default 127.0.0.1)"); 15 | readOption("port|p", &settings.port, "Sets the port used for serving. (default 8080)"); 16 | version (VibeNoSSL) {} 17 | else 18 | { 19 | string pem; 20 | if (readOption("https-crt", &pem, "Serve over https using the given combined PEM TLS certificate/key file.")) 21 | { 22 | settings.tlsContext = createTLSContext(TLSContextKind.server); 23 | settings.tlsContext.useCertificateChainFile(pem); 24 | settings.tlsContext.usePrivateKeyFile(pem); 25 | } 26 | } 27 | 28 | // returns false if a help screen has been requested and displayed (--help) 29 | string[] args; 30 | if (!finalizeCommandLineOptions(&args)) 31 | return 0; 32 | 33 | auto path = args.length > 1 ? args[1] : "."; 34 | 35 | path = path.absolutePath.buildNormalizedPath; 36 | auto folder = path.isDir ? path : path.dirName; 37 | writefln("serving '%s'", folder.relativePath); 38 | auto l = listenHTTP(settings, serveStaticFiles(folder)); 39 | 40 | if (!path.isDir && path.extension == ".html") 41 | { 42 | auto url = URL("http", settings.bindAddresses[0], settings.port, NativePath("/" ~ path.baseName)); 43 | writefln("opening %s in a browser", url); 44 | browse(url.toString()); 45 | } 46 | 47 | lowerPrivileges(); 48 | return runEventLoop(); 49 | } 50 | --------------------------------------------------------------------------------