hv web服务

在实际工作中,为了保证App的高可用性,服务端需要缓存一部分静态资源,通过web服务来分发资源。hv即可快速实现web服务。

hv静态资源服务(如果含中文路径需转utf8,否则抛异常)。
HttpService router;
router.Static("/statics", "smart-yi-ui");

目录结构(smart-yi-ui 映射静态资源):
demo.exe
此时访问:http://127.0.0.1:13456/statics/index.html即可获取smart-yi-ui的index.html资源。

hv 支持大文件上传服务
//upload
	http_state_handler upload = std::bind(&XHttpServices::OnUpload, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);
	m_http_router.POST("/shader/upload", upload);

//验签+分段接受存储+应答
int XHttpServices::OnUpload(const HttpContextPtr& ctx, http_parser_state state, const char* data, size_t size)
{
	//hv内部会自动urldecode,所以此处不用decode
	const std::string& filename = UTF82ASTR(ctx->param("filename")); 
	const std::string& gamename = UTF82ASTR(ctx->param("gamename"));
	const std::string& filemd5 = ctx->param("md5");

	int status_code = HTTP_STATUS_UNFINISHED;
	HFileUnShared* file = (HFileUnShared*)ctx->userdata;
	switch (state) {
	case HP_HEADERS_COMPLETE:
	{
		if (ctx->is(MULTIPART_FORM_DATA))
		{
			// NOTE: You can use multipart_parser if you want to use multipart/form-data.
			ctx->close();
			return HTTP_STATUS_BAD_REQUEST;
		}
		
		XLOGI("OnUpload url[%s]", ctx->url().c_str());
		if (filename.empty() || gamename.empty() || filemd5.empty())
		{
			response_status(ctx, 1, "params invalid");
			return HTTP_STATUS_OK;
		}

		if (!CheckSign(ctx->params()))
		{
			response_status(ctx, 2, "sign check error");
			XLOGI("OnUpload Skip,game[%s] file[%s] md5[%s] sign not match", gamename.c_str(), filename.c_str(), filemd5.c_str());
			return HTTP_STATUS_OK;
		}

		//查询游戏目录失败
		std::string game_dir = QueryGamePath(gamename);
#ifdef _DEBUG
		game_dir = "d:\\123\\123";
#endif // _DEBUG

		if (game_dir.empty())
		{
			response_status(ctx, 3, "game dir not find");
			XLOGI("OnUpload Skip,game[%s] dir not find", gamename.c_str());
			return HTTP_STATUS_OK;
		}
		ExecludeFolders(game_dir);
		std::string save_path =JoinPath(game_dir, SHARDER_FOLDER_NAME);
		CreateDir(save_path);
		std::string filepath = JoinPath(save_path,filename);
		//如果着色文件已经存在则不在上传
		if (_access(filepath.c_str(), 00) == 0)
		{
			response_status(ctx, 0, "file is exist,no need upload");
			XLOGI("OnUpload Skip,game[%s] file[%s] md5[%s] file is exist", gamename.c_str(), filename.c_str(), filemd5.c_str());
			return HTTP_STATUS_OK;
		}
		//已独占方式打开
		file = new HFileUnShared(filemd5);
		int errcode = file->open((filepath+".upload").c_str(), "wb");
		if (errcode != 0)
		{
			XLOGI("OnUpload Skip,open[%s] failed[%d],game[%s] file[%s] md5[%s]", filepath.c_str(),errcode, gamename.c_str(), filename.c_str(), filemd5.c_str());
			response_status(ctx, 4, fmt::format("file open failed[{0}]",errcode).c_str());
			return HTTP_STATUS_OK;
		}
		ctx->userdata = file;
	}
	break;
	case HP_BODY:
	{
		if (file && data && size) {
			if (file->write(data, size) != size) {
				int errcode = errno;
				response_status(ctx, -1, "file write failed");
				XLOGI("OnUpload Skip,file[%s] write failed[%d],game[%s] file[%s] md5[%s]", file->filepath, errcode, gamename.c_str(), filename.c_str(), filemd5.c_str());
				return HTTP_STATUS_OK;
			}
		}
	}
	break;
	case HP_MESSAGE_COMPLETE:
	{
		if (file)
		{
			if (file->checkmd5())
			{
				std::string end_suffix = ".upload";
				std::string new_filename = file->filepath;
				if (hv::endswith(new_filename, end_suffix))
				{
					new_filename.erase(new_filename.size() - end_suffix.size(), end_suffix.size());
					file->rename(new_filename.c_str());
					XLOGI("rename [%s]->[%s]", file->filepath, new_filename.c_str());
				}
				
				if (_access(new_filename.c_str(), 00) == 0)
				{
					XLOGI("OnUpload OK,path[%s],game[%s] file[%s] md5[%s]", file->filepath, gamename.c_str(), filename.c_str(), filemd5.c_str());
					response_status(ctx, 0, "successed");
				}
				else
				{
					XLOGI("OnUpload failed rename failed,path[%s],game[%s] file[%s] md5[%s]", file->filepath, gamename.c_str(), filename.c_str(), filemd5.c_str());
					response_status(ctx, -2, "rename failed");
				}
			}
			else
			{
				XLOGI("OnUpload failed md5 not match,path[%s],game[%s] file[%s] md5[%s]", file->filepath, gamename.c_str(), filename.c_str(), filemd5.c_str());
				response_status(ctx, -3, "md5 not match");
			}

			delete file;
			ctx->userdata = NULL;
		}	
	}
	break;
	case HP_ERROR:
	{
		if (file)
		{
			delete file;
			ctx->userdata = NULL;
		}
	}
	break;
	default:
		break;
	}
	return status_code;
}

int XHttpServices::response_status(HttpResponse* resp, int code, const char* message) {
	if (message == NULL) message = http_status_str((enum http_status)code);
	resp->Set("code", code);
	resp->Set("message", message);
	return code;
}
int XHttpServices::response_status(const HttpResponseWriterPtr& writer, int code, const char* message) {
	response_status(writer->response.get(), code, message);
	writer->End();
	return code;
}
int XHttpServices::response_status(const HttpContextPtr& ctx, int code , const char* message ) {
	ctx->setContentType(APPLICATION_JSON);
	response_status(ctx->response.get(), code, message);
	ctx->send();
	ctx->close();
	return code;
}
hv 实现重定向
http_sync_handler user_status = std::bind(&XHttpServices::OnUserStatus, this, std::placeholders::_1, std::placeholders::_2);
router.GET("/user/status", user_status);


int XHttpServices::OnUserStatus(HttpRequest* req, HttpResponse* resp)
{
	//设置重定向地址
	resp->SetHeader("Location", "https://www.baidu.com");
	return 302;
}

此时访问http://127.0.0.1:13456//user/status即可重定向到https://www.baidu.com

hv 实现文件下载服务
int XHttpServices::OnDownaload(HttpRequest* req, HttpResponse* resp)
{
	//解析请求文件名,匹配文件地址
	char* path = "D:\\demo.zip";
    return resp->File(path);
}
hv 客户端提交表单
requests::uploadFormFile

如果需要提交多文件,重写uploadFormFile,SetFormFile支持多文件。

华为RH2288HV2服务器的管理口地址是指用于远程管理和监控服务器的网口地址。RH2288HV2服务器提供了两种管理口类型:管理网口和iBMC管理口。管理网口的地址可以通过后台接入交换机或路由器进行管理,iBMC管理口用于连接服务器的基板管理控制器。具体管理口地址的设置步骤如下: 1. 管理网口地址设置: a. 首先,登录服务器操作系统或虚拟化管理界面。 b. 打开网络配置面板,在网卡列表中找到管理网口对应的网卡。 c. 设置管理网口的IP地址、子网掩码、网关等参数。确保与管理网络的配置相匹配,并确保IP地址在管理网络范围内。 d. 单击保存并应用设置,使新的管理网口地址生效。 2. iBMC管理口地址设置: a. 使用连接线将服务器的iBMC管理口与管理网络的交换机或路由器相连。 b. 打开Web浏览器,输入预设的iBMC管理网地址(默认为192.168.1.100),进入iBMC管理界面。 c. 在iBMC管理界面中找到网络配置选项,进入网络配置页面。 d. 根据实际需要,配置iBMC管理口的IP地址、子网掩码、网关等参数。 e. 单击保存并应用设置,使新的iBMC管理口地址生效。 需要注意的是,确保所设置的管理口地址与网络环境相匹配,以便实现远程管理和监控服务器的目的。另外,需要保证管理口的网络连接是稳定和可靠的,以确保服务器远程访问的可用性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值