2 * nghttp2 - HTTP/2 C Library
4 * Copyright (c) 2012 Tatsuhiro Tsujikawa
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 #include "nghttp2_config.h"
38 #include <openssl/ssl.h>
39 #include <openssl/err.h>
40 #include <openssl/conf.h>
41 #include <nghttp2/nghttp2.h>
43 #include "app_helper.h"
44 #include "HttpServer.h"
51 int parse_push_config(Config &config, const char *optarg) {
52 const char *eq = strchr(optarg, '=');
56 auto &paths = config.push[std::string(optarg, eq)];
57 auto optarg_end = optarg + strlen(optarg);
60 const char *j = strchr(i, ',');
64 paths.emplace_back(i, j);
65 if (j == optarg_end) {
77 void print_version(std::ostream &out) {
78 out << "nghttpd nghttp2/" NGHTTP2_VERSION << std::endl;
83 void print_usage(std::ostream &out) {
84 out << "Usage: nghttpd [OPTION]... <PORT> [<PRIVATE_KEY> <CERT>]\n"
85 << "HTTP/2 experimental server" << std::endl;
90 void print_help(std::ostream &out) {
93 <PORT> Specify listening port number.
95 Set path to server's private key. Required unless
96 --no-tls is specified.
97 <CERT> Set path to server's certificate. Required unless
98 --no-tls is specified.
101 Run in a background. If -D is used, the current working
102 directory is changed to '/'. Therefore if this option
103 is used, -d option must be specified.
105 The server sends a client certificate request. If the
106 client did not return a certificate, the handshake is
107 terminated. Currently, this option just requests a
108 client certificate and does not verify it.
110 Specify document root. If this option is not specified,
111 the document root is the current working directory.
113 Print debug information such as reception/ transmission
114 of frames and name/value pairs.
115 --no-tls Disable SSL/TLS.
116 -c, --header-table-size=<SIZE>
117 Specify decoder header table size.
118 --color Force colored log output.
119 -p, --push=<PATH>=<PUSH_PATH,...>
120 Push resources <PUSH_PATH>s when <PATH> is requested.
121 This option can be used repeatedly to specify multiple
122 push configurations. <PATH> and <PUSH_PATH>s are
123 relative to document root. See --htdocs option.
124 Example: -p/=/foo.png -p/doc=/bar.css
126 Add at most <N> bytes to a frame payload as padding.
127 Specify 0 to disable padding.
129 Set the number of worker threads.
132 Make error response gzipped.
133 --dh-param-file=<PATH>
134 Path to file that contains DH parameters in PEM format.
135 Without this option, DHE cipher suites are not
138 Start sending response when request HEADERS is received,
139 rather than complete request is received.
140 --version Display version information and exit.
141 -h, --help Display this help and exit.
143 The <SIZE> argument is an integer and an optional unit (e.g., 10K is
144 10 * 1024). Units are K, M and G (powers of 1024).)" << std::endl;
148 int main(int argc, char **argv) {
153 static option long_options[] = {
154 {"daemon", no_argument, nullptr, 'D'},
155 {"htdocs", required_argument, nullptr, 'd'},
156 {"help", no_argument, nullptr, 'h'},
157 {"verbose", no_argument, nullptr, 'v'},
158 {"verify-client", no_argument, nullptr, 'V'},
159 {"header-table-size", required_argument, nullptr, 'c'},
160 {"push", required_argument, nullptr, 'p'},
161 {"padding", required_argument, nullptr, 'b'},
162 {"workers", required_argument, nullptr, 'n'},
163 {"error-gzip", no_argument, nullptr, 'e'},
164 {"no-tls", no_argument, &flag, 1},
165 {"color", no_argument, &flag, 2},
166 {"version", no_argument, &flag, 3},
167 {"dh-param-file", required_argument, &flag, 4},
168 {"early-response", no_argument, &flag, 5},
169 {nullptr, 0, nullptr, 0}};
170 int option_index = 0;
172 getopt_long(argc, argv, "DVb:c:d:ehn:p:v", long_options, &option_index);
179 config.daemon = true;
182 config.verify_client = true;
185 config.padding = strtol(optarg, nullptr, 10);
188 config.htdocs = optarg;
191 config.error_gzip = true;
195 std::cerr << "-n: WARNING: Threading disabled at build time, "
196 << "no threads created." << std::endl;
199 config.num_worker = strtoul(optarg, &end, 10);
200 if (errno == ERANGE || *end != '\0' || config.num_worker == 0) {
201 std::cerr << "-n: Bad option value: " << optarg << std::endl;
207 print_help(std::cout);
210 config.verbose = true;
214 config.header_table_size = util::parse_uint_with_unit(optarg);
215 if (config.header_table_size == -1) {
216 std::cerr << "-c: Bad option value: " << optarg << std::endl;
221 if (parse_push_config(config, optarg) != 0) {
222 std::cerr << "-p: Bad option value: " << optarg << std::endl;
226 util::show_candidates(argv[optind - 1], long_options);
232 config.no_tls = true;
240 print_version(std::cout);
244 config.dh_param_file = optarg;
248 config.early_response = true;
256 if (argc - optind < (config.no_tls ? 1 : 3)) {
257 print_usage(std::cerr);
258 std::cerr << "Too few arguments" << std::endl;
262 config.port = strtol(argv[optind++], nullptr, 10);
264 if (!config.no_tls) {
265 config.private_key_file = argv[optind++];
266 config.cert_file = argv[optind++];
270 if (config.htdocs.empty()) {
271 print_usage(std::cerr);
272 std::cerr << "-d option must be specified when -D is used." << std::endl;
275 if (daemon(0, 0) == -1) {
280 if (config.htdocs.empty()) {
281 config.htdocs = "./";
284 set_color_output(color || isatty(fileno(stdout)));
286 struct sigaction act;
287 memset(&act, 0, sizeof(struct sigaction));
288 act.sa_handler = SIG_IGN;
289 sigaction(SIGPIPE, &act, nullptr);
290 OPENSSL_config(nullptr);
291 OpenSSL_add_all_algorithms();
292 SSL_load_error_strings();
295 ssl::LibsslGlobalLock lock;
300 HttpServer server(&config);
305 } // namespace nghttp2
307 int main(int argc, char **argv) { return nghttp2::main(argc, argv); }