关于Http协议中的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;
}

 


版权声明:本文为dong1528313271原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。