hv 支持内容压缩

本文介绍了如何在HTTP服务中利用zlib库对响应数据进行gzip或deflate压缩,根据客户端的Accept-Encoding头判断并设置适当的Content-Encoding。
摘要由CSDN通过智能技术生成

本文参考:HTTP协议之压缩,需要依赖zlib,摘抄Crow源码

支持 br, deflate, gzip

xHttpCompress.h

#pragma once

#include <string>
#include <zlib.h>

// http://zlib.net/manual.html

namespace xHttpCompress
{
	// Values used in the 'windowBits' parameter for deflateInit2.
	enum algorithm
	{
		// 15 is the default value for deflate
		DEFLATE = 15,
		// windowBits can also be greater than 15 for optional gzip encoding.
		// Add 16 to windowBits to write a simple gzip header and trailer around the compressed data instead of a zlib wrapper.
		GZIP = 15 | 16,
	};

	inline std::string compress_string(std::string const& str, algorithm algo)
	{
		std::string compressed_str;
		z_stream stream{};
		// Initialize with the default values
		if (::deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, algo, 8, Z_DEFAULT_STRATEGY) == Z_OK)
		{
			char buffer[8192];

			stream.avail_in = str.size();
			// zlib does not take a const pointer. The data is not altered.
			stream.next_in = const_cast<Bytef*>(reinterpret_cast<const Bytef*>(str.c_str()));

			int code = Z_OK;
			do
			{
				stream.avail_out = sizeof(buffer);
				stream.next_out = reinterpret_cast<Bytef*>(&buffer[0]);

				code = ::deflate(&stream, Z_FINISH);
				// Successful and non-fatal error code returned by deflate when used with Z_FINISH flush
				if (code == Z_OK || code == Z_STREAM_END)
				{
					std::copy(&buffer[0], &buffer[sizeof(buffer) - stream.avail_out], std::back_inserter(compressed_str));
				}

			} while (code == Z_OK);

			if (code != Z_STREAM_END)
				compressed_str.clear();

			::deflateEnd(&stream);
		}

		return compressed_str;
	}

	inline std::string decompress_string(std::string const& deflated_string)
	{
		std::string inflated_string;
		Bytef tmp[8192];

		z_stream zstream{};
		zstream.avail_in = deflated_string.size();
		// Nasty const_cast but zlib won't alter its contents
		zstream.next_in = const_cast<Bytef*>(reinterpret_cast<Bytef const*>(deflated_string.c_str()));
		// Initialize with automatic header detection, for gzip support
		if (::inflateInit2(&zstream, MAX_WBITS | 32) == Z_OK)
		{
			do
			{
				zstream.avail_out = sizeof(tmp);
				zstream.next_out = &tmp[0];

				auto ret = ::inflate(&zstream, Z_NO_FLUSH);
				if (ret == Z_OK || ret == Z_STREAM_END)
				{
					std::copy(&tmp[0], &tmp[sizeof(tmp) - zstream.avail_out], std::back_inserter(inflated_string));
				}
				else
				{
					// Something went wrong with inflate; make sure we return an empty string
					inflated_string.clear();
					break;
				}

			} while (zstream.avail_out == 0);

			// Free zlib's internal memory
			::inflateEnd(&zstream);
		}

		return inflated_string;
	}
} // namespace xHttpCompress

hv 实现content压缩
HttpService router;
http_sync_handler user_status = std::bind(&XHttpServices::OnUserStatus, this, std::placeholders::_1, std::placeholders::_2);
router.GET("/user/status", user_status);

```cpp
int XHttpServices::OnUserStatus(HttpRequest* req, HttpResponse* resp)
{
	XLOGI("OnUserStatus:%s", UTF82ACSTR(req->body));
	hv::Json jresp, jdata;
	try
	{
		jresp["code"] = jeflib::ERR_OK;
		jresp["msg"] = jeflib::strerror(jresp["code"]);
		jdata = UserMgr::instance().GetUserStatus();
		jresp["data"] = jdata;
		
		//查询客户端支持的压缩算法
		std::string accept_encoding = req->GetHeader("Accept-Encoding");
		if (accept_encoding.find("gzip") != std::string::npos)
		{
			resp->SetHeader("Content-Encoding", "gzip");
			std::string strcontent = xHttpCompress::compress_string(jresp.dump(), xHttpCompress::algorithm::GZIP);
			return resp->String(strcontent);
		}
		else if (accept_encoding.find("deflate") != std::string::npos)
		{
			resp->SetHeader("Content-Encoding", "deflate");
			std::string strcontent = xHttpCompress::compress_string(jresp.dump(), xHttpCompress::algorithm::DEFLATE);
			return resp->String(strcontent);
		}

		return resp->String(jresp.dump());
	}
	catch (const nlohmann::detail::exception& e)
	{
		jresp["code"] = jeflib::ERR_JSON_EXCEPTION;
		jresp["msg"] = e.what();
		return resp->String(jresp.dump());
	}
}

测试结果:
在这里插入图片描述

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值