File: embedded_test_server.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (767 lines) | stat: -rw-r--r-- 31,894 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef NET_TEST_EMBEDDED_TEST_SERVER_EMBEDDED_TEST_SERVER_H_
#define NET_TEST_EMBEDDED_TEST_SERVER_EMBEDDED_TEST_SERVER_H_

#include <stdint.h>

#include <map>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <vector>

#include "base/callback_list.h"
#include "base/files/file_path.h"
#include "base/functional/callback.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread.h"
#include "base/threading/thread_checker.h"
#include "base/types/expected.h"
#include "net/base/address_list.h"
#include "net/base/host_port_pair.h"
#include "net/base/ip_endpoint.h"
#include "net/cert/test_root_certs.h"
#include "net/cert/x509_certificate.h"
#include "net/socket/ssl_server_socket.h"
#include "net/socket/stream_socket.h"
#include "net/socket/tcp_server_socket.h"
#include "net/ssl/ssl_server_config.h"
#include "net/test/cert_builder.h"
#include "net/test/embedded_test_server/http_connection.h"
#include "third_party/boringssl/src/include/openssl/pki/ocsp.h"
#include "third_party/boringssl/src/pki/parse_certificate.h"
#include "url/gurl.h"
#include "url/origin.h"

namespace net {

class StreamSocket;
class TCPServerSocket;

namespace test_server {

class EmbeddedTestServerConnectionListener;
class HttpConnection;
class HttpConnectProxyHandler;
class HttpResponse;
class HttpResponseDelegate;
struct HttpRequest;

class EmbeddedTestServer;

// Enum representing the possible outcomes of handling an upgrade request.
// - kUpgraded: The request was successfully upgraded to a WebSocket connection.
// - kNotHandled: The request was not handled as an upgrade and should be
// processed as a normal HTTP request.
enum class UpgradeResult {
  kUpgraded,
  kNotHandled,
};

// Returned by the Start[AcceptingConnections]WithHandle() APIs, to simplify
// correct shutdown ordering of the EmbeddedTestServer. Shutdown() is invoked
// on the associated test server when the handle goes out of scope. The handle
// must therefore be destroyed before the test server.
class EmbeddedTestServerHandle {
 public:
  EmbeddedTestServerHandle() = default;
  EmbeddedTestServerHandle(EmbeddedTestServerHandle&& other);
  EmbeddedTestServerHandle& operator=(EmbeddedTestServerHandle&& other);
  ~EmbeddedTestServerHandle();

  bool is_valid() const { return test_server_; }
  explicit operator bool() const { return test_server_; }

 private:
  friend class EmbeddedTestServer;

  explicit EmbeddedTestServerHandle(EmbeddedTestServer* test_server);
  raw_ptr<EmbeddedTestServer> test_server_ = nullptr;
};

// Class providing an HTTP server for testing purpose. This is a basic server
// providing only an essential subset of HTTP/1.1 protocol. Especially,
// it assumes that the request syntax is correct. It *does not* support
// a Chunked Transfer Encoding.
//
// The common use case for unit tests is below:
//
// void SetUp() {
//   test_server_ = std::make_unique<EmbeddedTestServer>();
//   test_server_->RegisterRequestHandler(
//       base::BindRepeating(&FooTest::HandleRequest, base::Unretained(this)));
//   ASSERT_TRUE((test_server_handle_ = test_server_.StartAndReturnHandle()));
// }
//
// std::unique_ptr<HttpResponse> HandleRequest(const HttpRequest& request) {
//   GURL absolute_url = test_server_->GetURL(request.relative_url);
//   if (absolute_url.path() != "/test")
//     return nullptr;
//
//   auto http_response = std::make_unique<BasicHttpResponse>();
//   http_response->set_code(net::HTTP_OK);
//   http_response->set_content("hello");
//   http_response->set_content_type("text/plain");
//   return http_response;
// }
//
// For a test that spawns another process such as browser_tests, it is
// suggested to call Start in SetUpOnMainThread after the process is spawned.
//  If you have to do it before the process spawns, you need to first setup the
// listen socket so that there is no no other threads running while spawning
// the process. To do so, please follow the following example:
//
// void SetUp() {
//   ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
//   ...
//   InProcessBrowserTest::SetUp();
// }
//
// void SetUpOnMainThread() {
//   // Starts the accept IO thread.
//   embedded_test_server()->StartAcceptingConnections();
// }
//
class EmbeddedTestServer {
 public:
  enum Type {
    TYPE_HTTP,
    TYPE_HTTPS,
  };

  // A Java counterpart will be generated for this enum.
  // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.net.test
  enum ServerCertificate {
    CERT_OK,

    CERT_MISMATCHED_NAME,
    CERT_EXPIRED,

    // Cross-signed certificate to test PKIX path building. Contains an
    // intermediate cross-signed by an unknown root, while the client (via
    // TestRootStore) is expected to have a self-signed version of the
    // intermediate.
    CERT_CHAIN_WRONG_ROOT,

    // Causes the testserver to use a hostname that is a domain
    // instead of an IP.
    CERT_COMMON_NAME_IS_DOMAIN,

    // A certificate that only contains a commonName, rather than also
    // including a subjectAltName extension.
    CERT_COMMON_NAME_ONLY,

    // A certificate that is a leaf certificate signed with SHA-1.
    CERT_SHA1_LEAF,

    // A certificate that is signed by an intermediate certificate.
    CERT_OK_BY_INTERMEDIATE,

    // A certificate that covers a number of test names. See [test_names] in
    // net/data/ssl/scripts/ee.cnf. More may be added by editing this list and
    // and rerunning net/data/ssl/scripts/generate-test-certs.sh.
    CERT_TEST_NAMES,

    // An RSA certificate with the keyUsage extension specifying that the key
    // is only for encipherment.
    CERT_KEY_USAGE_RSA_ENCIPHERMENT,

    // An RSA certificate with the keyUsage extension specifying that the key
    // is only for digital signatures.
    CERT_KEY_USAGE_RSA_DIGITAL_SIGNATURE,

    // A certificate will be generated at runtime. A ServerCertificateConfig
    // passed to SetSSLConfig may be used to configure the details of the
    // generated certificate.
    CERT_AUTO,
  };

  enum class RootType {
    // The standard test_root_ca.pem certificate will be used, which should be
    // trusted by default. (See `RegisterTestCerts`.)
    kTestRootCa,
    // A new CA certificate will be generated at runtime. The generated
    // certificate chain will not be trusted unless the test itself trusts it.
    kUniqueRoot,
  };

  enum class IntermediateType {
    // Generated cert is issued directly by the CA.
    kNone,
    // Generated cert is issued by a generated intermediate cert, which is
    // included in the TLS handshake.
    kInHandshake,
    // Generated cert is issued by a generated intermediate, which is NOT
    // included in the TLS handshake, but is available through the leaf's
    // AIA caIssuers URL.
    kByAIA,
    // Generated cert is issued by a generated intermediate, which is NOT
    // included in the TLS handshake and not served by an AIA server.
    kMissing,
  };

  struct OCSPConfig {
    // Enumerates the types of OCSP response that the testserver can produce.
    enum class ResponseType {
      // OCSP will not be enabled for the corresponding config.
      kOff,
      // These correspond to the OCSPResponseStatus enumeration in RFC
      // 6960.
      kSuccessful,
      kMalformedRequest,
      kInternalError,
      kTryLater,
      kSigRequired,
      kUnauthorized,
      // The response will not be valid bssl::OCSPResponse DER.
      kInvalidResponse,
      // bssl::OCSPResponse will be valid DER but the contained ResponseData
      // will not.
      kInvalidResponseData,
    };

    // OCSPProduced describes the time of the producedAt field in the
    // OCSP response relative to the certificate the response is for.
    enum class Produced {
      // producedAt is between certificate's notBefore and notAfter dates.
      kValid,
      // producedAt is before certificate's notBefore date.
      kBeforeCert,
      // producedAt is after certificate's notAfter date.
      kAfterCert,
    };

    struct SingleResponse {
      // Date describes the thisUpdate..nextUpdate ranges for OCSP
      // singleResponses, relative to the current time.
      enum class Date {
        // The singleResponse is valid for 7 days, and includes the current
        // time.
        kValid,
        // The singleResponse is valid for 7 days, but nextUpdate is before the
        // current time.
        kOld,
        // The singleResponse is valid for 7 days, but thisUpdate is after the
        // current time.
        kEarly,
        // The singleResponse is valid for 366 days, and includes the current
        // time.
        kLong,
        // The singleResponse is valid for 368 days, and includes the current
        // time.
        kLonger,
      };

      // Configures whether a generated OCSP singleResponse's serial field
      // matches the serial number of the target certificate.
      enum class Serial {
        kMatch,
        kMismatch,
      };

      bssl::OCSPRevocationStatus cert_status = bssl::OCSPRevocationStatus::GOOD;
      Date ocsp_date = Date::kValid;
      Serial serial = Serial::kMatch;
    };

    OCSPConfig();
    // Configure OCSP response with |response_type|.
    explicit OCSPConfig(ResponseType response_type);
    // Configure a successful OCSP response with |single_responses|. |produced|
    // specifies the response's producedAt value, relative to the validity
    // period of the certificate the OCSPConfig is for.
    explicit OCSPConfig(std::vector<SingleResponse> single_responses,
                        Produced produced = Produced::kValid);
    OCSPConfig(const OCSPConfig&);
    OCSPConfig(OCSPConfig&&);
    ~OCSPConfig();
    OCSPConfig& operator=(const OCSPConfig&);
    OCSPConfig& operator=(OCSPConfig&&);

    ResponseType response_type = ResponseType::kOff;
    Produced produced = Produced::kValid;
    std::vector<SingleResponse> single_responses;
  };

  // Configuration for generated server certificate.
  struct ServerCertificateConfig {
    ServerCertificateConfig();
    ServerCertificateConfig(const ServerCertificateConfig&);
    ServerCertificateConfig(ServerCertificateConfig&&);
    ~ServerCertificateConfig();
    ServerCertificateConfig& operator=(const ServerCertificateConfig&);
    ServerCertificateConfig& operator=(ServerCertificateConfig&&);

    // Configure what root CA certificate should be used to issue the generated
    // certificate chain.
    RootType root = RootType::kTestRootCa;

    // Configure whether the generated certificate chain should include an
    // intermediate, and if so, how it is delivered to the client.
    IntermediateType intermediate = IntermediateType::kNone;

    // Configure OCSP handling.
    // Note: In the current implementation the AIA request handler does not
    // actually parse the OCSP request (a different OCSP URL is used for each
    // cert). So this is useful for testing the client's handling of the OCSP
    // response, but not for testing that the client is sending a proper OCSP
    // request.
    //
    // AIA OCSP for the leaf cert. If |kOff|, no AIA OCSP URL will be included
    // in the leaf cert.
    OCSPConfig ocsp_config;
    // Stapled OCSP for the leaf cert. If |kOff|, OCSP Stapling will not be
    // used.
    OCSPConfig stapled_ocsp_config;
    // AIA OCSP for the intermediate cert. If |kOff|, no AIA OCSP URL will be
    // included in the intermediate cert. It is invalid to supply a
    // configuration other than |kOff| if |intermediate| is |kNone|.
    OCSPConfig intermediate_ocsp_config;

    // Certificate policy OIDs, in text notation (e.g. "1.2.3.4"). If
    // non-empty, the policies will be added to the leaf cert and the
    // intermediate cert (if an intermediate is configured).
    std::vector<std::string> policy_oids;

    // QWAC QC types for the QcStatements extension. If non-empty, the
    // QcStatements extension will be set on the leaf cert containing values
    // appropriate for a QWAC with the given QC types.
    std::vector<bssl::der::Input> qwac_qc_types;

    // Value to use for leaf's basicConstraints isCA field
    bool leaf_is_ca = false;

    // A list of DNS names to include in the leaf subjectAltName extension.
    std::vector<std::string> dns_names;

    // A list of DNS names to include in the root subjectAltName extension. Only
    // used if root = RootType::kUniqueRoot
    std::vector<std::string> root_dns_names;

    // A list of IP addresses to include in the leaf subjectAltName extension.
    std::vector<net::IPAddress> ip_addresses;

    // A list of key usages to include in the leaf keyUsage extension.
    std::vector<bssl::KeyUsageBit> key_usages;

    // Generate embedded SCTList in the certificate for the specified logs.
    std::vector<CertBuilder::SctConfig> embedded_scts;

    // If non-empty, raw bytes to use as the leaf subject. If empty, a random
    // valid subject will be generated.
    // (This can be used for testing behavior with invalid or weird encodings,
    // if we need tests to set specific subjects for more normal cases, we
    // should consider adding a more ergonomic API for that.)
    std::vector<uint8_t> subject_tlv;
  };

  using UpgradeResultOrHttpResponse =
      base::expected<UpgradeResult, std::unique_ptr<HttpResponse>>;
  using HandleUpgradeRequestCallback =
      base::RepeatingCallback<UpgradeResultOrHttpResponse(
          const HttpRequest& request,
          HttpConnection* connection)>;

  using HandleRequestCallback =
      base::RepeatingCallback<std::unique_ptr<HttpResponse>(
          const HttpRequest& request)>;

  using MonitorRequestCallback =
      base::RepeatingCallback<void(const HttpRequest& request)>;

  // Creates a http test server. StartAndReturnHandle() must be called to start
  // the server.
  // |type| indicates the protocol type of the server (HTTP/HTTPS).
  //
  //  When a TYPE_HTTPS server is created, EmbeddedTestServer will call
  // EmbeddedTestServer::RegisterTestCerts(), so that when the default
  // CertVerifiers are run in-process, they will recognize the test server's
  // certs. However, if the test server is running in a different process from
  // the CertVerifiers, EmbeddedTestServer::RegisterTestCerts() must be called
  // in any process where CertVerifiers are expected to accept the
  // EmbeddedTestServer's certs.
  EmbeddedTestServer();
  explicit EmbeddedTestServer(
      Type type,
      HttpConnection::Protocol protocol = HttpConnection::Protocol::kHttp1);
  ~EmbeddedTestServer();

  //  Send a request to the server to be handled. If a response is created,
  //  SendResponseBytes() should be called on the provided HttpConnection.
  void HandleRequest(base::WeakPtr<HttpResponseDelegate> delegate,
                     std::unique_ptr<HttpRequest> request,
                     const StreamSocket* socket);

  // Notify the server that a connection is no longer usable and is safe to
  // destroy. For H/1 connections, this means a single request/response
  // interaction, as keep-alive connections are not supported. If the
  // connection listener is present and the socket is still connected, the
  // listener will be notified.
  void RemoveConnection(
      HttpConnection* connection,
      EmbeddedTestServerConnectionListener* listener = nullptr);

  // Registers the EmbeddedTestServer's certs for the current process. See
  // constructor documentation for more information.
  [[nodiscard]] static ScopedTestRoot RegisterTestCerts();

  // Sets a connection listener, that would be notified when various connection
  // events happen. May only be called before the server is started. Caller
  // maintains ownership of the listener.
  void SetConnectionListener(EmbeddedTestServerConnectionListener* listener);

  // Initializes and waits until the server is ready to accept requests.
  // This is the equivalent of calling InitializeAndListen() followed by
  // StartAcceptingConnectionsAndReturnHandle().
  // Returns a "handle" which will ShutdownAndWaitUntilComplete() when
  // destroyed, or null if the listening socket could not be created.
  [[nodiscard]] EmbeddedTestServerHandle StartAndReturnHandle(int port = 0);

  // Equivalent of StartAndReturnHandle(), but requires manual Shutdown() by
  // the caller.
  [[nodiscard]] bool Start(int port = 0,
                           std::string_view address = "127.0.0.1");

  // Starts listening for incoming connections but will not yet accept them.
  // Returns whether a listening socket has been successfully created.
  [[nodiscard]] bool InitializeAndListen(
      int port = 0,
      std::string_view address = "127.0.0.1");

  // Starts the Accept IO Thread and begins accepting connections.
  [[nodiscard]] EmbeddedTestServerHandle
  StartAcceptingConnectionsAndReturnHandle();

  // Equivalent of StartAcceptingConnectionsAndReturnHandle(), but requires
  // manual Shutdown() by the caller.
  void StartAcceptingConnections();

  // Shuts down the http server and waits until the shutdown is complete.
  // Prefer to use the Start*AndReturnHandle() APIs to manage shutdown, if
  // possible.
  [[nodiscard]] bool ShutdownAndWaitUntilComplete();

  // Checks if the server has started listening for incoming connections.
  bool Started() const { return listen_socket_.get() != nullptr; }

  // Checks if the server has started running the message loop.
  bool StartedAcceptingConnection() const {
    return io_thread_.get() != nullptr;
  }

  static base::FilePath GetRootCertPemPath();

  HostPortPair host_port_pair() const {
    return HostPortPair::FromURL(base_url_);
  }

  // Returns the base URL to the server, which looks like
  // http://127.0.0.1:<port>/, where <port> is the actual port number used by
  // the server.
  const GURL& base_url() const { return base_url_; }

  // Returns a URL to the server based on the given relative URL, which
  // should start with '/'. For example: GetURL("/path?query=foo") =>
  // http://127.0.0.1:<port>/path?query=foo.
  GURL GetURL(std::string_view relative_url) const;

  // Similar to the above method with the difference that it uses the supplied
  // |hostname| for the URL instead of 127.0.0.1. The hostname should be
  // resolved to 127.0.0.1.
  GURL GetURL(std::string_view hostname, std::string_view relative_url) const;

  // Convenience function equivalent to calling url::Origin::Create(base_url()).
  // Will use the GetURL() variant that takes a hostname as the base URL, if
  // `hostname` is non-null.
  url::Origin GetOrigin(
      const std::optional<std::string>& hostname = std::nullopt) const;

  // Returns the address list needed to connect to the server.
  [[nodiscard]] bool GetAddressList(AddressList* address_list) const;

  // Returns the IP Address to connect to the server as a string.
  std::string GetIPLiteralString() const;

  // Returns the port number used by the server.
  uint16_t port() const { return port_; }

  // SetSSLConfig sets the SSL configuration for the server. It is invalid to
  // call after the server is started. If called multiple times, the last call
  // will have effect.
  void SetSSLConfig(ServerCertificate cert, const SSLServerConfig& ssl_config);
  void SetSSLConfig(ServerCertificate cert);
  void SetSSLConfig(const ServerCertificateConfig& cert_config,
                    const SSLServerConfig& ssl_config);
  void SetSSLConfig(const ServerCertificateConfig& cert_config);

  // TODO(mattm): make this [[nodiscard]]
  bool ResetSSLConfig(ServerCertificate cert,
                      const SSLServerConfig& ssl_config);

  // Configures the test server to generate a certificate that covers the
  // specified hostnames. This implicitly also includes 127.0.0.1 in the
  // certificate. It is invalid to call after the server is started. If called
  // multiple times, the last call will have effect.
  // Convenience method for configuring an HTTPS test server when a test needs
  // to support a set of hostnames over HTTPS, rather than explicitly setting
  /// up a full config using SetSSLConfig().
  void SetCertHostnames(std::vector<std::string> hostnames);

  // Returns the certificate that the server is using.
  // If using a generated ServerCertificate type, this must not be called before
  // InitializeAndListen() has been called.
  scoped_refptr<X509Certificate> GetCertificate();

  // Returns any generated intermediates that the server may be using. May
  // return null if no intermediate is generated.  Must not be called before
  // InitializeAndListen().
  scoped_refptr<X509Certificate> GetGeneratedIntermediate();

  // Returns the root certificate that issued the certificate the server is
  // using.  Must not be called before InitializeAndListen().
  scoped_refptr<X509Certificate> GetRoot();

  // Registers request handler which serves files from |directory|.
  // For instance, a request to "/foo.html" is served by "foo.html" under
  // |directory|. Files under sub directories are also handled in the same way
  // (i.e. "/foo/bar.html" is served by "foo/bar.html" under |directory|).
  // TODO(svaldez): Merge ServeFilesFromDirectory and
  // ServeFilesFromSourceDirectory.
  void ServeFilesFromDirectory(const base::FilePath& directory);

  // Serves files relative to DIR_SRC_TEST_DATA_ROOT.
  void ServeFilesFromSourceDirectory(std::string_view relative);
  void ServeFilesFromSourceDirectory(const base::FilePath& relative);

  // Registers the default handlers and serve additional files from the
  // |directory| directory, relative to DIR_SRC_TEST_DATA_ROOT.
  void AddDefaultHandlers(const base::FilePath& directory);

  // Returns the directory that files will be served from if |relative| is
  // passed to ServeFilesFromSourceDirectory().
  static base::FilePath GetFullPathFromSourceDirectory(
      const base::FilePath& relative);

  // Adds all default handlers except, without serving additional files from any
  // directory.
  void AddDefaultHandlers();

  // Registers an Auth handler for validating credentials in HTTP requests.
  // The handler will check the Authorization header and compare the provided
  // credentials to the expected values. If credentials are valid, the request
  // processing will proceed; otherwise, the handler will respond with a 401
  // Unauthorized. Note that:
  // 1. All handlers must be registered before the server is started.
  // 2. The server should be shutdown before any variables referred to by
  //    |callback| (e.g., via base::Unretained(&local)) are deleted. Using the
  //    Start*WithHandle() API variants is recommended for proper shutdown
  //    handling.
  void RegisterAuthHandler(const HandleRequestCallback& callback);

  // Makes the server act as an HTTP/HTTPS CONNECT proxy. Must be invoked before
  // the server is fully started. Only supports HTTP/1.x. All CONNECT requests
  // go to `dest_port` on localhost, regardless of what destination is actually
  // provided. `expected_dest`, if provided, is the expected destination of all
  // requests. CONNECT requests to other destinations will then result in test
  // failures.
  //
  // Must be called before the EmbeddedTestServer starts accepting connections.
  void EnableConnectProxy(uint16_t dest_port,
                          std::optional<HostPortPair> expected_dest);

  // Adds a handler callback to process WebSocket upgrade requests.
  // |callback| will be invoked on the server's IO thread when a request
  // attempts to upgrade to a WebSocket connection. Note that:
  // 1. All upgrade request handlers must be registered before the server is
  //    Start()ed.
  // 2. This method is not supported for HTTP/2 connections.
  // 3. The server should be Shutdown() before any variables referred to by
  //    |callback| (e.g., via base::Unretained(&local)) are deleted. Using the
  //    Start*WithHandle() API variants is recommended for this reason.
  void RegisterUpgradeRequestHandler(
      const HandleUpgradeRequestCallback& callback);

  // Adds a request handler that can perform any general-purpose processing.
  // |callback| will be invoked on the server's IO thread. Note that:
  // 1. All handlers must be registered before the server is Start()ed.
  // 2. The server should be Shutdown() before any variables referred to by
  //    |callback| (e.g. via base::Unretained(&local)) are deleted. Using the
  //    Start*WithHandle() API variants is recommended for this reason.
  void RegisterRequestHandler(const HandleRequestCallback& callback);

  // Adds a request monitor that will be called before any handlers. Monitors
  // can be used to observe requests, but not to respond to them.
  // See RegisterRequestHandler() for notes on usage.
  void RegisterRequestMonitor(const MonitorRequestCallback& callback);

  // Adds a default request handler, to be called if no user-specified handler
  // handles the request.
  // See RegisterRequestHandler() for notes on usage.
  void RegisterDefaultHandler(const HandleRequestCallback& callback);

  bool FlushAllSocketsAndConnectionsOnUIThread();
  void FlushAllSocketsAndConnections();

  // Adds an origin/accept_ch pair to add to an ACCEPT_CH HTTP/2 frame. If any
  // pairs have been added, the ALPS TLS extension will be populated, which
  // will act as though an ACCEPT_CH frame was sent by the server before the
  // first frame is sent by a client. For more information, see
  // draft-vvv-tls-alps-01 and section 4.1 (HTTP/2 ACCEPT_CH Frame) of
  // draft-davidben-http-client-hint-reliability
  //
  // Only valid before Start() or ResetSSLServerConfig(). Only valid when
  // constructed with PROTOCOL_HTTP2. For the default host, use an empty
  // string.
  void SetAlpsAcceptCH(std::string hostname, std::string accept_ch);

  // Registers a shutdown closure for WebSocket connections to safely
  // disconnect. This method should only be called from handler callbacks and
  // must be invoked on the server's callback thread.
  //
  // The closure registered here will be executed on the callback thread before
  // the server completes its shutdown. This ensures that any resources specific
  // to the callback thread are cleaned up safely.
  base::CallbackListSubscription RegisterShutdownClosure(
      base::OnceClosure closure);

 private:
  // Returns the file name of the certificate the server is using. The test
  // certificates can be found in net/data/ssl/certificates/.
  std::string GetCertificateName() const;

  // Shuts down the server.
  void ShutdownOnIOThread();

  // Sets the SSL configuration for the server. It is invalid for |cert_config|
  // to be non-null if |cert| is not CERT_AUTO.
  void SetSSLConfigInternal(ServerCertificate cert,
                            const ServerCertificateConfig* cert_config,
                            const SSLServerConfig& ssl_config);

  // Resets the SSLServerConfig on the IO thread.
  bool ResetSSLConfigOnIOThread(ServerCertificate cert,
                                const SSLServerConfig& ssl_config);

  HttpConnection* GetConnectionForSocket(const StreamSocket* socket);

  // Upgrade the TCP connection to one over SSL.
  std::unique_ptr<SSLServerSocket> DoSSLUpgrade(
      std::unique_ptr<StreamSocket> connection);
  // Handles async callback when the SSL handshake has been completed.
  void OnHandshakeDone(HttpConnection* http_connection, int rv);
  // Begins new connection if handshake resulted in a connection
  void HandleHandshakeResults();

  // Begins accepting new client connections.
  void DoAcceptLoop();
  // Handles async callback when there is a new client socket. |rv| is the
  // return value of the socket Accept.
  void OnAcceptCompleted(int rv);
  // Adds the new |socket| to the list of clients and begins the reading
  // data.
  void HandleAcceptResult(std::unique_ptr<StreamSocket> socket_ptr);

  // Create a connection with a socket, add it to the map, and return pointers
  // to both.
  HttpConnection* AddConnection(std::unique_ptr<StreamSocket> socket_ptr);

  // Handles async callback when new data has been read from the |connection|.
  void OnReadCompleted(HttpConnection* connection, int rv);

  // Returns true if the current |cert_| configuration uses a static
  // pre-generated cert loaded from the filesystem.
  bool UsingStaticCert() const;

  // Reads server certificate and private key from file. May only be called if
  // |cert_| refers to a file-based cert & key.
  [[nodiscard]] bool InitializeCertAndKeyFromFile();

  // Generate server certificate and private key. May only be called if |cert_|
  // refers to a generated cert & key.
  [[nodiscard]] bool GenerateCertAndKey();

  // Initializes the SSLServerContext so that SSLServerSocket connections may
  // share the same cache
  [[nodiscard]] bool InitializeSSLServerContext();

  // Posts a task to the |io_thread_| and waits for a reply.
  [[nodiscard]] bool PostTaskToIOThreadAndWait(base::OnceClosure closure);

  // Posts a task that returns a true/false success/fail value to the
  // |io_thread_| and waits for a reply.
  [[nodiscard]] bool PostTaskToIOThreadAndWaitWithResult(
      base::OnceCallback<bool()> task);

  const bool is_using_ssl_;
  const HttpConnection::Protocol protocol_;

  std::unique_ptr<base::Thread> io_thread_;

  std::unique_ptr<TCPServerSocket> listen_socket_;
  std::unique_ptr<StreamSocket> accepted_socket_;

  raw_ptr<EmbeddedTestServerConnectionListener, DanglingUntriaged>
      connection_listener_ = nullptr;
  uint16_t port_ = 0;
  GURL base_url_;
  IPEndPoint local_endpoint_;

  std::map<const StreamSocket*, std::unique_ptr<HttpConnection>> connections_;

  // Optional Auth handler to validate HTTP requests. If set, this handler
  // is checked first; requests without valid credentials return an error
  // immediately without reaching other handlers.
  HandleRequestCallback auth_handler_;

  // Optional handle to make the test server work as an HTTP/1 proxy. Created on
  // main thread, but destroyed on `io_thread_`, as it may own sockets for
  // tunnels.
  std::unique_ptr<HttpConnectProxyHandler> http_connect_proxy_handler_;

  // Vector of registered and default request handlers and monitors.
  std::vector<HandleUpgradeRequestCallback> upgrade_request_handlers_;
  std::vector<HandleRequestCallback> request_handlers_;
  std::vector<MonitorRequestCallback> request_monitors_;
  std::vector<HandleRequestCallback> default_request_handlers_;

  base::ThreadChecker thread_checker_;

  ScopedTestRoot scoped_test_root_;
  net::SSLServerConfig ssl_config_;
  ServerCertificate cert_ = CERT_OK;
  ServerCertificateConfig cert_config_;
  // If non-empty, will be used instead of `x509_cert_`.
  std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> cert_chain_;
  scoped_refptr<X509Certificate> x509_cert_;
  // May be null if no intermediate is generated.
  scoped_refptr<X509Certificate> intermediate_;
  scoped_refptr<X509Certificate> root_;
  bssl::UniquePtr<EVP_PKEY> private_key_;
  base::flat_map<std::string, std::string> alps_accept_ch_;
  std::unique_ptr<SSLServerContext> context_;

  // HTTP server that handles AIA URLs that are embedded in this test server's
  // certificate when the server certificate is one of the CERT_AUTO variants.
  std::unique_ptr<EmbeddedTestServer> aia_http_server_;

  // Closure list to manage shutdown closures for WebSocket connections.
  base::OnceClosureList shutdown_closures_;

  base::WeakPtrFactory<EmbeddedTestServer> weak_factory_{this};
};

}  // namespace test_server

// TODO(svaldez): Refactor EmbeddedTestServer to be in the net namespace.
using test_server::EmbeddedTestServer;

}  // namespace net

#endif  // NET_TEST_EMBEDDED_TEST_SERVER_EMBEDDED_TEST_SERVER_H_