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