xref: /netbsd-src/external/bsd/libevent/dist/sample/http-connect.c (revision 657871a79c9a2060a6255a242fa1a1ef76b56ec6)
1*657871a7Schristos /*	$NetBSD: http-connect.c,v 1.1.1.2 2021/04/07 02:43:15 christos Exp $	*/
2805a1ce9Schristos #include "event2/event-config.h"
3805a1ce9Schristos #include <sys/cdefs.h>
4*657871a7Schristos __RCSID("$NetBSD: http-connect.c,v 1.1.1.2 2021/04/07 02:43:15 christos Exp $");
5805a1ce9Schristos 
6805a1ce9Schristos #include <event2/event.h>
7805a1ce9Schristos #include <event2/http.h>
8805a1ce9Schristos #include <event2/http_struct.h>
9805a1ce9Schristos #include <event2/buffer.h>
10805a1ce9Schristos #include <stdlib.h>
11805a1ce9Schristos #include <stdio.h>
12805a1ce9Schristos #include <limits.h>
13805a1ce9Schristos 
14805a1ce9Schristos #define VERIFY(cond) do {                       \
15805a1ce9Schristos 	if (!(cond)) {                              \
16805a1ce9Schristos 		fprintf(stderr, "[error] %s\n", #cond); \
17*657871a7Schristos 		exit(EXIT_FAILURE);                     \
18805a1ce9Schristos 	}                                           \
19805a1ce9Schristos } while (0);                                    \
20805a1ce9Schristos 
21805a1ce9Schristos #define URL_MAX 4096
22805a1ce9Schristos 
23805a1ce9Schristos struct connect_base
24805a1ce9Schristos {
25805a1ce9Schristos 	struct evhttp_connection *evcon;
26805a1ce9Schristos 	struct evhttp_uri *location;
27805a1ce9Schristos };
28805a1ce9Schristos 
uri_parse(const char * str)29*657871a7Schristos static struct evhttp_uri* uri_parse(const char *str)
30*657871a7Schristos {
31*657871a7Schristos 	struct evhttp_uri *uri;
32*657871a7Schristos 	VERIFY(uri = evhttp_uri_parse(str));
33*657871a7Schristos 	VERIFY(evhttp_uri_get_host(uri));
34*657871a7Schristos 	VERIFY(evhttp_uri_get_port(uri) > 0);
35*657871a7Schristos 	return uri;
36*657871a7Schristos }
uri_path(struct evhttp_uri * uri,char buffer[URL_MAX])37*657871a7Schristos static char* uri_path(struct evhttp_uri *uri, char buffer[URL_MAX])
38*657871a7Schristos {
39*657871a7Schristos 	struct evhttp_uri *path;
40*657871a7Schristos 
41*657871a7Schristos 	VERIFY(evhttp_uri_join(uri, buffer, URL_MAX));
42*657871a7Schristos 
43*657871a7Schristos 	path = evhttp_uri_parse(buffer);
44*657871a7Schristos 	evhttp_uri_set_scheme(path, NULL);
45*657871a7Schristos 	evhttp_uri_set_userinfo(path, 0);
46*657871a7Schristos 	evhttp_uri_set_host(path, NULL);
47*657871a7Schristos 	evhttp_uri_set_port(path, -1);
48*657871a7Schristos 	VERIFY(evhttp_uri_join(path, buffer, URL_MAX));
49*657871a7Schristos 	return buffer;
50*657871a7Schristos }
uri_hostport(struct evhttp_uri * uri,char buffer[URL_MAX])51*657871a7Schristos static char* uri_hostport(struct evhttp_uri *uri, char buffer[URL_MAX])
52*657871a7Schristos {
53*657871a7Schristos 	VERIFY(evhttp_uri_join(uri, buffer, URL_MAX));
54*657871a7Schristos 	VERIFY(evhttp_uri_get_host(uri));
55*657871a7Schristos 	VERIFY(evhttp_uri_get_port(uri) > 0);
56*657871a7Schristos 	evutil_snprintf(buffer, URL_MAX, "%s:%d",
57*657871a7Schristos 		evhttp_uri_get_host(uri), evhttp_uri_get_port(uri));
58*657871a7Schristos 	return buffer;
59*657871a7Schristos }
60*657871a7Schristos 
get_cb(struct evhttp_request * req,void * arg)61805a1ce9Schristos static void get_cb(struct evhttp_request *req, void *arg)
62805a1ce9Schristos {
63805a1ce9Schristos 	ev_ssize_t len;
64805a1ce9Schristos 	struct evbuffer *evbuf;
65805a1ce9Schristos 
66805a1ce9Schristos 	VERIFY(req);
67805a1ce9Schristos 
68805a1ce9Schristos 	evbuf = evhttp_request_get_input_buffer(req);
69805a1ce9Schristos 	len = evbuffer_get_length(evbuf);
70805a1ce9Schristos 	fwrite(evbuffer_pullup(evbuf, len), len, 1, stdout);
71805a1ce9Schristos 	evbuffer_drain(evbuf, len);
72805a1ce9Schristos }
73805a1ce9Schristos 
connect_cb(struct evhttp_request * proxy_req,void * arg)74805a1ce9Schristos static void connect_cb(struct evhttp_request *proxy_req, void *arg)
75805a1ce9Schristos {
76805a1ce9Schristos 	struct connect_base *base = arg;
77805a1ce9Schristos 	struct evhttp_connection *evcon = base->evcon;
78805a1ce9Schristos 	struct evhttp_uri *location = base->location;
79*657871a7Schristos 	struct evhttp_request *req;
80*657871a7Schristos 	char buffer[URL_MAX];
81805a1ce9Schristos 
82805a1ce9Schristos 	VERIFY(proxy_req);
83*657871a7Schristos 	VERIFY(evcon);
84*657871a7Schristos 
85*657871a7Schristos 	req = evhttp_request_new(get_cb, NULL);
86805a1ce9Schristos 	evhttp_add_header(req->output_headers, "Connection", "close");
87*657871a7Schristos 	evhttp_add_header(req->output_headers, "Host", evhttp_uri_get_host(location));
88805a1ce9Schristos 	VERIFY(!evhttp_make_request(evcon, req, EVHTTP_REQ_GET,
89*657871a7Schristos 		uri_path(location, buffer)));
90805a1ce9Schristos }
91805a1ce9Schristos 
main(int argc,const char ** argv)92805a1ce9Schristos int main(int argc, const char **argv)
93805a1ce9Schristos {
94*657871a7Schristos 	char hostport[URL_MAX];
95805a1ce9Schristos 
96805a1ce9Schristos 	struct evhttp_uri *location;
97805a1ce9Schristos 	struct evhttp_uri *proxy;
98805a1ce9Schristos 
99805a1ce9Schristos 	struct event_base *base;
100805a1ce9Schristos 	struct evhttp_connection *evcon;
101805a1ce9Schristos 	struct evhttp_request *req;
102805a1ce9Schristos 
103805a1ce9Schristos 	struct connect_base connect_base;
104805a1ce9Schristos 
105805a1ce9Schristos 	if (argc != 3) {
106805a1ce9Schristos 		printf("Usage: %s proxy url\n", argv[0]);
107805a1ce9Schristos 		return 1;
108805a1ce9Schristos 	}
109805a1ce9Schristos 
110*657871a7Schristos 	proxy    = uri_parse(argv[1]);
111*657871a7Schristos 	location = uri_parse(argv[2]);
112805a1ce9Schristos 
113805a1ce9Schristos 	VERIFY(base = event_base_new());
114805a1ce9Schristos 	VERIFY(evcon = evhttp_connection_base_new(base, NULL,
115805a1ce9Schristos 		evhttp_uri_get_host(proxy), evhttp_uri_get_port(proxy)));
116805a1ce9Schristos 	connect_base.evcon = evcon;
117805a1ce9Schristos 	connect_base.location = location;
118805a1ce9Schristos 	VERIFY(req = evhttp_request_new(connect_cb, &connect_base));
119805a1ce9Schristos 
120*657871a7Schristos 	uri_hostport(location, hostport);
121805a1ce9Schristos 	evhttp_add_header(req->output_headers, "Connection", "keep-alive");
122805a1ce9Schristos 	evhttp_add_header(req->output_headers, "Proxy-Connection", "keep-alive");
123*657871a7Schristos 	evhttp_add_header(req->output_headers, "Host", hostport);
124*657871a7Schristos 	evhttp_make_request(evcon, req, EVHTTP_REQ_CONNECT, hostport);
125805a1ce9Schristos 
126805a1ce9Schristos 	event_base_dispatch(base);
127*657871a7Schristos 
128805a1ce9Schristos 	evhttp_connection_free(evcon);
129805a1ce9Schristos 	event_base_free(base);
130805a1ce9Schristos 	evhttp_uri_free(proxy);
131805a1ce9Schristos 	evhttp_uri_free(location);
132*657871a7Schristos 
133805a1ce9Schristos 	return 0;
134805a1ce9Schristos }
135