1 /**
2  * Start a HTTP server on a port and serve the files in the current directory.
3  *
4  * License:
5  *   This Source Code Form is subject to the terms of
6  *   the Mozilla Public License, v. 2.0. If a copy of
7  *   the MPL was not distributed with this file, You
8  *   can obtain one at http://mozilla.org/MPL/2.0/.
9  *
10  * Authors:
11  *   Vladimir Panteleev <ae@cy.md>
12  */
13 
14 module ae.demo.http.httpserve;
15 
16 import std.algorithm.searching;
17 import std.base64;
18 import std.conv;
19 import std.datetime;
20 import std.exception;
21 import std.stdio;
22 import std.string;
23 
24 import ae.net.asockets;
25 import ae.net.http.common;
26 import ae.net.http.responseex;
27 import ae.net.http.server;
28 import ae.net.ietf.headers;
29 import ae.net.ssl.openssl;
30 import ae.sys.log;
31 import ae.sys.shutdown;
32 import ae.utils.funopt;
33 import ae.utils.main;
34 
35 mixin SSLUseLib;
36 
37 void httpserve(
38 	ushort port = 0, string host = null,
39 	string sslCert = null, string sslKey = null,
40 	string userName = null, string password = null,
41 	bool stripQueryParameters = false,
42 )
43 {
44 	HttpServer server;
45 
46 	if (sslCert || sslKey)
47 	{
48 		auto https = new HttpsServer();
49 		https.ctx.setCertificate(sslCert);
50 		https.ctx.setPrivateKey(sslKey);
51 		server = https;
52 	}
53 	else
54 		server = new HttpServer();
55 
56 	server.log = consoleLogger("Web");
57 	server.handleRequest =
58 		(HttpRequest request, HttpServerConnection conn)
59 		{
60 			auto response = new HttpResponseEx();
61 
62 			if ((userName || password) &&
63 				!response.authorize(request, (reqUser, reqPass) => reqUser == userName && reqPass == password))
64 				return conn.sendResponse(response);
65 
66 			response.status = HttpStatusCode.OK;
67 
68 			auto path = request.resource[1..$];
69 			if (stripQueryParameters)
70 				path = path.findSplit("?")[0];
71 
72 			try
73 				response.serveFile(
74 					decodeUrlParameter(path),
75 					"",
76 					true,
77 					formatAddress("http", conn.localAddress, request.host, request.port) ~ "/");
78 			catch (Exception e)
79 				response.writeError(HttpStatusCode.InternalServerError, e.msg);
80 			conn.sendResponse(response);
81 		};
82 	server.listen(port, host);
83 	addShutdownHandler((reason) { server.close(); });
84 
85 	socketManager.loop();
86 }
87 
88 mixin main!(funopt!httpserve);