|
|
#include <iostream>
|
|
#include <event2/http.h>
|
|
#include<event2/event.h>
|
|
#include <event2/listener.h>
|
|
#include <event2/keyvalq_struct.h>
|
|
#include <event2/buffer.h>
|
|
#include <string.h>
|
|
#ifndef _WIN32
|
|
#include <signal.h>
|
|
#include "test_http_server.h"
|
|
#endif // !_WIN32
|
|
|
|
using namespace std;
|
|
|
|
#define WEBROOT "."
|
|
#define DEFAULTINDEX "index.html"
|
|
|
|
void http_cb(struct evhttp_request* request, void *arg) {
|
|
cout << "http_cb" << endl;
|
|
//1 获取浏览器请求信息
|
|
//url
|
|
const char* uri = evhttp_request_get_uri(request);
|
|
cout << "uri:" << uri << endl;
|
|
|
|
//获取请求类型Get Post
|
|
string cmdtype;
|
|
evhttp_cmd_type type = evhttp_request_get_command(request);
|
|
switch (type)
|
|
{
|
|
case EVHTTP_REQ_GET:
|
|
cout << "EVHTTP_REQ_GET" << endl;
|
|
break;
|
|
case EVHTTP_REQ_POST:
|
|
|
|
break;
|
|
case EVHTTP_REQ_HEAD:
|
|
break;
|
|
case EVHTTP_REQ_PUT:
|
|
break;
|
|
case EVHTTP_REQ_DELETE:
|
|
break;
|
|
case EVHTTP_REQ_OPTIONS:
|
|
break;
|
|
case EVHTTP_REQ_TRACE:
|
|
break;
|
|
case EVHTTP_REQ_CONNECT:
|
|
break;
|
|
case EVHTTP_REQ_PATCH:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
//消息报头
|
|
evkeyvalq *headers = evhttp_request_get_input_headers(request);
|
|
cout << "========headers========\n" << endl;
|
|
|
|
for (evkeyval *p = headers->tqh_first; p != NULL; p = p->next.tqe_next) {
|
|
cout << p->key << ":" << p->value << endl;
|
|
}
|
|
|
|
//请求正文
|
|
evbuffer*inbuf = evhttp_request_get_input_buffer(request);
|
|
char buf[1024] = { 0 };
|
|
cout << "=========Input data ===========" << endl;
|
|
while (evbuffer_get_length(inbuf)) {
|
|
int n = evbuffer_remove(inbuf, buf, sizeof(buf) - 1);
|
|
|
|
if (n > 0) {
|
|
buf[n] = '\0';
|
|
cout << buf << endl;
|
|
}
|
|
}
|
|
|
|
|
|
//2 回复浏览器
|
|
//状态行 响应正文
|
|
|
|
//消息报头
|
|
evkeyvalq *outhead = evhttp_request_get_output_headers(request);
|
|
|
|
|
|
//分析URI
|
|
//设置根目录
|
|
string filepath = WEBROOT;
|
|
filepath += uri;
|
|
if (strcmp(uri, "/") == 0) {
|
|
filepath += DEFAULTINDEX;
|
|
}
|
|
|
|
//文件后缀
|
|
int pos = filepath.rfind(".");
|
|
string postfix = filepath.substr(pos+1,filepath.size() - (pos+1));
|
|
if (postfix == "jpg" || postfix == "png" || postfix == "gif" || postfix == "ico") {
|
|
string temp = "image/" + postfix;
|
|
evhttp_add_header(outhead, "Content-Type", temp.c_str());
|
|
}
|
|
else if (postfix == "zip") {
|
|
evhttp_add_header(outhead, "Content-Type", "application/zip");
|
|
}
|
|
else if (postfix == "html") {
|
|
evhttp_add_header(outhead, "Content-Type", "text/html;charset=UTF8");
|
|
}
|
|
else if (postfix == "css") {
|
|
evhttp_add_header(outhead, "Content-Type", "text/css");
|
|
}
|
|
|
|
FILE *fp = fopen(filepath.c_str(), "rb");
|
|
if (!fp) {
|
|
evhttp_send_reply(request, HTTP_NOTFOUND, "", 0);
|
|
return;
|
|
}
|
|
|
|
evbuffer *outbuf = evhttp_request_get_output_buffer(request);
|
|
|
|
for (;;) {
|
|
int len = fread(buf, 1,sizeof(buf), fp);
|
|
if (len <= 0)
|
|
break;
|
|
evbuffer_add(outbuf, buf, len);
|
|
}
|
|
fclose(fp);
|
|
|
|
evhttp_send_reply(request, HTTP_OK, "", outbuf);
|
|
|
|
|
|
}
|
|
|
|
int main()
|
|
{
|
|
#ifdef _WIN32
|
|
//初始化socket库
|
|
WSADATA wsa;
|
|
WSAStartup(MAKEWORD(2, 2), &wsa);
|
|
#else
|
|
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { //忽略管道信号,发送数据给已关闭的socket,会飞掉!
|
|
return 1;
|
|
}
|
|
#endif
|
|
|
|
//创建libevent上下文
|
|
event_base* base = event_base_new();
|
|
if (base) {
|
|
std::cout << "test server" << "\n";
|
|
}
|
|
|
|
//http 服务器
|
|
//1.创建evhttp上下文
|
|
evhttp *evh = evhttp_new(base);
|
|
|
|
//2.绑定端口、IP
|
|
if (evhttp_bind_socket(evh, "0.0.0.0", 8080) != 0) {
|
|
cout << "绑定失败" << endl;
|
|
}
|
|
|
|
//3. 设定回调函数
|
|
evhttp_set_gencb(evh, http_cb, 0);
|
|
|
|
|
|
if (base)
|
|
event_base_dispatch(base); //事件分发处理
|
|
if (base)
|
|
event_base_free(base);
|
|
if (evh)
|
|
evhttp_free(evh);
|
|
|
|
#if _WIN32
|
|
WSACleanup();
|
|
#endif // _WIN32
|
|
|
|
|
|
|
|
return 0;
|
|
}
|
|
|
|
|