关于Http协议中的Range字段详解

Http协议Range字段解析与应用
本文详细介绍了Http协议中的Range字段,其主要用于支持范围请求,常见于客户端多线程并发获取服务端资源。作者分享了在实现HTTP服务器时遇到的问题,特别是关于Content-Range响应头的设置,强调其应表示一个闭区间。

个人空间(后台就是c/c++写的httpserver)

=首先Range字段的作用是支持http协议的范围请求,而范围请求的用途多用于客户端多线程请求服务端某一资源,实现高效并发。

 

扫描二维码看MDN文档对Http.Range字段的描述,应该比我写的好,

或者Http协议的Range字段-----MDN

 

 

然后我再说点我的踩的坑:

一下是我的httpserver收到的一个浏览器的一个含有Range的请求:

GET /gdl/bgm/zhoushen-t.mp3 HTTP/1.1
Host: www.yqun.xyz
Connection: keep-alive
Accept-Encoding: identity;q=1, *;q=0
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36
Accept: */*
Referer: http://www.yqun.xyz/gdl/articles/e7a7bbe58aa8e9809ae4bfa147534dindex.html
Accept-Language: zh-CN,zh;q=0.9
Range: bytes=0-

响应是这样的:

HTTP/1.1 206 Partial Content
Content-Type: audio/mp3
Server: gdl_WebServer
Connection: keep-alive
Keep-Alive: timeout=59, max=100
Accept-Ranges: bytes
Content-Range: bytes 0-3601310/3601311
Content-Length: 3601311

然后值得注意的是在此前的的实现中,将请求的Range字段的范围"0-"直接截取给响应头的Content-Range的范围,导致每次浏览器都请求range失败。请记住他:在响应头中的Content-Range中的给出的范围是一个[start,end]的一个含有两个端点值得一个闭区间。

 

关于我的range的分解(未做优化):

bool gdl::Http::getranges(){

	//get file size.
	size_t filesz = getfilesize();
	if(0 > filesz){
		status = STATUS_HTTP_FILE_NOT_EXIST;
		statusCode = "404 Not Found\r\n";
		return false;
	}
	std::string &srange = mapField.at(pfields[NUM_RANGE]);
	//get ranges.
	auto vret = gdl::split(srange, "=");
	if(2 != vret.size())
		return false;
	//decompose range from ranges.
	range_str = gdl::split(vret.at(1), ",");
	//dispose range.
	try{

		for(auto it : range_str){
			//getposs of '-'
			auto cret = gdl::getposs(it, "-");
			if(0 == cret.size()){
				//there is no '-'
				int pos = std::stoi(it);
				if(pos >= filesz)throw "you are a pig.";;
				range.push_back(std::pair<size_t,size_t>(pos, filesz - pos));
			}
			else if(1 == cret.size()){
				//there is a '-'
				//if it is begin with '-':
				if('-' == it.at(0)){
					int pos = std::stoi(it);
					pos += filesz;
					if(0 > pos)throw "you are a pig pig.";;
					range.push_back(std::pair<size_t,size_t>(pos, filesz - pos));
				}
				//if it is end with '-':
				else if('-' == it.at(it.size() - 1)){
					int pos = std::stoi(it);
					if(pos >= filesz)throw "you are a small pig.";;
					range.push_back(std::pair<size_t,size_t>(pos, filesz - pos));
				}
				else{
					//like: 500-1000
					int pos1 = std::stoi(it);
					int pos2 = std::stoi(it.substr(it.find("-")));
					pos2 = pos2 *- 1;
					if(pos1 > pos2 || pos2 >= filesz)throw "you are a small pig pig.";;
					range.push_back(std::pair<size_t,size_t>(pos1, pos2 - pos1 + 1));
				}
			}
			else
				throw "you are a small pig pig.";
		}
	}
	catch(...){
		range.clear();
		range_str.clear();
		return false;
	}
	//重组range_str.
	for(int ii = 0; ii<range_str.size(); ii++){

		range_str[ii] = std::to_string(range[ii].first) + "-" + std::to_string(range[ii].first+range[ii].second - 1);
	}
	
	return true;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值