proxygen
HTTPServerTest.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015-present, Facebook, Inc.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * LICENSE file in the root directory of this source tree. An additional grant
7  * of patent rights can be found in the PATENTS file in the same directory.
8  *
9  */
11 #include <boost/thread.hpp>
12 #include <folly/FileUtil.h>
25 
26 using namespace folly;
27 using namespace folly::ssl;
28 using namespace proxygen;
29 using namespace testing;
30 using namespace CurlService;
31 
35 using folly::SSLContext;
36 using folly::SSLContext;
38 
39 namespace {
40 
41 const std::string kTestDir = getContainingDirectory(__FILE__).str();
42 
43 }
44 
45 class ServerThread {
46  private:
47  boost::barrier barrier_{2};
48  std::thread t_;
49  HTTPServer* server_{nullptr};
50 
51  public:
52 
53  explicit ServerThread(HTTPServer* server) : server_(server) {}
55  if (server_) {
56  server_->stop();
57  }
58  t_.join();
59  }
60 
61  bool start() {
62  bool throws = false;
63  t_ = std::thread([&]() {
64  server_->start([&]() { barrier_.wait(); },
65  [&](std::exception_ptr /*ex*/) {
66  throws = true;
67  server_ = nullptr;
68  barrier_.wait();
69  });
70  });
71  barrier_.wait();
72  return !throws;
73  }
74 };
75 
76 TEST(MultiBind, HandlesListenFailures) {
77  SocketAddress addr("127.0.0.1", 0);
78 
79  auto evb = EventBaseManager::get()->getEventBase();
81  socket->bind(addr);
82 
83  // Get the ephemeral port
84  socket->getAddress(&addr);
85  int port = addr.getPort();
86 
87  std::vector<HTTPServer::IPConfig> ips = {
88  {
89  folly::SocketAddress("127.0.0.1", port),
90  HTTPServer::Protocol::HTTP
91  }
92  };
93 
94  HTTPServerOptions options;
95  options.threads = 4;
96 
97  auto server = std::make_unique<HTTPServer>(std::move(options));
98 
99  // We have to bind both the sockets before listening on either
100  server->bind(ips);
101 
102  // On kernel 2.6 trying to listen on a FD that another socket
103  // has bound to fails. While in kernel 3.2 only when one socket tries
104  // to listen on a FD that another socket is listening on fails.
105  try {
106  socket->listen(1024);
107  } catch (const std::exception& ex) {
108  return;
109  }
110 
111  ServerThread st(server.get());
112  EXPECT_FALSE(st.start());
113 }
114 
115 TEST(HttpServerStartStop, TestRepeatStopCalls) {
116  HTTPServerOptions options;
117  auto server = std::make_unique<HTTPServer>(std::move(options));
118  auto st = std::make_unique<ServerThread>(server.get());
119  EXPECT_TRUE(st->start());
120 
121  server->stop();
122  // Calling stop again should be benign.
123  server->stop();
124 }
125 
126 // Make an SSL connection to the server
128  public:
129  explicit Cb(folly::AsyncSSLSocket* sock) : sock_(sock) {}
130  void connectSuccess() noexcept override {
131  success = true;
132  reusedSession = sock_->getSSLSessionReused();
133  session.reset(sock_->getSSLSession());
134  if (sock_->getPeerCert()) {
135  // keeps this alive until Cb is destroyed, even if sock is closed
136  peerCert_ = sock_->getPeerCert();
137  }
138  sock_->close();
139  }
140 
142  success = false;
143  }
144 
145  const X509* getPeerCert() { return peerCert_.get(); }
146 
147  bool success{false};
148  bool reusedSession{false};
151  folly::ssl::X509UniquePtr peerCert_{nullptr};
152 };
153 
154 TEST(SSL, SSLTest) {
156  folly::SocketAddress("127.0.0.1", 0),
157  HTTPServer::Protocol::HTTP};
159  sslCfg.isDefault = true;
160  sslCfg.setCertificate(
161  kTestDir + "certs/test_cert1.pem",
162  kTestDir + "certs/test_key1.pem",
163  "");
164  cfg.sslConfigs.push_back(sslCfg);
165 
166  HTTPServerOptions options;
167  options.threads = 4;
168 
169  auto server = std::make_unique<HTTPServer>(std::move(options));
170 
171  std::vector<HTTPServer::IPConfig> ips{cfg};
172  server->bind(ips);
173 
174  ServerThread st(server.get());
175  EXPECT_TRUE(st.start());
176 
177  folly::EventBase evb;
178  auto ctx = std::make_shared<SSLContext>();
180  Cb cb(sock.get());
181  sock->connect(&cb, server->addresses().front().address, 1000);
182  evb.loop();
183  EXPECT_TRUE(cb.success);
184 }
185 
190  public:
191  class DummyFilter : public Filter {
192  public:
193  explicit DummyFilter(RequestHandler* upstream) : Filter(upstream) {}
194  };
195 
197  return new DummyFilter(h);
198  }
199 
201  void onServerStop() noexcept override {}
202 };
203 
205  public:
206  class TestHandler : public RequestHandler {
207  void onRequest(std::unique_ptr<HTTPMessage>) noexcept override {
208  }
209  void onBody(std::unique_ptr<folly::IOBuf>) noexcept override {}
211  }
212 
213  void onEOM() noexcept override {
214  std::string certHeader("");
215  auto txn = CHECK_NOTNULL(downstream_->getTransaction());
216  auto& transport = txn->getTransport();
217  if (auto cert = transport.getUnderlyingTransport()->getPeerCert()) {
218  certHeader = OpenSSLCertUtils::getCommonName(*cert).value_or("");
219  }
220  ResponseBuilder(downstream_)
221  .status(200, "OK")
222  .header("X-Client-CN", certHeader)
223  .body(IOBuf::copyBuffer("hello"))
224  .sendWithEOM();
225  }
226 
227  void requestComplete() noexcept override { delete this; }
228 
229  void onError(ProxygenError) noexcept override { delete this; }
230  };
231 
233  return new TestHandler();
234  }
235 
237  void onServerStop() noexcept override {}
238 };
239 
240 std::pair<std::unique_ptr<HTTPServer>, std::unique_ptr<ServerThread>>
241 setupServer(bool allowInsecureConnectionsOnSecureServer = false,
243  HTTPServer::IPConfig cfg{folly::SocketAddress("127.0.0.1", 0),
244  HTTPServer::Protocol::HTTP};
246  sslCfg.isDefault = true;
247  sslCfg.setCertificate(
248  kTestDir + "certs/test_cert1.pem", kTestDir + "certs/test_key1.pem", "");
249  cfg.sslConfigs.push_back(sslCfg);
250  cfg.allowInsecureConnectionsOnSecureServer =
251  allowInsecureConnectionsOnSecureServer;
252  cfg.ticketSeeds = seeds;
253 
254  HTTPServerOptions options;
255  options.threads = 4;
256  options.handlerFactories =
258 
259  auto server = std::make_unique<HTTPServer>(std::move(options));
260 
261  std::vector<HTTPServer::IPConfig> ips{cfg};
262  server->bind(ips);
263 
264  auto st = std::make_unique<ServerThread>(server.get());
265  EXPECT_TRUE(st->start());
266  return std::make_pair(std::move(server), std::move(st));
267 }
268 
269 TEST(SSL, TestAllowInsecureOnSecureServer) {
270  std::unique_ptr<HTTPServer> server;
271  std::unique_ptr<ServerThread> st;
272  std::tie(server, st) = setupServer(true);
273 
274  folly::EventBase evb;
275  URL url(folly::to<std::string>(
276  "http://localhost:", server->addresses().front().address.getPort()));
277  HTTPHeaders headers;
278  CurlClient curl(&evb, HTTPMethod::GET, url, nullptr, headers, "");
279  curl.setFlowControlSettings(64 * 1024);
280  curl.setLogging(false);
282  &evb,
283  std::chrono::milliseconds(HHWheelTimer::DEFAULT_TICK_INTERVAL),
285  std::chrono::milliseconds(1000))};
286  HTTPConnector connector(&curl, timer.get());
287  connector.connect(&evb,
288  server->addresses().front().address,
289  std::chrono::milliseconds(1000));
290  evb.loop();
291  auto response = curl.getResponse();
292  EXPECT_EQ(200, response->getStatusCode());
293 }
294 
295 TEST(SSL, DisallowInsecureOnSecureServer) {
296  std::unique_ptr<HTTPServer> server;
297  std::unique_ptr<ServerThread> st;
298  std::tie(server, st) = setupServer(false);
299 
300  folly::EventBase evb;
301  URL url(folly::to<std::string>(
302  "http://localhost:", server->addresses().front().address.getPort()));
303  HTTPHeaders headers;
304  CurlClient curl(&evb, HTTPMethod::GET, url, nullptr, headers, "");
305  curl.setFlowControlSettings(64 * 1024);
306  curl.setLogging(false);
308  &evb,
309  std::chrono::milliseconds(HHWheelTimer::DEFAULT_TICK_INTERVAL),
311  std::chrono::milliseconds(1000))};
312  HTTPConnector connector(&curl, timer.get());
313  connector.connect(&evb,
314  server->addresses().front().address,
315  std::chrono::milliseconds(1000));
316  evb.loop();
317  auto response = curl.getResponse();
318  EXPECT_EQ(nullptr, response);
319 }
320 
321 TEST(SSL, TestResumptionWithTickets) {
322  std::unique_ptr<HTTPServer> server;
323  std::unique_ptr<ServerThread> st;
325  seeds.currentSeeds.push_back(hexlify("hello"));
326  std::tie(server, st) = setupServer(false, seeds);
327 
328  folly::EventBase evb;
329  auto ctx = std::make_shared<SSLContext>();
331  Cb cb(sock.get());
332  sock->connect(&cb, server->addresses().front().address, 1000);
333  evb.loop();
334  ASSERT_TRUE(cb.success);
335  ASSERT_NE(nullptr, cb.session.get());
336  ASSERT_FALSE(cb.reusedSession);
337 
339  sock2->setSSLSession(cb.session.get());
340  Cb cb2(sock2.get());
341  sock2->connect(&cb2, server->addresses().front().address, 1000);
342  evb.loop();
343  ASSERT_TRUE(cb2.success);
344  ASSERT_NE(nullptr, cb2.session.get());
345  ASSERT_TRUE(cb2.reusedSession);
346 }
347 
348 TEST(SSL, TestResumptionAfterUpdateFails) {
349  std::unique_ptr<HTTPServer> server;
350  std::unique_ptr<ServerThread> st;
352  seeds.currentSeeds.push_back(hexlify("hello"));
353  std::tie(server, st) = setupServer(false, seeds);
354 
355  folly::EventBase evb;
356  auto ctx = std::make_shared<SSLContext>();
358  Cb cb(sock.get());
359  sock->connect(&cb, server->addresses().front().address, 1000);
360  evb.loop();
361  ASSERT_TRUE(cb.success);
362  ASSERT_NE(nullptr, cb.session.get());
363  ASSERT_FALSE(cb.reusedSession);
364 
365  wangle::TLSTicketKeySeeds newSeeds;
366  newSeeds.currentSeeds.push_back(hexlify("goodbyte"));
367  server->updateTicketSeeds(newSeeds);
368 
370  sock2->setSSLSession(cb.session.get());
371  Cb cb2(sock2.get());
372  sock2->connect(&cb2, server->addresses().front().address, 1000);
373  evb.loop();
374  ASSERT_TRUE(cb2.success);
375  ASSERT_NE(nullptr, cb2.session.get());
376  ASSERT_FALSE(cb2.reusedSession);
377 
379  sock3->setSSLSession(cb2.session.get());
380  Cb cb3(sock3.get());
381  sock3->connect(&cb3, server->addresses().front().address, 1000);
382  evb.loop();
383  ASSERT_TRUE(cb3.success);
384  ASSERT_NE(nullptr, cb3.session.get());
385  ASSERT_TRUE(cb3.reusedSession);
386 }
387 
388 TEST(SSL, TestUpdateTLSCredentials) {
389  // Set up a temporary file with credentials that we will update
391  auto copyCreds = [path = credFile.path()](const std::string& certFile,
392  const std::string& keyFile) {
393  std::string certData, keyData;
394  folly::readFile(certFile.c_str(), certData);
395  folly::writeFile(certData, path.c_str(), O_WRONLY | O_CREAT | O_TRUNC);
396  folly::writeFile(std::string("\n"), path.c_str(), O_WRONLY | O_APPEND);
397  folly::readFile(keyFile.c_str(), keyData);
398  folly::writeFile(keyData, path.c_str(), O_WRONLY | O_APPEND);
399  };
400 
401  auto getCertDigest = [&](const X509* x) -> std::string {
402  unsigned int n;
403  unsigned char md[EVP_MAX_MD_SIZE];
404  const EVP_MD* dig = EVP_sha256();
405 
406  if (!X509_digest(x, dig, md, &n)) {
407  throw std::runtime_error("Cannot calculate digest");
408  }
409  return std::string((const char*)md, n);
410  };
411 
412  HTTPServer::IPConfig cfg{folly::SocketAddress("127.0.0.1", 0),
413  HTTPServer::Protocol::HTTP};
415  sslCfg.isDefault = true;
416  copyCreds(kTestDir + "certs/test_cert1.pem",
417  kTestDir + "certs/test_key1.pem");
418  sslCfg.setCertificate(credFile.path().string(), credFile.path().string(), "");
419  cfg.sslConfigs.push_back(sslCfg);
420 
421  HTTPServer::IPConfig insecureCfg{folly::SocketAddress("127.0.0.1", 0),
422  HTTPServer::Protocol::HTTP};
423 
424  HTTPServerOptions options;
425  options.threads = 4;
426 
427  auto server = std::make_unique<HTTPServer>(std::move(options));
428 
429  std::vector<HTTPServer::IPConfig> ips{cfg, insecureCfg};
430  server->bind(ips);
431 
432  ServerThread st(server.get());
433  EXPECT_TRUE(st.start());
434 
435  // First connection which should return old cert
436  folly::EventBase evb;
437  auto ctx = std::make_shared<SSLContext>();
438  std::string certDigest1, certDigest2;
439 
440  // Connect and store digest of server cert
441  auto connectAndFetchServerCert = [&]() -> std::string {
443  Cb cb(sock.get());
444  sock->connect(&cb, server->addresses().front().address, 1000);
445  evb.loop();
446  EXPECT_TRUE(cb.success);
447 
448  auto x509 = cb.getPeerCert();
449  EXPECT_NE(x509, nullptr);
450  return getCertDigest(x509);
451  };
452 
453  // Original cert
454  auto cert1 = connectAndFetchServerCert();
455  EXPECT_EQ(cert1.length(), SHA256_DIGEST_LENGTH);
456 
457  // Update cert/key
458  copyCreds(kTestDir + "certs/test_cert2.pem",
459  kTestDir + "certs/test_key2.pem");
460  server->updateTLSCredentials();
461  evb.loop();
462 
463  // Should get new cert
464  auto cert2 = connectAndFetchServerCert();
465  EXPECT_EQ(cert2.length(), SHA256_DIGEST_LENGTH);
466  EXPECT_NE(cert1, cert2);
467 }
468 
469 TEST(GetListenSocket, TestNoBootstrap) {
470  HTTPServerOptions options;
471  auto server = std::make_unique<HTTPServer>(std::move(options));
472  auto st = std::make_unique<ServerThread>(server.get());
473  EXPECT_TRUE(st->start());
474 
475  auto socketFd = server->getListenSocket();
476  ASSERT_EQ(-1, socketFd);
477 }
478 
479 TEST(GetListenSocket, TestBootstrapWithNoBinding) {
480  std::unique_ptr<HTTPServer> server;
481  std::unique_ptr<ServerThread> st;
483  seeds.currentSeeds.push_back(hexlify("hello"));
484  std::tie(server, st) = setupServer(false, seeds);
485 
486  // Stop listening on socket
487  server->stopListening();
488 
489  auto socketFd = server->getListenSocket();
490  ASSERT_EQ(-1, socketFd);
491 }
492 
493 TEST(GetListenSocket, TestBootstrapWithBinding) {
494  std::unique_ptr<HTTPServer> server;
495  std::unique_ptr<ServerThread> st;
497  seeds.currentSeeds.push_back(hexlify("hello"));
498  std::tie(server, st) = setupServer(false, seeds);
499 
500  auto socketFd = server->getListenSocket();
501  ASSERT_NE(-1, socketFd);
502 }
503 
504 TEST(UseExistingSocket, TestWithExistingAsyncServerSocket) {
506  serverSocket->bind(0);
507 
508  HTTPServer::IPConfig cfg{folly::SocketAddress("127.0.0.1", 0),
509  HTTPServer::Protocol::HTTP};
510  std::vector<HTTPServer::IPConfig> ips{cfg};
511 
512  HTTPServerOptions options;
513  options.handlerFactories =
515  // Use the existing AsyncServerSocket for binding
516  auto existingFd = serverSocket->getSocket();
517  options.useExistingSocket(std::move(serverSocket));
518 
519  auto server = std::make_unique<HTTPServer>(std::move(options));
520  auto st = std::make_unique<ServerThread>(server.get());
521  server->bind(ips);
522 
523  EXPECT_TRUE(st->start());
524 
525  auto socketFd = server->getListenSocket();
526  ASSERT_EQ(existingFd, socketFd);
527 }
528 
529 TEST(UseExistingSocket, TestWithSocketFd) {
531  serverSocket->bind(0);
532 
533  HTTPServer::IPConfig cfg{folly::SocketAddress("127.0.0.1", 0),
534  HTTPServer::Protocol::HTTP};
535  HTTPServerOptions options;
536  options.handlerFactories =
538  // Use the socket fd from the existing AsyncServerSocket for binding
539  auto existingFd = serverSocket->getSocket();
540  options.useExistingSocket(existingFd);
541 
542  auto server = std::make_unique<HTTPServer>(std::move(options));
543  auto st = std::make_unique<ServerThread>(server.get());
544  std::vector<HTTPServer::IPConfig> ips{cfg};
545  server->bind(ips);
546 
547 
548  EXPECT_TRUE(st->start());
549 
550  auto socketFd = server->getListenSocket();
551  ASSERT_EQ(existingFd, socketFd);
552 }
553 
554 TEST(UseExistingSocket, TestWithMultipleSocketFds) {
556  serverSocket->bind(0);
557  try {
558  serverSocket->bind(1024);
559  } catch (const std::exception& ex) {
560  // This is fine because we are trying to bind to multiple ports
561  }
562 
563  HTTPServer::IPConfig cfg{folly::SocketAddress("127.0.0.1", 0),
564  HTTPServer::Protocol::HTTP};
565  HTTPServerOptions options;
566  options.handlerFactories =
568  // Use the socket fd from the existing AsyncServerSocket for binding
569  auto existingFds = serverSocket->getSockets();
570  options.useExistingSockets(existingFds);
571 
572  auto server = std::make_unique<HTTPServer>(std::move(options));
573  auto st = std::make_unique<ServerThread>(server.get());
574  std::vector<HTTPServer::IPConfig> ips{cfg};
575  server->bind(ips);
576 
577 
578  EXPECT_TRUE(st->start());
579 
580  auto socketFd = server->getListenSocket();
581  ASSERT_EQ(existingFds[0], socketFd);
582 }
583 
585  public:
586  void SetUp() override {
587  timer_.reset(new HHWheelTimer(
588  &evb_,
589  std::chrono::milliseconds(HHWheelTimer::DEFAULT_TICK_INTERVAL),
591  std::chrono::milliseconds(1000)));
592  }
593 
594  protected:
595  std::unique_ptr<ScopedHTTPServer>
597  auto opts = createDefaultOpts();
598  auto res = ScopedHTTPServer::start(cfg_, std::move(opts));
599  auto addresses = res->getAddresses();
600  address_ = addresses.front().address;
601  return res;
602  }
603 
604  std::unique_ptr<CurlClient> connectSSL(const std::string& caFile = "",
605  const std::string& certFile = "",
606  const std::string& keyFile = "") {
607  URL url(folly::to<std::string>("https://localhost:", address_.getPort()));
608  HTTPHeaders headers;
609  auto client = std::make_unique<CurlClient>(
610  &evb_, HTTPMethod::GET, url, nullptr, headers, "");
611  client->setFlowControlSettings(64 * 1024);
612  client->setLogging(false);
613  client->initializeSsl(caFile, "http/1.1", certFile, keyFile);
614  HTTPConnector connector(client.get(), timer_.get());
615  connector.connectSSL(
616  &evb_,
617  address_,
618  client->getSSLContext(),
619  nullptr,
620  std::chrono::milliseconds(1000));
621  evb_.loop();
622  return client;
623  }
624 
625  std::unique_ptr<CurlClient> connectPlainText() {
626  URL url(
627  folly::to<std::string>("http://localhost:", address_.getPort()));
628  HTTPHeaders headers;
629  auto client = std::make_unique<CurlClient>(
630  &evb_, HTTPMethod::GET, url, nullptr, headers, "");
631  client->setFlowControlSettings(64 * 1024);
632  client->setLogging(false);
633  HTTPConnector connector(client.get(), timer_.get());
634  connector.connect(
635  &evb_,
636  address_,
637  std::chrono::milliseconds(1000));
638  evb_.loop();
639  return client;
640  }
641 
643  HTTPServerOptions res;
644  res.handlerFactories =
646  res.threads = 4;
647  return res;
648  }
649 
654  folly::SocketAddress("127.0.0.1", 0),
655  HTTPServer::Protocol::HTTP};
656 };
657 
659  auto server = createScopedServer();
660  auto client = connectPlainText();
661  auto resp = client->getResponse();
662  EXPECT_EQ(200, resp->getStatusCode());
663 }
664 
665 TEST_F(ScopedServerTest, StartStrictSSL) {
667  sslCfg.isDefault = true;
668  sslCfg.setCertificate(
669  "/path/should/not/exist",
670  "/path/should/not/exist",
671  "");
672  cfg_.sslConfigs.push_back(sslCfg);
673  EXPECT_THROW(createScopedServer(), std::exception);
674 }
675 
676 TEST_F(ScopedServerTest, StartNotStrictSSL) {
678  sslCfg.isDefault = true;
679  sslCfg.setCertificate(
680  "/path/should/not/exist",
681  "/path/should/not/exist",
682  "");
683  cfg_.strictSSL = false;
684  cfg_.sslConfigs.push_back(sslCfg);
685  auto server = createScopedServer();
686  auto client = connectPlainText();
687  auto resp = client->getResponse();
688  EXPECT_EQ(200, resp->getStatusCode());
689 }
690 
691 TEST_F(ScopedServerTest, StartSSLWithInsecure) {
693  sslCfg.isDefault = true;
694  sslCfg.setCertificate(
695  kTestDir + "certs/test_cert1.pem",
696  kTestDir + "certs/test_key1.pem",
697  "");
698  cfg_.sslConfigs.push_back(sslCfg);
699  cfg_.allowInsecureConnectionsOnSecureServer = true;
700  auto server = createScopedServer();
701  auto client = connectPlainText();
702  auto resp = client->getResponse();
703  EXPECT_EQ(200, resp->getStatusCode());
704 
705  client = connectSSL();
706  resp = client->getResponse();
707  EXPECT_EQ(200, resp->getStatusCode());
708 }
709 
711  protected:
713  HTTPServerOptions options;
714  options.threads = 4;
715  options.handlerFactories =
719  .addThen<TestHandlerFactory>()
720  .build();
721  options.newConnectionFilter =
722  [](const folly::AsyncTransportWrapper* sock,
723  const folly::SocketAddress* /* address */,
724  const std::string& /* nextProtocolName */,
725  wangle::SecureTransportType /* secureTransportType */,
726  const wangle::TransportInfo& /* tinfo */) {
727  auto cert = sock->getPeerCert();
728  if (!cert || OpenSSLCertUtils::getCommonName(*cert).value_or("") !=
729  "testuser1") {
730  throw std::runtime_error("Client cert is missing or invalid.");
731  }
732  };
733  return options;
734  }
735 };
736 
739  sslCfg.isDefault = true;
740  sslCfg.setCertificate(
741  kTestDir + "certs/test_cert1.pem", kTestDir + "certs/test_key1.pem", "");
742  sslCfg.clientCAFile = kTestDir + "certs/client_ca_cert.pem";
743  // Permissive client auth.
744  sslCfg.clientVerification = folly::SSLContext::SSLVerifyPeerEnum::VERIFY;
745  cfg_.sslConfigs.push_back(sslCfg);
746 
747  auto server = createScopedServer();
748  auto insecureClient = connectPlainText();
749  auto certlessClient = connectSSL();
750  auto certlessClient2 = connectSSL(kTestDir + "certs/ca_cert.pem");
751  auto secureClient = connectSSL(kTestDir + "certs/ca_cert.pem",
752  kTestDir + "certs/client_cert.pem",
753  kTestDir + "certs/client_key.pem");
754 
755  // The following clients fail newConnectionFilter.
756  EXPECT_EQ(nullptr, insecureClient->getResponse());
757  EXPECT_EQ(nullptr, certlessClient->getResponse());
758  EXPECT_EQ(nullptr, certlessClient2->getResponse());
759 
760  // Only secureClient passes.
761  auto response = secureClient->getResponse();
762  EXPECT_EQ(200, response->getStatusCode());
763 
764  // Check the header set by TestHandler.
765  auto headers = response->getHeaders();
766  EXPECT_EQ("testuser1", headers.getSingleOrEmpty("X-Client-CN"));
767 }
folly::EventBase evb_
Definition: InvokeTest.cpp:58
wangle::SSLSessionPtr session
void onServerStart(folly::EventBase *) noexceptoverride
RequestHandler * onRequest(RequestHandler *h, HTTPMessage *) noexceptoverride
*than *hazptr_holder h
Definition: Hazptr.h:116
std::vector< std::string > currentSeeds
bool readFile(int fd, Container &out, size_t num_bytes=std::numeric_limits< size_t >::max())
Definition: FileUtil.h:125
ResponseBuilder & status(uint16_t code, const std::string &message)
std::thread t_
EventBase * getEventBase() const
std::string str() const
Definition: Range.h:591
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
HHWheelTimer::UniquePtr timer_
#define ASSERT_EQ(val1, val2)
Definition: gtest.h:1956
std::unique_ptr< X509, X509Deleter > X509UniquePtr
void onServerStart(folly::EventBase *) noexceptoverride
void useExistingSocket(folly::AsyncServerSocket::UniquePtr socket)
void setFlowControlSettings(int32_t recvWindow)
Definition: CurlClient.cpp:108
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
const int x
RequestHandlerChain & addThen(Args &&...args)
NewConnectionFilter newConnectionFilter
uint16_t getPort() const
void onServerStop() noexceptoverride
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
ResponseBuilder & body(std::unique_ptr< folly::IOBuf > bodyIn)
static int DEFAULT_TICK_INTERVAL
Definition: HHWheelTimer.h:163
RequestHandler * onRequest(RequestHandler *, HTTPMessage *) noexceptoverride
requires E e noexcept(noexcept(s.error(std::move(e))))
stop_watch< std::chrono::milliseconds > timer_
void onServerStop() noexceptoverride
folly::SocketAddress address_
static EventBaseManager * get()
int getListenSocket() const
Definition: HTTPServer.cpp:224
std::unique_ptr< SSL_SESSION, SessionDestructor > SSLSessionPtr
Definition: SSLSession.h:32
void requestComplete() noexceptoverride
std::unique_ptr< AsyncSSLSocket, Destructor > UniquePtr
folly::SSLContext::SSLVerifyPeerEnum clientVerification
Cb(folly::AsyncSSLSocket *sock)
HTTPServerOptions createDefaultOpts() override
EventBase * evb_
void onEOM() noexceptoverride
virtual HTTPServerOptions createDefaultOpts()
void onError(ProxygenError) noexceptoverride
std::vector< std::unique_ptr< RequestHandlerFactory > > handlerFactories
std::pair< std::unique_ptr< HTTPServer >, std::unique_ptr< ServerThread > > setupServer(bool allowInsecureConnectionsOnSecureServer=false, folly::Optional< wangle::TLSTicketKeySeeds > seeds=folly::none)
std::vector< IPConfig > addresses() const
Definition: HTTPServer.h:139
void connectSuccess() noexceptoverride
ResponseBuilder & header(const std::string &headerIn, const T &value)
void useExistingSockets(const std::vector< int > &socketFds)
AsyncSocket::UniquePtr sock_
NetworkSocket socket(int af, int type, int protocol)
Definition: NetOps.cpp:412
const fs::path & path() const
Definition: TestUtil.cpp:85
std::unique_ptr< ScopedHTTPServer > createScopedServer()
std::unique_ptr< HHWheelTimer, Destructor > UniquePtr
Definition: HHWheelTimer.h:57
static Optional< std::string > getCommonName(X509 &x509)
auto start
TEST_F(AsyncSSLSocketWriteTest, write_coalescing1)
FOLLY_CPP14_CONSTEXPR Value value_or(U &&dflt) const &
Definition: Optional.h:330
void setCertificate(const std::string &certPath, const std::string &keyPath, const std::string &passwordPath)
const X509 * getPeerCert()
std::unique_ptr< AsyncServerSocket, Destructor > UniquePtr
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
void connectErr(const folly::AsyncSocketException &) noexceptoverride
void setLogging(bool enabled)
Definition: CurlClient.h:76
void onUpgrade(UpgradeProtocol) noexceptoverride
const char * string
Definition: Conv.cpp:212
void connect(folly::EventBase *eventBase, const folly::SocketAddress &connectAddr, std::chrono::milliseconds timeoutMs=std::chrono::milliseconds(0), const folly::AsyncSocket::OptionMap &socketOptions=folly::AsyncSocket::emptyOptionMap, const folly::SocketAddress &bindAddr=folly::AsyncSocket::anyAddress())
folly::StringPiece getContainingDirectory(folly::StringPiece input)
Definition: TestUtils.h:33
std::unique_ptr< CurlClient > connectPlainText()
virtual ssl::X509UniquePtr getPeerCert() const
#define EXPECT_NE(val1, val2)
Definition: gtest.h:1926
void SetUp() override
void connectSSL(folly::EventBase *eventBase, const folly::SocketAddress &connectAddr, const std::shared_ptr< folly::SSLContext > &ctx, SSL_SESSION *session=nullptr, std::chrono::milliseconds timeoutMs=std::chrono::milliseconds(0), const folly::AsyncSocket::OptionMap &socketOptions=folly::AsyncSocket::emptyOptionMap, const folly::SocketAddress &bindAddr=folly::AsyncSocket::anyAddress(), const std::string &serverName=empty_string)
std::unique_ptr< CurlClient > connectSSL(const std::string &caFile="", const std::string &certFile="", const std::string &keyFile="")
void updateTicketSeeds(wangle::TLSTicketKeySeeds seeds)
Definition: HTTPServer.cpp:262
bool writeFile(const Container &data, const char *filename, int flags=O_WRONLY|O_CREAT|O_TRUNC, mode_t mode=0666)
Definition: FileUtil.h:211
const proxygen::HTTPMessage * getResponse() const
Definition: CurlClient.h:72
#define ASSERT_NE(val1, val2)
Definition: gtest.h:1960
#define ASSERT_FALSE(condition)
Definition: gtest.h:1868
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
bool hexlify(const InputString &input, OutputString &output, bool append_output)
Definition: String-inl.h:596
static std::unique_ptr< IOBuf > copyBuffer(const void *buf, std::size_t size, std::size_t headroom=0, std::size_t minTailroom=0)
Definition: IOBuf.h:1587
#define ASSERT_TRUE(condition)
Definition: gtest.h:1865
ServerThread(HTTPServer *server)
ThreadPoolListHook * addr
TEST(SequencedExecutor, CPUThreadPoolExecutor)
void onRequest(std::unique_ptr< HTTPMessage >) noexceptoverride
void onBody(std::unique_ptr< folly::IOBuf >) noexceptoverride
DummyFilter(RequestHandler *upstream)
constexpr None none
Definition: Optional.h:87