1//
2// TimeServer.cpp
3//
4// This sample demonstrates the HTTPServer and related classes.
5//
6// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
7// and Contributors.
8//
9// SPDX-License-Identifier: BSL-1.0
10//
11
12
13#include "Poco/Net/HTTPServer.h"
14#include "Poco/Net/HTTPRequestHandler.h"
15#include "Poco/Net/HTTPRequestHandlerFactory.h"
16#include "Poco/Net/HTTPServerParams.h"
17#include "Poco/Net/HTTPServerRequestImpl.h"
18#include "Poco/Net/HTTPServerResponse.h"
19#include "Poco/Net/HTTPServerParams.h"
20#include "Poco/Net/SecureStreamSocket.h"
21#include "Poco/Net/SecureServerSocket.h"
22#include "Poco/Net/X509Certificate.h"
23#include "Poco/Timestamp.h"
24#include "Poco/DateTimeFormatter.h"
25#include "Poco/DateTimeFormat.h"
26#include "Poco/Exception.h"
27#include "Poco/SharedPtr.h"
28#include "Poco/Util/ServerApplication.h"
29#include "Poco/Util/Option.h"
30#include "Poco/Util/OptionSet.h"
31#include "Poco/Util/HelpFormatter.h"
32#include "Poco/Net/SSLManager.h"
33#include "Poco/Net/KeyConsoleHandler.h"
34#include "Poco/Net/AcceptCertificateHandler.h"
35#include <iostream>
36
37
38using Poco::Net::SecureServerSocket;
39using Poco::Net::SecureStreamSocket;
40using Poco::Net::HTTPRequestHandler;
41using Poco::Net::HTTPRequestHandlerFactory;
42using Poco::Net::HTTPServer;
43using Poco::Net::HTTPServerRequest;
44using Poco::Net::HTTPServerRequestImpl;
45using Poco::Net::X509Certificate;
46using Poco::Net::HTTPServerResponse;
47using Poco::Net::HTTPServerParams;
48using Poco::Timestamp;
49using Poco::DateTimeFormatter;
50using Poco::DateTimeFormat;
51using Poco::SharedPtr;
52using Poco::Util::ServerApplication;
53using Poco::Util::Application;
54using Poco::Util::Option;
55using Poco::Util::OptionSet;
56using Poco::Util::HelpFormatter;
57using Poco::Net::SSLManager;
58using Poco::Net::Context;
59using Poco::Net::KeyConsoleHandler;
60using Poco::Net::PrivateKeyPassphraseHandler;
61using Poco::Net::InvalidCertificateHandler;
62using Poco::Net::AcceptCertificateHandler;
63
64
65class TimeRequestHandler: public HTTPRequestHandler
66 /// Return a HTML document with the current date and time.
67{
68public:
69 TimeRequestHandler(const std::string& format):
70 _format(format)
71 {
72 }
73
74 void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response)
75 {
76 Application& app = Application::instance();
77 app.logger().information("Request from " + request.clientAddress().toString());
78
79 SecureStreamSocket socket = static_cast<HTTPServerRequestImpl&>(request).socket();
80 if (socket.havePeerCertificate())
81 {
82 X509Certificate cert = socket.peerCertificate();
83 app.logger().information("Client certificate: " + cert.subjectName());
84 }
85 else
86 {
87 app.logger().information("No client certificate available.");
88 }
89
90 Timestamp now;
91 std::string dt(DateTimeFormatter::format(now, _format));
92
93 response.setChunkedTransferEncoding(true);
94 response.setContentType("text/html");
95
96 std::ostream& ostr = response.send();
97 ostr << "<html><head><title>HTTPTimeServer powered by POCO C++ Libraries</title>";
98 ostr << "<meta http-equiv=\"refresh\" content=\"1\"></head>";
99 ostr << "<body><p style=\"text-align: center; font-size: 48px;\">";
100 ostr << dt;
101 ostr << "</p></body></html>";
102 }
103
104private:
105 std::string _format;
106};
107
108
109class TimeRequestHandlerFactory: public HTTPRequestHandlerFactory
110{
111public:
112 TimeRequestHandlerFactory(const std::string& format):
113 _format(format)
114 {
115 }
116
117 HTTPRequestHandler* createRequestHandler(const HTTPServerRequest& request)
118 {
119 if (request.getURI() == "/")
120 return new TimeRequestHandler(_format);
121 else
122 return 0;
123 }
124
125private:
126 std::string _format;
127};
128
129
130class HTTPSTimeServer: public Poco::Util::ServerApplication
131 /// The main application class.
132 ///
133 /// This class handles command-line arguments and
134 /// configuration files.
135 /// Start the HTTPTimeServer executable with the help
136 /// option (/help on Windows, --help on Unix) for
137 /// the available command line options.
138 ///
139 /// To use the sample configuration file (HTTPTimeServer.properties),
140 /// copy the file to the directory where the HTTPTimeServer executable
141 /// resides. If you start the debug version of the HTTPTimeServer
142 /// (HTTPTimeServerd[.exe]), you must also create a copy of the configuration
143 /// file named HTTPTimeServerd.properties. In the configuration file, you
144 /// can specify the port on which the server is listening (default
145 /// 9443) and the format of the date/time string sent back to the client.
146 ///
147 /// To test the TimeServer you can use any web browser (https://localhost:9443/).
148{
149public:
150 HTTPSTimeServer(): _helpRequested(false)
151 {
152 Poco::Net::initializeSSL();
153 }
154
155 ~HTTPSTimeServer()
156 {
157 Poco::Net::uninitializeSSL();
158 }
159
160protected:
161 void initialize(Application& self)
162 {
163 loadConfiguration(); // load default configuration files, if present
164 ServerApplication::initialize(self);
165 }
166
167 void uninitialize()
168 {
169 ServerApplication::uninitialize();
170 }
171
172 void defineOptions(OptionSet& options)
173 {
174 ServerApplication::defineOptions(options);
175
176 options.addOption(
177 Option("help", "h", "display help information on command line arguments")
178 .required(false)
179 .repeatable(false));
180 }
181
182 void handleOption(const std::string& name, const std::string& value)
183 {
184 ServerApplication::handleOption(name, value);
185
186 if (name == "help")
187 _helpRequested = true;
188 }
189
190 void displayHelp()
191 {
192 HelpFormatter helpFormatter(options());
193 helpFormatter.setCommand(commandName());
194 helpFormatter.setUsage("OPTIONS");
195 helpFormatter.setHeader("A web server that serves the current date and time.");
196 helpFormatter.format(std::cout);
197 }
198
199 int main(const std::vector<std::string>& args)
200 {
201 if (_helpRequested)
202 {
203 displayHelp();
204 }
205 else
206 {
207 // get parameters from configuration file
208 unsigned short port = (unsigned short) config().getInt("HTTPSTimeServer.port", 9443);
209 std::string format(config().getString("HTTPSTimeServer.format", DateTimeFormat::SORTABLE_FORMAT));
210
211 // set-up a server socket
212 SecureServerSocket svs(port);
213 // set-up a HTTPServer instance
214 HTTPServer srv(new TimeRequestHandlerFactory(format), svs, new HTTPServerParams);
215 // start the HTTPServer
216 srv.start();
217 // wait for CTRL-C or kill
218 waitForTerminationRequest();
219 // Stop the HTTPServer
220 srv.stop();
221 }
222 return Application::EXIT_OK;
223 }
224
225private:
226 bool _helpRequested;
227};
228
229
230int main(int argc, char** argv)
231{
232 HTTPSTimeServer app;
233 return app.run(argc, argv);
234}
235