#include #include #include #include #include #include #include #ifndef _WIN32 #include #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; }