proxygen
CurlClientMain.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  *
10  * This is a higly simplified example of an HTTP client. This can be heavily
11  * extended using mechanisms like redirects, transfer encoding, connection
12  * pooling, etc.
13  *
14  */
16 
19 #include <folly/SocketAddress.h>
21 #include "CurlClient.h"
22 
23 using namespace CurlService;
24 using namespace folly;
25 using namespace proxygen;
26 using std::vector;
27 
29  "HTTP method to use. GET or POST are supported");
30 DEFINE_string(url, "https://github.com/facebook/proxygen",
31  "URL to perform the HTTP method against");
32 DEFINE_string(input_filename, "",
33  "Filename to read from for POST requests");
34 DEFINE_int32(http_client_connect_timeout, 1000,
35  "connect timeout in milliseconds");
36 DEFINE_string(ca_path, "/etc/ssl/certs/ca-certificates.crt",
37  "Path to trusted CA file"); // default for Ubuntu 14.04
38 DEFINE_string(cert_path, "",
39  "Path to client certificate file");
40 DEFINE_string(key_path, "",
41  "Path to client private key file");
42 DEFINE_string(next_protos, "h2,h2-14,spdy/3.1,spdy/3,http/1.1",
43  "Next protocol string for NPN/ALPN");
44 DEFINE_string(plaintext_proto, "", "plaintext protocol");
45 DEFINE_int32(recv_window, 65536, "Flow control receive window for h2/spdy");
46 DEFINE_bool(h2c, true, "Attempt HTTP/1.1 -> HTTP/2 upgrade");
47 DEFINE_string(headers, "", "List of N=V headers separated by ,");
48 DEFINE_string(proxy, "", "HTTP proxy URL");
49 
50 int main(int argc, char* argv[]) {
51  gflags::ParseCommandLineFlags(&argc, &argv, true);
52  google::InitGoogleLogging(argv[0]);
53  google::InstallFailureSignalHandler();
54 
55  EventBase evb;
56  URL url(FLAGS_url);
57  URL proxy(FLAGS_proxy);
58 
59  if (FLAGS_http_method != "GET" && FLAGS_http_method != "POST") {
60  LOG(ERROR) << "http_method must be either GET or POST";
61  return EXIT_FAILURE;
62  }
63 
64  HTTPMethod httpMethod = *stringToMethod(FLAGS_http_method);
65  if (httpMethod == HTTPMethod::POST) {
66  try {
67  File f(FLAGS_input_filename);
68  (void)f;
69  } catch (const std::system_error& se) {
70  LOG(ERROR) << "Couldn't open file for POST method";
71  LOG(ERROR) << se.what();
72  return EXIT_FAILURE;
73  }
74  }
75 
76  HTTPHeaders headers = CurlClient::parseHeaders(FLAGS_headers);
77 
78  CurlClient curlClient(&evb,
79  httpMethod,
80  url,
81  FLAGS_proxy.empty() ? nullptr : &proxy,
82  headers,
83  FLAGS_input_filename,
84  FLAGS_h2c);
85  curlClient.setFlowControlSettings(FLAGS_recv_window);
86 
88  if (!FLAGS_proxy.empty()) {
89  addr = SocketAddress(proxy.getHost(), proxy.getPort(), true);
90  } else {
91  addr = SocketAddress(url.getHost(), url.getPort(), true);
92  }
93  LOG(INFO) << "Trying to connect to " << addr;
94 
95  // Note: HHWheelTimer is a large object and should be created at most
96  // once per thread
97  HHWheelTimer::UniquePtr timer{HHWheelTimer::newTimer(
98  &evb,
99  std::chrono::milliseconds(HHWheelTimer::DEFAULT_TICK_INTERVAL),
100  AsyncTimeout::InternalEnum::NORMAL,
101  std::chrono::milliseconds(5000))};
102  HTTPConnector connector(&curlClient, timer.get());
103  if (!FLAGS_plaintext_proto.empty()) {
104  connector.setPlaintextProtocol(FLAGS_plaintext_proto);
105  }
106  static const AsyncSocket::OptionMap opts{{{SOL_SOCKET, SO_REUSEADDR}, 1}};
107 
108  if (url.isSecure()) {
109  curlClient.initializeSsl(
110  FLAGS_ca_path, FLAGS_next_protos, FLAGS_cert_path, FLAGS_key_path);
111  connector.connectSSL(
112  &evb,
113  addr,
114  curlClient.getSSLContext(),
115  nullptr,
116  std::chrono::milliseconds(FLAGS_http_client_connect_timeout),
117  opts,
119  curlClient.getServerName());
120  } else {
121  connector.connect(&evb, addr,
122  std::chrono::milliseconds(FLAGS_http_client_connect_timeout), opts);
123  }
124 
125  evb.loop();
126 
127  return EXIT_SUCCESS;
128 }
static proxygen::HTTPHeaders parseHeaders(const std::string &headersString)
Definition: CurlClient.cpp:48
int main(int argc, char *argv[])
folly::Optional< HTTPMethod > stringToMethod(folly::StringPiece method)
Definition: HTTPMethod.cpp:37
auto f
const std::string & getHost() const noexcept
Definition: URL.h:118
void setFlowControlSettings(int32_t recvWindow)
Definition: CurlClient.cpp:108
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
char ** argv
std::map< OptionKey, int > OptionMap
Definition: AsyncSocket.h:376
DEFINE_int32(http_client_connect_timeout, 1000,"connect timeout in milliseconds")
static const folly::SocketAddress & anyAddress()
void setPlaintextProtocol(const std::string &plaintextProto)
http_method
Definition: http_parser.h:90
std::unique_ptr< HHWheelTimer, Destructor > UniquePtr
Definition: HHWheelTimer.h:57
bool isSecure() const noexcept
Definition: URL.h:110
DEFINE_string(http_method,"GET","HTTP method to use. GET or POST are supported")
uint16_t getPort() const noexcept
Definition: URL.h:102
DEFINE_bool(h2c, true,"Attempt HTTP/1.1 -> HTTP/2 upgrade")
ThreadPoolListHook * addr