【libevent】 反向代理

使用libevent反向代理

转载自: https://blog.csdn.net/toontong/article/details/6029151

/**********************
 * ToonTonG@163.com
 * chuantong.huang@gmail.com
 * 2010-11-23
 * 简单的http反向代理
 * *******************/
#include<stdio.h>
#include<stdlib.h>
#include<sys/queue.h>
#include<event.h>
#include<evhttp.h>
char *proxy_host = "10.20.187.231";
unsigned int proxy_port = 80;
int proxy_timeout_in_secs = 60;

// called per chunk received
void chunkcb(struct evhttp_request * req, void * arg) {
	struct evhttp_request *response = (struct evhttp_request *)arg;
	evbuffer_add_buffer(((struct evhttp_request *)arg)->output_buffer , req->input_buffer);
	if (++response->chunked == req->chunked)
	{
		evhttp_send_reply(response, req->response_code, req->response_code_line, req->input_buffer);
		return;
	}
}

// gets called when request completes
void reqcb(struct evhttp_request * req, void * arg) {
	struct evhttp_request *response = (struct evhttp_request*)arg;
	if(!req){
		fprintf(stdout, "http close.");
		evhttp_send_reply(response, 504, "Bad Gateway.", NULL);
		return;
	}
	if (response->chunked)
		return;
	struct evkeyval *header;
	TAILQ_FOREACH(header, req->input_headers, next) {
			evhttp_add_header( response->output_headers,
								(const char *)header->key,
								(const char *)header->value);
	}
	evhttp_send_reply(response, req->response_code, req->response_code_line, req->input_buffer);
	evhttp_send_reply_end(response);
}

struct evhttp_request *proxy_request(const char *domain,
		unsigned short port,
		int timeout_in_secs,
		struct evhttp_request *response)
{
	struct evhttp_connection *evhttp_connection = NULL;
	struct evhttp_request *evhttp_request = NULL;
	evhttp_connection = evhttp_connection_new(domain, port);
//	evhttp_connection_set_local_address(evhttp_connection, &local_addr); //可以为每个连接设置本地IP,一台机可以多个IP,就可超过65535-1024个连接
	evhttp_request = evhttp_request_new(reqcb, (void*)response);
	evhttp_request->chunk_cb = chunkcb;
	struct evkeyval *header;
	TAILQ_FOREACH(header, response->input_headers, next) {
		evhttp_add_header( evhttp_request->output_headers,
							(const char *)header->key,
							(const char *)header->value);
	}
	if (response->type == EVHTTP_REQ_POST){
		evbuffer_add_buffer(evhttp_request->output_buffer , response->input_buffer);
	}
	evhttp_make_request(evhttp_connection, evhttp_request, response->type, response->uri);
	evhttp_connection_set_timeout(evhttp_request->evcon, timeout_in_secs);
	event_loop(EVLOOP_NONBLOCK);
	return evhttp_request;
}

/* 处理函数 */
void pushproxy_handler(struct evhttp_request *req, void *arg)
{
	fprintf(stdout, "request %s/n", req->uri);
	/* 只处理GET与POST请求 */
	if (EVHTTP_REQ_GET != req->type && EVHTTP_REQ_POST != req->type){
		goto response;
	}
	if(!proxy_request(proxy_host, proxy_port, proxy_timeout_in_secs, req)){
		fprintf(stderr, "connect to server fail.");
		goto response;
	}
//    struct evbuffer *buf;
//    buf = evbuffer_new();
    /* 分析URL参数 ,接收GET表单参数, 修改代码根据不同的url反向代理在不同的服务器 */
//  char *decode_uri = strdup((char*) evhttp_request_uri(req));
//  struct evkeyvalq http_query;
//	evhttp_parse_query(decode_uri, &http_query);
//	free(decode_uri);
//	const char *input_uid = evhttp_find_header (&http_query, "uid"); /* 队列名称 */
//	if ( NULL == input_uid || 0 == strlen(input_uid) )
//	{
//		evhttp_send_reply(req, HTTP_NOTFOUND, "404 Not Found.", buf);
//		goto response;
//	}
	/* 内存释放 */
//	evhttp_clear_headers(&http_query);
//	evbuffer_free(buf);
	return;
response:
	evhttp_send_error(req, 502, "Bad Gateway.");
	return;
}

int main(int argc, char **argv)
{
	char *pushproxy_settings_listen = "0.0.0.0";
	int pushproxy_settings_port = 8008;
	int pushproxy_settings_timeout = 60;
	/* 请求处理部分 */
	struct evhttp *httpd;
	event_init();
	httpd = evhttp_start(pushproxy_settings_listen,pushproxy_settings_port);
	if (httpd == NULL) {
		fprintf(stderr, "Error: Unable to listen on %s:%d/n/n", pushproxy_settings_listen, pushproxy_settings_port);
		exit(1);
	}
	evhttp_set_timeout(httpd, pushproxy_settings_timeout);
	/* Set a callback for all other requests. */
	evhttp_set_gencb(httpd, pushproxy_handler, NULL);
	fprintf(stdout, "ok: going in loop event");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值