xref: /aosp_15_r20/external/cronet/net/tools/testserver/run_testserver.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <stdio.h>
6 
7 #include <memory>
8 
9 #include "base/at_exit.h"
10 #include "base/command_line.h"
11 #include "base/files/file_path.h"
12 #include "base/files/file_util.h"
13 #include "base/logging.h"
14 #include "base/message_loop/message_pump_type.h"
15 #include "base/run_loop.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "base/task/single_thread_task_executor.h"
18 #include "base/test/test_timeouts.h"
19 #include "net/test/embedded_test_server/embedded_test_server.h"
20 #include "net/test/spawned_test_server/spawned_test_server.h"
21 
PrintUsage()22 static void PrintUsage() {
23   printf(
24       "run_testserver --doc-root=relpath\n"
25       "               [--http|--https|--ws|--wss]\n"
26       "               [--ssl-cert=ok|mismatched-name|expired]\n");
27   printf("(NOTE: relpath should be relative to the 'src' directory.\n");
28 }
29 
main(int argc,const char * argv[])30 int main(int argc, const char* argv[]) {
31   base::AtExitManager at_exit_manager;
32   base::SingleThreadTaskExecutor io_task_executor(base::MessagePumpType::IO);
33 
34   // Process command line
35   base::CommandLine::Init(argc, argv);
36   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
37 
38   logging::LoggingSettings settings;
39   settings.logging_dest = logging::LOG_TO_ALL;
40   settings.log_file_path = FILE_PATH_LITERAL("testserver.log");
41   if (!logging::InitLogging(settings)) {
42     printf("Error: could not initialize logging. Exiting.\n");
43     return -1;
44   }
45 
46   TestTimeouts::Initialize();
47 
48   if (command_line->GetSwitches().empty() ||
49       command_line->HasSwitch("help")) {
50     PrintUsage();
51     return -1;
52   }
53 
54   // If populated, EmbeddedTestServer is used instead of the SpawnedTestServer.
55   std::optional<net::EmbeddedTestServer::Type> embedded_test_server_type;
56 
57   net::SpawnedTestServer::Type server_type;
58   if (command_line->HasSwitch("http")) {
59     embedded_test_server_type = net::EmbeddedTestServer::TYPE_HTTP;
60   } else if (command_line->HasSwitch("https")) {
61     embedded_test_server_type = net::EmbeddedTestServer::TYPE_HTTPS;
62   } else if (command_line->HasSwitch("ws")) {
63     server_type = net::SpawnedTestServer::TYPE_WS;
64   } else if (command_line->HasSwitch("wss")) {
65     server_type = net::SpawnedTestServer::TYPE_WSS;
66   } else {
67     // If no scheme switch is specified, select http or https scheme.
68     // TODO(toyoshim): Remove this estimation.
69     if (command_line->HasSwitch("ssl-cert")) {
70       embedded_test_server_type = net::EmbeddedTestServer::TYPE_HTTPS;
71     } else {
72       embedded_test_server_type = net::EmbeddedTestServer::TYPE_HTTP;
73     }
74   }
75 
76   net::SpawnedTestServer::SSLOptions ssl_options;
77   net::EmbeddedTestServer::ServerCertificate server_certificate;
78   if (command_line->HasSwitch("ssl-cert")) {
79     if ((embedded_test_server_type.has_value() &&
80          *embedded_test_server_type != net::EmbeddedTestServer::TYPE_HTTPS) ||
81         (!embedded_test_server_type.has_value() &&
82          !net::SpawnedTestServer::UsingSSL(server_type))) {
83       printf("Error: --ssl-cert is specified on non-secure scheme\n");
84       PrintUsage();
85       return -1;
86     }
87     std::string cert_option = command_line->GetSwitchValueASCII("ssl-cert");
88     if (cert_option == "ok") {
89       ssl_options.server_certificate =
90           net::SpawnedTestServer::SSLOptions::CERT_OK;
91       server_certificate = net::EmbeddedTestServer::CERT_OK;
92     } else if (cert_option == "mismatched-name") {
93       ssl_options.server_certificate =
94           net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME;
95       server_certificate = net::EmbeddedTestServer::CERT_MISMATCHED_NAME;
96     } else if (cert_option == "expired") {
97       ssl_options.server_certificate =
98           net::SpawnedTestServer::SSLOptions::CERT_EXPIRED;
99       server_certificate = net::EmbeddedTestServer::CERT_EXPIRED;
100     } else {
101       printf("Error: --ssl-cert has invalid value %s\n", cert_option.c_str());
102       PrintUsage();
103       return -1;
104     }
105   }
106 
107   base::FilePath doc_root = command_line->GetSwitchValuePath("doc-root");
108   if (doc_root.empty()) {
109     printf("Error: --doc-root must be specified\n");
110     PrintUsage();
111     return -1;
112   }
113 
114   base::FilePath full_path =
115       net::test_server::EmbeddedTestServer::GetFullPathFromSourceDirectory(
116           doc_root);
117   if (!base::DirectoryExists(full_path)) {
118     printf("Error: invalid doc root: \"%s\" does not exist!\n",
119            base::UTF16ToUTF8(full_path.LossyDisplayName()).c_str());
120     return -1;
121   }
122 
123   // Use EmbeddedTestServer, if it supports the provided configuration.
124   if (embedded_test_server_type.has_value()) {
125     net::EmbeddedTestServer embedded_test_server(*embedded_test_server_type);
126     if (*embedded_test_server_type == net::EmbeddedTestServer::TYPE_HTTPS) {
127       embedded_test_server.SetSSLConfig(server_certificate);
128     }
129 
130     embedded_test_server.AddDefaultHandlers(doc_root);
131     if (!embedded_test_server.Start()) {
132       printf("Error: failed to start embedded test server. Exiting.\n");
133       return -1;
134     }
135 
136     printf("Embedded test server running at %s (type ctrl+c to exit)\n",
137            embedded_test_server.host_port_pair().ToString().c_str());
138 
139     base::RunLoop().Run();
140     return 0;
141   }
142 
143   // Otherwise, use the SpawnedTestServer.
144   std::unique_ptr<net::SpawnedTestServer> test_server;
145   if (net::SpawnedTestServer::UsingSSL(server_type)) {
146     test_server = std::make_unique<net::SpawnedTestServer>(
147         server_type, ssl_options, doc_root);
148   } else {
149     test_server =
150         std::make_unique<net::SpawnedTestServer>(server_type, doc_root);
151   }
152 
153   if (!test_server->Start()) {
154     printf("Error: failed to start test server. Exiting.\n");
155     return -1;
156   }
157 
158   printf("testserver running at %s (type ctrl+c to exit)\n",
159          test_server->host_port_pair().ToString().c_str());
160 
161   base::RunLoop().Run();
162 }
163