mirror of
https://gitee.com/xia-chu/ZLMediaKit.git
synced 2026-05-06 10:57:50 +08:00
hls直播支持文件根目录设置在http根目录之外
解决hls保存根目录必须和http根目录一致才能播放的问题
This commit is contained in:
parent
b8301bd085
commit
eef858ffd3
@ -17,6 +17,7 @@
|
|||||||
#include "HttpConst.h"
|
#include "HttpConst.h"
|
||||||
#include "HttpSession.h"
|
#include "HttpSession.h"
|
||||||
#include "HttpFileManager.h"
|
#include "HttpFileManager.h"
|
||||||
|
#include "Common/MultiMediaSourceMuxer.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace toolkit;
|
using namespace toolkit;
|
||||||
@ -48,6 +49,8 @@ struct HttpCookieAttachment {
|
|||||||
// 上次鉴权失败信息,为空则上次鉴权成功 [AUTO-TRANSLATED:de48b753]
|
// 上次鉴权失败信息,为空则上次鉴权成功 [AUTO-TRANSLATED:de48b753]
|
||||||
// Last authentication failure information, empty means last authentication succeeded
|
// Last authentication failure information, empty means last authentication succeeded
|
||||||
string _err_msg;
|
string _err_msg;
|
||||||
|
// hls文件根目录
|
||||||
|
string _hls_root_path;
|
||||||
// hls直播时的其他一些信息,主要用于播放器个数计数以及流量计数 [AUTO-TRANSLATED:790de53a]
|
// hls直播时的其他一些信息,主要用于播放器个数计数以及流量计数 [AUTO-TRANSLATED:790de53a]
|
||||||
// Other information during hls live broadcast, mainly used for player count and traffic count
|
// Other information during hls live broadcast, mainly used for player count and traffic count
|
||||||
HlsCookieData::Ptr _hls_data;
|
HlsCookieData::Ptr _hls_data;
|
||||||
@ -315,6 +318,10 @@ static bool emitHlsPlayed(const Parser &parser, const MediaInfo &media_info, con
|
|||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string getUidFromParams(const string ¶ms) {
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断http客户端是否有权限访问文件的逻辑步骤
|
* 判断http客户端是否有权限访问文件的逻辑步骤
|
||||||
* 1、根据http请求头查找cookie,找到进入步骤3
|
* 1、根据http请求头查找cookie,找到进入步骤3
|
||||||
@ -335,7 +342,7 @@ static void canAccessPath(Session &sender, const Parser &parser, const MediaInfo
|
|||||||
const function<void(const string &err_msg, const HttpServerCookie::Ptr &cookie)> &callback) {
|
const function<void(const string &err_msg, const HttpServerCookie::Ptr &cookie)> &callback) {
|
||||||
// 获取用户唯一id [AUTO-TRANSLATED:5b1cf4bf]
|
// 获取用户唯一id [AUTO-TRANSLATED:5b1cf4bf]
|
||||||
// Get the user's unique id
|
// Get the user's unique id
|
||||||
auto uid = parser.params();
|
auto uid = getUidFromParams(parser.params());
|
||||||
auto path = parser.url();
|
auto path = parser.url();
|
||||||
|
|
||||||
// 先根据http头中的cookie字段获取cookie [AUTO-TRANSLATED:155cf682]
|
// 先根据http头中的cookie字段获取cookie [AUTO-TRANSLATED:155cf682]
|
||||||
@ -370,7 +377,7 @@ static void canAccessPath(Session &sender, const Parser &parser, const MediaInfo
|
|||||||
}
|
}
|
||||||
// 上次鉴权失败,但是如果url参数发生变更,那么也重新鉴权下 [AUTO-TRANSLATED:df9bd345]
|
// 上次鉴权失败,但是如果url参数发生变更,那么也重新鉴权下 [AUTO-TRANSLATED:df9bd345]
|
||||||
// Last authentication failed, but if the url parameter changes, then re-authenticate
|
// Last authentication failed, but if the url parameter changes, then re-authenticate
|
||||||
if (parser.params().empty() || parser.params() == cookie->getUid()) {
|
if (parser.params().empty() || getUidFromParams(parser.params()) == cookie->getUid()) {
|
||||||
// url参数未变,或者本来就没有url参数,那么判断本次请求为重复请求,无访问权限 [AUTO-TRANSLATED:f46b4fca]
|
// url参数未变,或者本来就没有url参数,那么判断本次请求为重复请求,无访问权限 [AUTO-TRANSLATED:f46b4fca]
|
||||||
// The url parameter has not changed, or there is no url parameter at all, then determine that the current request is a duplicate request and has no access permission
|
// The url parameter has not changed, or there is no url parameter at all, then determine that the current request is a duplicate request and has no access permission
|
||||||
callback(attach._err_msg, update_cookie ? cookie : nullptr);
|
callback(attach._err_msg, update_cookie ? cookie : nullptr);
|
||||||
@ -419,9 +426,9 @@ static void canAccessPath(Session &sender, const Parser &parser, const MediaInfo
|
|||||||
// hls related information
|
// hls related information
|
||||||
attach->_hls_data = std::make_shared<HlsCookieData>(media_info, strong_session);
|
attach->_hls_data = std::make_shared<HlsCookieData>(media_info, strong_session);
|
||||||
}
|
}
|
||||||
toolkit::Any any;
|
toolkit::Any any;
|
||||||
any.set(std::move(attach));
|
any.set(std::move(attach));
|
||||||
callback(err_msg, HttpCookieManager::Instance().addCookie(kCookieName, uid, life_second, std::move(any)));
|
callback(err_msg, HttpCookieManager::Instance().addCookie(kCookieName, uid, life_second, std::move(any)));
|
||||||
} else {
|
} else {
|
||||||
callback(err_msg, nullptr);
|
callback(err_msg, nullptr);
|
||||||
}
|
}
|
||||||
@ -468,6 +475,8 @@ static string pathCat(const string &a, const string &b){
|
|||||||
return a + '/' + b;
|
return a + '/' + b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static string getFilePath(const Parser &parser,const MediaInfo &media_info, Session *sender, const string &customRootPath = "");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 访问文件
|
* 访问文件
|
||||||
* @param sender 事件触发者
|
* @param sender 事件触发者
|
||||||
@ -481,17 +490,11 @@ static string pathCat(const string &a, const string &b){
|
|||||||
* @param media_info http url information
|
* @param media_info http url information
|
||||||
* @param file_path Absolute file path
|
* @param file_path Absolute file path
|
||||||
* @param cb Callback object
|
* @param cb Callback object
|
||||||
|
|
||||||
* [AUTO-TRANSLATED:2d840fe6]
|
* [AUTO-TRANSLATED:2d840fe6]
|
||||||
*/
|
*/
|
||||||
static void accessFile(Session &sender, const Parser &parser, const MediaInfo &media_info, const string &file_path, const HttpFileManager::invoker &cb) {
|
static void accessFile(Session &sender, const Parser &parser, const MediaInfo &media_info, const string &file_path, const HttpFileManager::invoker &cb) {
|
||||||
bool is_hls = end_with(file_path, kHlsSuffix) || end_with(file_path, kHlsFMP4Suffix);
|
bool is_hls = end_with(file_path, kHlsSuffix) || end_with(file_path, kHlsFMP4Suffix);
|
||||||
if (!is_hls && !File::fileExist(file_path)) {
|
|
||||||
// 文件不存在且不是hls,那么直接返回404 [AUTO-TRANSLATED:7aae578b]
|
|
||||||
// The file does not exist and is not hls, so directly return 404
|
|
||||||
sendNotFound(cb);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (is_hls) {
|
if (is_hls) {
|
||||||
// hls,那么移除掉后缀获取真实的stream_id并且修改协议为HLS [AUTO-TRANSLATED:94b5818a]
|
// hls,那么移除掉后缀获取真实的stream_id并且修改协议为HLS [AUTO-TRANSLATED:94b5818a]
|
||||||
// hls, then remove the suffix to get the real stream_id and change the protocol to HLS
|
// hls, then remove the suffix to get the real stream_id and change the protocol to HLS
|
||||||
@ -552,6 +555,13 @@ static void accessFile(Session &sender, const Parser &parser, const MediaInfo &m
|
|||||||
invoker.responseFile(parser.getHeader(), httpHeader, file_content.empty() ? file_path : file_content, !is_hls && !is_forbid_cache, file_content.empty());
|
invoker.responseFile(parser.getHeader(), httpHeader, file_content.empty() ? file_path : file_content, !is_hls && !is_forbid_cache, file_content.empty());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (cookie) {
|
||||||
|
auto &attach = cookie->getAttach<HttpCookieAttachment>();
|
||||||
|
if (!attach._hls_root_path.empty()) {
|
||||||
|
// 强制替换为真实hls路径
|
||||||
|
const_cast<std::string &>(file_path) = getFilePath(parser, media_info, nullptr, attach._hls_root_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!is_hls || !cookie) {
|
if (!is_hls || !cookie) {
|
||||||
// 不是hls或访问m3u8文件不带cookie, 直接回复文件或404 [AUTO-TRANSLATED:64e5d19b]
|
// 不是hls或访问m3u8文件不带cookie, 直接回复文件或404 [AUTO-TRANSLATED:64e5d19b]
|
||||||
// Not hls or accessing m3u8 files without cookies, directly reply to the file or 404
|
// Not hls or accessing m3u8 files without cookies, directly reply to the file or 404
|
||||||
@ -601,6 +611,10 @@ static void accessFile(Session &sender, const Parser &parser, const MediaInfo &m
|
|||||||
// Reset the MediaSource search timer
|
// Reset the MediaSource search timer
|
||||||
attach._find_src_ticker.resetTime();
|
attach._find_src_ticker.resetTime();
|
||||||
|
|
||||||
|
auto muxer = hls->getMuxer();
|
||||||
|
if (muxer) {
|
||||||
|
attach._hls_root_path = muxer->getOption().hls_save_path;
|
||||||
|
}
|
||||||
// m3u8文件可能不存在, 等待m3u8索引文件按需生成 [AUTO-TRANSLATED:0dbd4df2]
|
// m3u8文件可能不存在, 等待m3u8索引文件按需生成 [AUTO-TRANSLATED:0dbd4df2]
|
||||||
// The m3u8 file may not exist, wait for the m3u8 index file to be generated on demand
|
// The m3u8 file may not exist, wait for the m3u8 index file to be generated on demand
|
||||||
hls->getIndexFile([response_file, file_path, cookie, cb, parser](const string &file) {
|
hls->getIndexFile([response_file, file_path, cookie, cb, parser](const string &file) {
|
||||||
@ -610,13 +624,15 @@ static void accessFile(Session &sender, const Parser &parser, const MediaInfo &m
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static string getFilePath(const Parser &parser,const MediaInfo &media_info, Session &sender) {
|
static string getFilePath(const Parser &parser,const MediaInfo &media_info, Session *sender, const string &customRootPath) {
|
||||||
GET_CONFIG(bool, enableVhost, General::kEnableVhost);
|
GET_CONFIG(bool, enableVhost, General::kEnableVhost);
|
||||||
GET_CONFIG(string, rootPath, Http::kRootPath);
|
GET_CONFIG(string, httpRootPath, Http::kRootPath);
|
||||||
GET_CONFIG_FUNC(StrCaseMap, virtualPathMap, Http::kVirtualPath, [](const string &str) {
|
GET_CONFIG_FUNC(StrCaseMap, virtualPathMap, Http::kVirtualPath, [](const string &str) {
|
||||||
return Parser::parseArgs(str, ";", ",");
|
return Parser::parseArgs(str, ";", ",");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
auto rootPath = customRootPath.empty() ? httpRootPath : customRootPath;
|
||||||
|
|
||||||
string url, path, virtual_app;
|
string url, path, virtual_app;
|
||||||
auto it = virtualPathMap.find(media_info.app);
|
auto it = virtualPathMap.find(media_info.app);
|
||||||
if (it != virtualPathMap.end()) {
|
if (it != virtualPathMap.end()) {
|
||||||
@ -645,10 +661,12 @@ static string getFilePath(const Parser &parser,const MediaInfo &media_info, Sess
|
|||||||
// The accessed http file must not be outside the http root directory
|
// The accessed http file must not be outside the http root directory
|
||||||
throw std::runtime_error("Attempting to access files outside of the http root directory");
|
throw std::runtime_error("Attempting to access files outside of the http root directory");
|
||||||
}
|
}
|
||||||
// 替换url,防止返回的目录索引网页被注入非法内容 [AUTO-TRANSLATED:463ad1b1]
|
if (sender) {
|
||||||
// Replace the url to prevent the returned directory index page from being injected with illegal content
|
// 替换url,防止返回的目录索引网页被注入非法内容 [AUTO-TRANSLATED:463ad1b1]
|
||||||
const_cast<Parser&>(parser).setUrl("/" + virtual_app + ret.substr(http_root.size()));
|
// Replace the url to prevent the returned directory index page from being injected with illegal content
|
||||||
NOTICE_EMIT(BroadcastHttpBeforeAccessArgs, Broadcast::kBroadcastHttpBeforeAccess, parser, ret, sender);
|
const_cast<Parser&>(parser).setUrl("/" + virtual_app + ret.substr(http_root.size()));
|
||||||
|
NOTICE_EMIT(BroadcastHttpBeforeAccessArgs, Broadcast::kBroadcastHttpBeforeAccess, parser, ret, *sender);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -661,14 +679,14 @@ static string getFilePath(const Parser &parser,const MediaInfo &media_info, Sess
|
|||||||
* @param sender Event trigger
|
* @param sender Event trigger
|
||||||
* @param parser http request
|
* @param parser http request
|
||||||
* @param cb Callback object
|
* @param cb Callback object
|
||||||
|
|
||||||
* [AUTO-TRANSLATED:a79c824d]
|
* [AUTO-TRANSLATED:a79c824d]
|
||||||
*/
|
*/
|
||||||
void HttpFileManager::onAccessPath(Session &sender, Parser &parser, const HttpFileManager::invoker &cb) {
|
void HttpFileManager::onAccessPath(Session &sender, Parser &parser, const HttpFileManager::invoker &cb) {
|
||||||
auto fullUrl = "http://" + parser["Host"] + parser.fullUrl();
|
auto fullUrl = "http://" + parser["Host"] + parser.fullUrl();
|
||||||
MediaInfo media_info(fullUrl);
|
MediaInfo media_info(fullUrl);
|
||||||
auto file_path = getFilePath(parser, media_info, sender);
|
auto file_path = getFilePath(parser, media_info, &sender);
|
||||||
if (file_path.size() == 0) {
|
if (file_path.empty()) {
|
||||||
sendNotFound(cb);
|
sendNotFound(cb);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,13 +25,15 @@ namespace mediakit {
|
|||||||
string Recorder::getRecordPath(Recorder::type type, const MediaTuple& tuple, const string &customized_path) {
|
string Recorder::getRecordPath(Recorder::type type, const MediaTuple& tuple, const string &customized_path) {
|
||||||
GET_CONFIG(bool, enableVhost, General::kEnableVhost);
|
GET_CONFIG(bool, enableVhost, General::kEnableVhost);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case Recorder::type_hls_fmp4:
|
||||||
case Recorder::type_hls: {
|
case Recorder::type_hls: {
|
||||||
GET_CONFIG(string, hlsPath, Protocol::kHlsSavePath);
|
GET_CONFIG(string, hlsPath, Protocol::kHlsSavePath);
|
||||||
string m3u8FilePath;
|
string m3u8FilePath;
|
||||||
|
auto tail = type == Recorder::type_hls ? "/hls.m3u8" : "/hls.fmp4.m3u8";
|
||||||
if (enableVhost) {
|
if (enableVhost) {
|
||||||
m3u8FilePath = tuple.shortUrl() + "/hls.m3u8";
|
m3u8FilePath = tuple.shortUrl() + tail;
|
||||||
} else {
|
} else {
|
||||||
m3u8FilePath = tuple.app + "/" + tuple.stream + "/hls.m3u8";
|
m3u8FilePath = tuple.app + "/" + tuple.stream + tail;
|
||||||
}
|
}
|
||||||
//Here we use the customized file path.
|
//Here we use the customized file path.
|
||||||
if (!customized_path.empty()) {
|
if (!customized_path.empty()) {
|
||||||
@ -54,20 +56,6 @@ string Recorder::getRecordPath(Recorder::type type, const MediaTuple& tuple, con
|
|||||||
}
|
}
|
||||||
return File::absolutePath(mp4FilePath, recordPath);
|
return File::absolutePath(mp4FilePath, recordPath);
|
||||||
}
|
}
|
||||||
case Recorder::type_hls_fmp4: {
|
|
||||||
GET_CONFIG(string, hlsPath, Protocol::kHlsSavePath);
|
|
||||||
string m3u8FilePath;
|
|
||||||
if (enableVhost) {
|
|
||||||
m3u8FilePath = tuple.shortUrl() + "/hls.fmp4.m3u8";
|
|
||||||
} else {
|
|
||||||
m3u8FilePath = tuple.app + "/" + tuple.stream + "/hls.fmp4.m3u8";
|
|
||||||
}
|
|
||||||
// Here we use the customized file path.
|
|
||||||
if (!customized_path.empty()) {
|
|
||||||
return File::absolutePath(m3u8FilePath, customized_path);
|
|
||||||
}
|
|
||||||
return File::absolutePath(m3u8FilePath, hlsPath);
|
|
||||||
}
|
|
||||||
default: return "";
|
default: return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user