mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-26 04:31:37 +08:00
http地址支持相对路径 (#2223)
* 部分hls中会出现类似[../]或者[./]的相对地址, 因此写了一个解析的方法 * 有时候上游http协议不规范会导致直接输出eof, 特别是在自动重试机制开启下, 容易造成定时器没办法初始化从而拉不到流但是session一直存在,所以需要做一个判断,如果没数据直接报错
This commit is contained in:
parent
5bcfba1da4
commit
2f8dab66c5
@ -159,7 +159,81 @@ StrCaseMap Parser::parseArgs(const string &str, const char *pair_delim, const ch
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
std::string Parser::merge_url(const string &base_url, const string &path) {
|
||||||
|
//以base_url为基础, 合并path路径生成新的url, path支持相对路径和绝对路径
|
||||||
|
if (base_url.empty()) {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
if (path.empty()) {
|
||||||
|
return base_url;
|
||||||
|
}
|
||||||
|
// 如果包含协议,则直接返回
|
||||||
|
if (path.find("://") != string::npos) {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
string protocol = "http://";
|
||||||
|
size_t protocol_end = base_url.find("://");
|
||||||
|
if (protocol_end != string::npos) {
|
||||||
|
protocol = base_url.substr(0, protocol_end + 3);
|
||||||
|
}
|
||||||
|
// 如果path以"//"开头,则直接拼接协议
|
||||||
|
if (path.find("//") == 0) {
|
||||||
|
return protocol + path.substr(2);
|
||||||
|
}
|
||||||
|
string host;
|
||||||
|
size_t pos = 0;
|
||||||
|
if (protocol_end != string::npos) {
|
||||||
|
pos = base_url.find('/', protocol_end + 3);
|
||||||
|
host = base_url.substr(0, pos);
|
||||||
|
if (pos == string::npos) {
|
||||||
|
pos = base_url.size();
|
||||||
|
} else {
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 如果path以"/"开头,则直接拼接协议和主机
|
||||||
|
if (path[0] == '/') {
|
||||||
|
return host + path;
|
||||||
|
}
|
||||||
|
vector<string> path_parts;
|
||||||
|
size_t next_pos = 0;
|
||||||
|
if (!host.empty()) {
|
||||||
|
path_parts.emplace_back(host);
|
||||||
|
}
|
||||||
|
while ((next_pos = base_url.find('/', pos)) != string::npos) {
|
||||||
|
path_parts.emplace_back(base_url.substr(pos, next_pos - pos));
|
||||||
|
pos = next_pos + 1;
|
||||||
|
}
|
||||||
|
pos = 0;
|
||||||
|
while ((next_pos = path.find('/', pos)) != string::npos) {
|
||||||
|
string part = path.substr(pos, next_pos - pos);
|
||||||
|
if (part == "..") {
|
||||||
|
if (!path_parts.empty() && !path_parts.back().empty()) {
|
||||||
|
if (path_parts.size() > 1 || protocol_end == string::npos) {
|
||||||
|
path_parts.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (part != "." && !part.empty()) {
|
||||||
|
path_parts.emplace_back(part);
|
||||||
|
}
|
||||||
|
pos = next_pos + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
string part = path.substr(pos);
|
||||||
|
if (part != ".." && part != "." && !part.empty()) {
|
||||||
|
path_parts.emplace_back(part);
|
||||||
|
}
|
||||||
|
stringstream final_url;
|
||||||
|
for (size_t i = 0; i < path_parts.size(); ++i) {
|
||||||
|
if (i == 0) {
|
||||||
|
final_url << path_parts[i];
|
||||||
|
} else {
|
||||||
|
final_url << '/' << path_parts[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return final_url.str();
|
||||||
|
}
|
||||||
void RtspUrl::parse(const string &strUrl) {
|
void RtspUrl::parse(const string &strUrl) {
|
||||||
auto schema = FindField(strUrl.data(), nullptr, "://");
|
auto schema = FindField(strUrl.data(), nullptr, "://");
|
||||||
bool is_ssl = strcasecmp(schema.data(), "rtsps") == 0;
|
bool is_ssl = strcasecmp(schema.data(), "rtsps") == 0;
|
||||||
@ -238,4 +312,4 @@ static onceToken token([](){
|
|||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}//namespace mediakit
|
}//namespace mediakit
|
||||||
|
@ -105,6 +105,8 @@ public:
|
|||||||
//解析?后面的参数
|
//解析?后面的参数
|
||||||
static StrCaseMap parseArgs(const std::string &str, const char *pair_delim = "&", const char *key_delim = "=");
|
static StrCaseMap parseArgs(const std::string &str, const char *pair_delim = "&", const char *key_delim = "=");
|
||||||
|
|
||||||
|
static std::string merge_url(const std::string &base_url, const std::string &path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string _strMethod;
|
std::string _strMethod;
|
||||||
std::string _strUrl;
|
std::string _strUrl;
|
||||||
|
@ -37,15 +37,7 @@ bool HlsParser::parse(const string &http_url, const string &m3u8) {
|
|||||||
|
|
||||||
if ((_is_m3u8_inner || extinf_dur != 0) && line[0] != '#') {
|
if ((_is_m3u8_inner || extinf_dur != 0) && line[0] != '#') {
|
||||||
segment.duration = extinf_dur;
|
segment.duration = extinf_dur;
|
||||||
if (line.find("http://") == 0 || line.find("https://") == 0) {
|
segment.url = Parser::merge_url(http_url, line);
|
||||||
segment.url = line;
|
|
||||||
} else {
|
|
||||||
if (line.find("/") == 0) {
|
|
||||||
segment.url = http_url.substr(0, http_url.find("/", 8)) + line;
|
|
||||||
} else {
|
|
||||||
segment.url = http_url.substr(0, http_url.rfind("/") + 1) + line;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!_is_m3u8_inner) {
|
if (!_is_m3u8_inner) {
|
||||||
//ts按照先后顺序排序
|
//ts按照先后顺序排序
|
||||||
ts_map.emplace(index++, segment);
|
ts_map.emplace(index++, segment);
|
||||||
|
@ -182,8 +182,8 @@ void HttpClient::onErr(const SockException &ex) {
|
|||||||
|
|
||||||
ssize_t HttpClient::onRecvHeader(const char *data, size_t len) {
|
ssize_t HttpClient::onRecvHeader(const char *data, size_t len) {
|
||||||
_parser.Parse(data);
|
_parser.Parse(data);
|
||||||
if (_parser.Url() == "302" || _parser.Url() == "301") {
|
if (_parser.Url() == "302" || _parser.Url() == "301" || _parser.Url() == "303") {
|
||||||
auto new_url = _parser["Location"];
|
auto new_url = Parser::merge_url(_url, _parser["Location"]);
|
||||||
if (new_url.empty()) {
|
if (new_url.empty()) {
|
||||||
throw invalid_argument("未找到Location字段(跳转url)");
|
throw invalid_argument("未找到Location字段(跳转url)");
|
||||||
}
|
}
|
||||||
@ -206,7 +206,11 @@ ssize_t HttpClient::onRecvHeader(const char *data, size_t len) {
|
|||||||
onResponseBody(data, len);
|
onResponseBody(data, len);
|
||||||
} else {
|
} else {
|
||||||
_total_body_size = _recved_body_size;
|
_total_body_size = _recved_body_size;
|
||||||
onResponseCompleted_l(SockException(Err_success, "success"));
|
if (_recved_body_size > 0) {
|
||||||
|
onResponseCompleted_l(SockException(Err_success, "success"));
|
||||||
|
}else{
|
||||||
|
onResponseCompleted_l(SockException(Err_other, "no body"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
//后续为源源不断的body
|
//后续为源源不断的body
|
||||||
|
Loading…
Reference in New Issue
Block a user