libevent(十三)http server 支持图像与文件下载,并获取表单POST

在这里插入图片描述

简单的请求访问:
浏览器请求相应的url,得到text,html, jpg, zip文件下载,提交表单等操作
main.cpp

#include <iostream>
#include <event2/event.h>
#include <event2/http.h>
#include <event2/keyvalq_struct.h>
#include <event2/buffer.h>
#include <string.h>
#include <string>
#include <event2/listener.h>
#define SPORT 5001
#ifndef _WIN32
#include <signal.h>
#endif
using namespace std;
#define WEBROOT "."
#define DEFAULTINDEX "index.html"


void http_cb(struct evhttp_request* request, void* arg)
{
	cout << "http_cb" << endl;
	//1. 获取浏览器的请求信息
	//uri 网路资源地址 若url="http://127.0.0.1:8080/index.html"(则uri="/index.html")
	const char* uri = evhttp_request_get_uri(request);
	cout << "uri:" << uri << endl;
	
	//请求类型
	string cmdtype;
	switch (evhttp_request_get_command(request))
	{
	case EVHTTP_REQ_GET:
		cmdtype = "GET";
		break;
	case EVHTTP_REQ_POST:
		cmdtype = "POST";
		break;
	default:
		break;
	}
	cout << "cmdtype; " << cmdtype << endl;

	//消息报头
	evkeyvalq* headers = evhttp_request_get_input_headers(request);
	cout << "======headers: =======\n";
	for (evkeyval* p = headers->tqh_first; p != NULL; p = p->next.tqe_next) {
		cout << p->key << ":" << p->value << endl;
	}

	//请求正文(GET=NULL, POST有表单信息)
	evbuffer* inbuf = evhttp_request_get_input_buffer(request);
	char buf[1024] = { 0 };
	cout << "=============inbuf==============" << 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. 回复浏览器
	//状态行,消息报头, 响应正文 HTTP_OK=200  HTTP_NOTFOUND=404 HTTP_INTERNAL=500

	// 分析出请求的文件uri
	// 设置根目录 WEBROOT
	// windows C/C++预处理器 添加 _CRT_SECURE_NO_WARNINGS
	string filepath = WEBROOT;
	filepath += uri;
	if (strcmp(uri, "/") == 0)
	{
		//默认加入首页文件
		filepath += DEFAULTINDEX;
	}

	//消息报头
	evkeyvalq* outhead = evhttp_request_get_output_headers(request);

	// 支持图片,js,css,下载普通zip文件
	// 获取文件的后缀名
	// ./root/index.html
	int pos = filepath.rfind('.');
	string postfix = filepath.substr(pos + 1, filepath.size() - (pos + 1));
	if (postfix == "jpg"||postfix == "gif"||postfix == "png")
	{
		string tmp = "image/" + postfix;
		evhttp_add_header(outhead, "Content-Type", tmp.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");
		evhttp_add_header(outhead, "Content-Type", "text/html");
	}
	else if (postfix == "css")
	{
		evhttp_add_header(outhead, "Content-Type", "text/css");
	}
	else if (postfix == "js")
	{
		evhttp_add_header(outhead, "Content-Type", "text/js");
	}
	
	//读取html文件返回正文
	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, "200 OK", 6);
		evbuffer_add(outbuf, buf, len);
	}
	fclose(fp);
	evhttp_send_reply(request, HTTP_OK, "", outbuf);
}


int main(int argc, char** argv) {
#if _WIN32
	//windowns 初始化socket库
	WSADATA wsa;
	WSAStartup(MAKEWORD(2, 2), &wsa);
#else
	//linux 忽略管道信号,发送数据给已关闭的socket
	if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
		return 1;
#endif
	event_base* base = event_base_new();
	if (base) {
		std::cout << "event_base_new init successfuly!" << std::endl;
	}

	//http 服务器
	//1. 创建evhttp上下文
	evhttp* evh = evhttp_new(base);

	//2. 绑定端口与ip
	if (evhttp_bind_socket(evh, "0.0.0.0", 8080) != 0) {
		cout << "evhttp_bind_socket failed!" << 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);
	}
#ifdef _WIN32
	WSACleanup();
#endif // _WIN32
	return 0;
}

index.html

<HTML>
<HEAD>
   <meta charset="utf-8" />
<TITLE>test http server</TITLE>
</HEAD>
<BODY>
    <h1>test http server h1</h1>
    <h2>this is a test!</h2>
    <h2>这是http服务!</h2>
    <img src="test.jpg" />
    <form method="post">
        <input type="text" name="username"/>
        <input type="password" name="password"/>
        <input type="submit" name="submit" />
    </form>
</BODY>
</HTML>

浏览器展示:
访问:http://127.0.0.1:8080/
在这里插入图片描述
服务端终端:
在这里插入图片描述

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SongpingWang

你的鼓励是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值