Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Z
ZLMediaKit
概览
Overview
Details
Activity
Cycle Analytics
版本库
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
问题
0
Issues
0
列表
Board
标记
里程碑
合并请求
0
Merge Requests
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
Snippets
成员
Collapse sidebar
Close sidebar
活动
图像
聊天
创建新问题
作业
提交
Issue Boards
Open sidebar
张翔宇
ZLMediaKit
Commits
f9f9cde2
Commit
f9f9cde2
authored
Dec 27, 2020
by
xiongziliang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
整理webapi、webhook框架代码
parent
781708f0
隐藏空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
229 行增加
和
162 行删除
+229
-162
server/WebApi.cpp
+97
-126
server/WebApi.h
+95
-4
server/WebHook.cpp
+17
-31
server/WebHook.h
+20
-1
没有找到文件。
server/WebApi.cpp
100644 → 100755
查看文件 @
f9f9cde2
...
...
@@ -13,7 +13,6 @@
#include <signal.h>
#include <functional>
#include <unordered_map>
#include "jsoncpp/json.h"
#include "Util/util.h"
#include "Util/logger.h"
#include "Util/onceToken.h"
...
...
@@ -36,20 +35,11 @@
#if defined(ENABLE_RTPPROXY)
#include "Rtp/RtpServer.h"
#endif
using
namespace
Json
;
using
namespace
toolkit
;
using
namespace
mediakit
;
namespace
API
{
typedef
enum
{
Exception
=
-
400
,
//代码抛异常
InvalidArgs
=
-
300
,
//参数不合法
SqlFailed
=
-
200
,
//sql执行失败
AuthFailed
=
-
100
,
//鉴权失败
OtherFailed
=
-
1
,
//业务代码执行失败,
Success
=
0
//执行成功
}
ApiErr
;
#define API_FIELD "api."
const
string
kApiDebug
=
API_FIELD
"apiDebug"
;
const
string
kSecret
=
API_FIELD
"secret"
;
...
...
@@ -64,42 +54,7 @@ static onceToken token([]() {
});
}
//namespace API
class
ApiRetException
:
public
std
::
runtime_error
{
public
:
ApiRetException
(
const
char
*
str
=
"success"
,
int
code
=
API
::
Success
)
:
runtime_error
(
str
){
_code
=
code
;
}
~
ApiRetException
()
=
default
;
int
code
(){
return
_code
;
}
private
:
int
_code
;
};
class
AuthException
:
public
ApiRetException
{
public
:
AuthException
(
const
char
*
str
)
:
ApiRetException
(
str
,
API
::
AuthFailed
){}
~
AuthException
()
=
default
;
};
class
InvalidArgsException
:
public
ApiRetException
{
public
:
InvalidArgsException
(
const
char
*
str
)
:
ApiRetException
(
str
,
API
::
InvalidArgs
){}
~
InvalidArgsException
()
=
default
;
};
class
SuccessException
:
public
ApiRetException
{
public
:
SuccessException
()
:
ApiRetException
(
"success"
,
API
::
Success
){}
~
SuccessException
()
=
default
;
};
#define API_ARGS1 SockInfo &sender,HttpSession::KeyValue &headerIn, HttpSession::KeyValue &headerOut, ApiArgsType &allArgs, Json::Value &val
#define API_ARGS2 API_ARGS1, const HttpSession::HttpResponseInvoker &invoker
#define API_ARGS_VALUE1 sender,headerIn,headerOut,allArgs,val
typedef
map
<
string
,
variant
,
StrCaseCompare
>
ApiArgsType
;
typedef
function
<
void
(
const
Parser
&
parser
,
const
HttpSession
::
HttpResponseInvoker
&
invoker
,
SockInfo
&
sender
)
>
HttpApi
;
using
HttpApi
=
function
<
void
(
const
Parser
&
parser
,
const
HttpSession
::
HttpResponseInvoker
&
invoker
,
SockInfo
&
sender
)
>
;
//http api列表
static
map
<
string
,
HttpApi
>
s_map_api
;
...
...
@@ -119,7 +74,7 @@ static void responseApi(int code, const string &msg, const HttpSession::HttpResp
static
ApiArgsType
getAllArgs
(
const
Parser
&
parser
);
static
HttpApi
toApi
(
const
function
<
void
(
API_ARGS
2
)
>
&
cb
)
{
static
HttpApi
toApi
(
const
function
<
void
(
API_ARGS
_MAP_ASYNC
)
>
&
cb
)
{
return
[
cb
](
const
Parser
&
parser
,
const
HttpSession
::
HttpResponseInvoker
&
invoker
,
SockInfo
&
sender
)
{
GET_CONFIG
(
string
,
charSet
,
Http
::
kCharSet
);
HttpSession
::
KeyValue
headerOut
;
...
...
@@ -128,23 +83,62 @@ static HttpApi toApi(const function<void(API_ARGS2)> &cb) {
Json
::
Value
val
;
val
[
"code"
]
=
API
::
Success
;
//参数解析成map
auto
args
=
getAllArgs
(
parser
);
cb
(
sender
,
parser
.
getHeader
(),
headerOut
,
args
,
val
,
invoker
);
};
}
static
HttpApi
toApi
(
const
function
<
void
(
API_ARGS
1
)
>
&
cb
)
{
return
toApi
([
cb
](
API_ARGS
2
)
{
cb
(
API_ARGS_VALUE
1
);
static
HttpApi
toApi
(
const
function
<
void
(
API_ARGS
_MAP
)
>
&
cb
)
{
return
toApi
([
cb
](
API_ARGS
_MAP_ASYNC
)
{
cb
(
API_ARGS_VALUE
);
invoker
(
"200 OK"
,
headerOut
,
val
.
toStyledString
());
});
}
template
<
typename
FUNC
>
static
void
api_regist
(
const
string
&
api_path
,
FUNC
&&
func
)
{
s_map_api
.
emplace
(
api_path
,
toApi
(
std
::
move
(
func
)));
static
HttpApi
toApi
(
const
function
<
void
(
API_ARGS_JSON_ASYNC
)
>
&
cb
)
{
return
[
cb
](
const
Parser
&
parser
,
const
HttpSession
::
HttpResponseInvoker
&
invoker
,
SockInfo
&
sender
)
{
GET_CONFIG
(
string
,
charSet
,
Http
::
kCharSet
);
HttpSession
::
KeyValue
headerOut
;
headerOut
[
"Content-Type"
]
=
string
(
"application/json; charset="
)
+
charSet
;
Json
::
Value
out
;
out
[
"code"
]
=
API
::
Success
;
if
(
parser
[
"Content-Type"
].
find
(
"application/json"
)
==
string
::
npos
)
{
throw
InvalidArgsException
(
"该接口只支持json格式的请求"
);
}
//参数解析成json对象然后处理
Json
::
Value
in
;
Json
::
Reader
reader
;
reader
.
parse
(
parser
.
Content
(),
in
);
cb
(
sender
,
parser
.
getHeader
(),
headerOut
,
in
,
out
,
invoker
);
};
}
static
HttpApi
toApi
(
const
function
<
void
(
API_ARGS_JSON
)
>
&
cb
)
{
return
toApi
([
cb
](
API_ARGS_JSON_ASYNC
)
{
cb
(
API_ARGS_VALUE
);
invoker
(
"200 OK"
,
headerOut
,
val
.
toStyledString
());
});
}
void
api_regist
(
const
string
&
api_path
,
const
function
<
void
(
API_ARGS_MAP
)
>
&
func
)
{
s_map_api
.
emplace
(
api_path
,
toApi
(
func
));
}
void
api_regist
(
const
string
&
api_path
,
const
function
<
void
(
API_ARGS_MAP_ASYNC
)
>
&
func
)
{
s_map_api
.
emplace
(
api_path
,
toApi
(
func
));
}
void
api_regist
(
const
string
&
api_path
,
const
function
<
void
(
API_ARGS_JSON
)
>
&
func
)
{
s_map_api
.
emplace
(
api_path
,
toApi
(
func
));
}
void
api_regist
(
const
string
&
api_path
,
const
function
<
void
(
API_ARGS_JSON_ASYNC
)
>
&
func
)
{
s_map_api
.
emplace
(
api_path
,
toApi
(
func
));
}
//获取HTTP请求中url参数、content参数
static
ApiArgsType
getAllArgs
(
const
Parser
&
parser
)
{
...
...
@@ -233,29 +227,6 @@ static inline void addHttpListener(){
});
}
template
<
typename
Args
,
typename
First
>
bool
checkArgs
(
Args
&&
args
,
First
&&
first
){
return
!
args
[
first
].
empty
();
}
template
<
typename
Args
,
typename
First
,
typename
...
KeyTypes
>
bool
checkArgs
(
Args
&&
args
,
First
&&
first
,
KeyTypes
&&
...
keys
){
return
!
args
[
first
].
empty
()
&&
checkArgs
(
std
::
forward
<
Args
>
(
args
),
std
::
forward
<
KeyTypes
>
(
keys
)...);
}
#define CHECK_ARGS(...) \
if(!checkArgs(allArgs,##__VA_ARGS__)){ \
throw InvalidArgsException("缺少必要参数:" #__VA_ARGS__); \
}
#define CHECK_SECRET() \
if(sender.get_peer_ip() != "127.0.0.1"){ \
CHECK_ARGS("secret"); \
if(api_secret != allArgs["secret"]){ \
throw AuthException("secret错误"); \
} \
}
//拉流代理器列表
static
unordered_map
<
string
,
PlayerProxy
::
Ptr
>
s_proxyMap
;
static
recursive_mutex
s_proxyMapMtx
;
...
...
@@ -285,7 +256,7 @@ void installWebApi() {
//获取线程负载
//测试url http://127.0.0.1/index/api/getThreadsLoad
api_regist
(
"/index/api/getThreadsLoad"
,[](
API_ARGS
2
){
api_regist
(
"/index/api/getThreadsLoad"
,[](
API_ARGS
_MAP_ASYNC
){
EventPollerPool
::
Instance
().
getExecutorDelay
([
invoker
,
headerOut
](
const
vector
<
int
>
&
vecDelay
)
{
Value
val
;
auto
vec
=
EventPollerPool
::
Instance
().
getExecutorLoad
();
...
...
@@ -303,7 +274,7 @@ void installWebApi() {
//获取后台工作线程负载
//测试url http://127.0.0.1/index/api/getWorkThreadsLoad
api_regist
(
"/index/api/getWorkThreadsLoad"
,
[](
API_ARGS
2
){
api_regist
(
"/index/api/getWorkThreadsLoad"
,
[](
API_ARGS
_MAP_ASYNC
){
WorkThreadPool
::
Instance
().
getExecutorDelay
([
invoker
,
headerOut
](
const
vector
<
int
>
&
vecDelay
)
{
Value
val
;
auto
vec
=
WorkThreadPool
::
Instance
().
getExecutorLoad
();
...
...
@@ -321,7 +292,7 @@ void installWebApi() {
//获取服务器配置
//测试url http://127.0.0.1/index/api/getServerConfig
api_regist
(
"/index/api/getServerConfig"
,[](
API_ARGS
1
){
api_regist
(
"/index/api/getServerConfig"
,[](
API_ARGS
_MAP
){
CHECK_SECRET
();
Value
obj
;
for
(
auto
&
pr
:
mINI
::
Instance
())
{
...
...
@@ -333,7 +304,7 @@ void installWebApi() {
//设置服务器配置
//测试url(比如关闭http api调试) http://127.0.0.1/index/api/setServerConfig?api.apiDebug=0
//你也可以通过http post方式传参,可以通过application/x-www-form-urlencoded或application/json方式传参
api_regist
(
"/index/api/setServerConfig"
,[](
API_ARGS
1
){
api_regist
(
"/index/api/setServerConfig"
,[](
API_ARGS
_MAP
){
CHECK_SECRET
();
auto
&
ini
=
mINI
::
Instance
();
int
changed
=
API
::
Success
;
...
...
@@ -357,7 +328,7 @@ void installWebApi() {
});
static
auto
s_get_api_list
=
[](
API_ARGS
1
){
static
auto
s_get_api_list
=
[](
API_ARGS
_MAP
){
CHECK_SECRET
();
for
(
auto
&
pr
:
s_map_api
){
val
[
"data"
].
append
(
pr
.
first
);
...
...
@@ -366,20 +337,20 @@ void installWebApi() {
//获取服务器api列表
//测试url http://127.0.0.1/index/api/getApiList
api_regist
(
"/index/api/getApiList"
,[](
API_ARGS
1
){
s_get_api_list
(
API_ARGS_VALUE
1
);
api_regist
(
"/index/api/getApiList"
,[](
API_ARGS
_MAP
){
s_get_api_list
(
API_ARGS_VALUE
);
});
//获取服务器api列表
//测试url http://127.0.0.1/index/
api_regist
(
"/index/"
,[](
API_ARGS
1
){
s_get_api_list
(
API_ARGS_VALUE
1
);
api_regist
(
"/index/"
,[](
API_ARGS
_MAP
){
s_get_api_list
(
API_ARGS_VALUE
);
});
#if !defined(_WIN32)
//重启服务器,只有Daemon方式才能重启,否则是直接关闭!
//测试url http://127.0.0.1/index/api/restartServer
api_regist
(
"/index/api/restartServer"
,[](
API_ARGS
1
){
api_regist
(
"/index/api/restartServer"
,[](
API_ARGS
_MAP
){
CHECK_SECRET
();
EventPollerPool
::
Instance
().
getPoller
()
->
doDelayTask
(
1000
,[](){
//尝试正常退出
...
...
@@ -457,7 +428,7 @@ void installWebApi() {
//测试url0(获取所有流) http://127.0.0.1/index/api/getMediaList
//测试url1(获取虚拟主机为"__defaultVost__"的流) http://127.0.0.1/index/api/getMediaList?vhost=__defaultVost__
//测试url2(获取rtsp类型的流) http://127.0.0.1/index/api/getMediaList?schema=rtsp
api_regist
(
"/index/api/getMediaList"
,[](
API_ARGS
1
){
api_regist
(
"/index/api/getMediaList"
,[](
API_ARGS
_MAP
){
CHECK_SECRET
();
//获取所有MediaSource列表
MediaSource
::
for_each_media
([
&
](
const
MediaSource
::
Ptr
&
media
){
...
...
@@ -475,14 +446,14 @@ void installWebApi() {
});
//测试url http://127.0.0.1/index/api/isMediaOnline?schema=rtsp&vhost=__defaultVhost__&app=live&stream=obs
api_regist
(
"/index/api/isMediaOnline"
,[](
API_ARGS
1
){
api_regist
(
"/index/api/isMediaOnline"
,[](
API_ARGS
_MAP
){
CHECK_SECRET
();
CHECK_ARGS
(
"schema"
,
"vhost"
,
"app"
,
"stream"
);
val
[
"online"
]
=
(
bool
)
(
MediaSource
::
find
(
allArgs
[
"schema"
],
allArgs
[
"vhost"
],
allArgs
[
"app"
],
allArgs
[
"stream"
]));
});
//测试url http://127.0.0.1/index/api/getMediaInfo?schema=rtsp&vhost=__defaultVhost__&app=live&stream=obs
api_regist
(
"/index/api/getMediaInfo"
,[](
API_ARGS
1
){
api_regist
(
"/index/api/getMediaInfo"
,[](
API_ARGS
_MAP
){
CHECK_SECRET
();
CHECK_ARGS
(
"schema"
,
"vhost"
,
"app"
,
"stream"
);
auto
src
=
MediaSource
::
find
(
allArgs
[
"schema"
],
allArgs
[
"vhost"
],
allArgs
[
"app"
],
allArgs
[
"stream"
]);
...
...
@@ -497,7 +468,7 @@ void installWebApi() {
//主动关断流,包括关断拉流、推流
//测试url http://127.0.0.1/index/api/close_stream?schema=rtsp&vhost=__defaultVhost__&app=live&stream=obs&force=1
api_regist
(
"/index/api/close_stream"
,[](
API_ARGS
1
){
api_regist
(
"/index/api/close_stream"
,[](
API_ARGS
_MAP
){
CHECK_SECRET
();
CHECK_ARGS
(
"schema"
,
"vhost"
,
"app"
,
"stream"
);
//踢掉推流器
...
...
@@ -519,7 +490,7 @@ void installWebApi() {
//批量主动关断流,包括关断拉流、推流
//测试url http://127.0.0.1/index/api/close_streams?schema=rtsp&vhost=__defaultVhost__&app=live&stream=obs&force=1
api_regist
(
"/index/api/close_streams"
,[](
API_ARGS
1
){
api_regist
(
"/index/api/close_streams"
,[](
API_ARGS
_MAP
){
CHECK_SECRET
();
//筛选命中个数
int
count_hit
=
0
;
...
...
@@ -555,7 +526,7 @@ void installWebApi() {
//获取所有TcpSession列表信息
//可以根据本地端口和远端ip来筛选
//测试url(筛选某端口下的tcp会话) http://127.0.0.1/index/api/getAllSession?local_port=1935
api_regist
(
"/index/api/getAllSession"
,[](
API_ARGS
1
){
api_regist
(
"/index/api/getAllSession"
,[](
API_ARGS
_MAP
){
CHECK_SECRET
();
Value
jsession
;
uint16_t
local_port
=
allArgs
[
"local_port"
].
as
<
uint16_t
>
();
...
...
@@ -580,7 +551,7 @@ void installWebApi() {
//断开tcp连接,比如说可以断开rtsp、rtmp播放器等
//测试url http://127.0.0.1/index/api/kick_session?id=123456
api_regist
(
"/index/api/kick_session"
,[](
API_ARGS
1
){
api_regist
(
"/index/api/kick_session"
,[](
API_ARGS
_MAP
){
CHECK_SECRET
();
CHECK_ARGS
(
"id"
);
//踢掉tcp会话
...
...
@@ -594,7 +565,7 @@ void installWebApi() {
//批量断开tcp连接,比如说可以断开rtsp、rtmp播放器等
//测试url http://127.0.0.1/index/api/kick_sessions?local_port=1935
api_regist
(
"/index/api/kick_sessions"
,[](
API_ARGS
1
){
api_regist
(
"/index/api/kick_sessions"
,[](
API_ARGS
_MAP
){
CHECK_SECRET
();
uint16_t
local_port
=
allArgs
[
"local_port"
].
as
<
uint16_t
>
();
string
&
peer_ip
=
allArgs
[
"peer_ip"
];
...
...
@@ -658,7 +629,7 @@ void installWebApi() {
//动态添加rtsp/rtmp拉流代理
//测试url http://127.0.0.1/index/api/addStreamProxy?vhost=__defaultVhost__&app=proxy&enable_rtsp=1&enable_rtmp=1&stream=0&url=rtmp://127.0.0.1/live/obs
api_regist
(
"/index/api/addStreamProxy"
,[](
API_ARGS
2
){
api_regist
(
"/index/api/addStreamProxy"
,[](
API_ARGS
_MAP_ASYNC
){
CHECK_SECRET
();
CHECK_ARGS
(
"vhost"
,
"app"
,
"stream"
,
"url"
);
addStreamProxy
(
allArgs
[
"vhost"
],
...
...
@@ -681,7 +652,7 @@ void installWebApi() {
//关闭拉流代理
//测试url http://127.0.0.1/index/api/delStreamProxy?key=__defaultVhost__/proxy/0
api_regist
(
"/index/api/delStreamProxy"
,[](
API_ARGS
1
){
api_regist
(
"/index/api/delStreamProxy"
,[](
API_ARGS
_MAP
){
CHECK_SECRET
();
CHECK_ARGS
(
"key"
);
lock_guard
<
recursive_mutex
>
lck
(
s_proxyMapMtx
);
...
...
@@ -721,7 +692,7 @@ void installWebApi() {
//动态添加rtsp/rtmp拉流代理
//测试url http://127.0.0.1/index/api/addFFmpegSource?src_url=http://live.hkstv.hk.lxdns.com/live/hks2/playlist.m3u8&dst_url=rtmp://127.0.0.1/live/hks2&timeout_ms=10000
api_regist
(
"/index/api/addFFmpegSource"
,[](
API_ARGS
2
){
api_regist
(
"/index/api/addFFmpegSource"
,[](
API_ARGS
_MAP_ASYNC
){
CHECK_SECRET
();
CHECK_ARGS
(
"src_url"
,
"dst_url"
,
"timeout_ms"
);
auto
src_url
=
allArgs
[
"src_url"
];
...
...
@@ -744,7 +715,7 @@ void installWebApi() {
//关闭拉流代理
//测试url http://127.0.0.1/index/api/delFFmepgSource?key=key
api_regist
(
"/index/api/delFFmpegSource"
,[](
API_ARGS
1
){
api_regist
(
"/index/api/delFFmpegSource"
,[](
API_ARGS
_MAP
){
CHECK_SECRET
();
CHECK_ARGS
(
"key"
);
lock_guard
<
decltype
(
s_ffmpegMapMtx
)
>
lck
(
s_ffmpegMapMtx
);
...
...
@@ -753,13 +724,13 @@ void installWebApi() {
//新增http api下载可执行程序文件接口
//测试url http://127.0.0.1/index/api/downloadBin
api_regist
(
"/index/api/downloadBin"
,[](
API_ARGS
2
){
api_regist
(
"/index/api/downloadBin"
,[](
API_ARGS
_MAP_ASYNC
){
CHECK_SECRET
();
invoker
.
responseFile
(
headerIn
,
StrCaseMap
(),
exePath
());
});
#if defined(ENABLE_RTPPROXY)
api_regist
(
"/index/api/getRtpInfo"
,[](
API_ARGS
1
){
api_regist
(
"/index/api/getRtpInfo"
,[](
API_ARGS
_MAP
){
CHECK_SECRET
();
CHECK_ARGS
(
"stream_id"
);
...
...
@@ -775,7 +746,7 @@ void installWebApi() {
val
[
"local_ip"
]
=
process
->
get_local_ip
();
});
api_regist
(
"/index/api/openRtpServer"
,[](
API_ARGS
1
){
api_regist
(
"/index/api/openRtpServer"
,[](
API_ARGS
_MAP
){
CHECK_SECRET
();
CHECK_ARGS
(
"port"
,
"enable_tcp"
,
"stream_id"
);
...
...
@@ -801,7 +772,7 @@ void installWebApi() {
val
[
"port"
]
=
server
->
getPort
();
});
api_regist
(
"/index/api/closeRtpServer"
,[](
API_ARGS
1
){
api_regist
(
"/index/api/closeRtpServer"
,[](
API_ARGS
_MAP
){
CHECK_SECRET
();
CHECK_ARGS
(
"stream_id"
);
...
...
@@ -816,7 +787,7 @@ void installWebApi() {
val
[
"hit"
]
=
1
;
});
api_regist
(
"/index/api/listRtpServer"
,[](
API_ARGS
1
){
api_regist
(
"/index/api/listRtpServer"
,[](
API_ARGS
_MAP
){
CHECK_SECRET
();
lock_guard
<
recursive_mutex
>
lck
(
s_rtpServerMapMtx
);
...
...
@@ -828,7 +799,7 @@ void installWebApi() {
}
});
api_regist
(
"/index/api/startSendRtp"
,[](
API_ARGS
2
){
api_regist
(
"/index/api/startSendRtp"
,[](
API_ARGS
_MAP_ASYNC
){
CHECK_SECRET
();
CHECK_ARGS
(
"vhost"
,
"app"
,
"stream"
,
"ssrc"
,
"dst_url"
,
"dst_port"
,
"is_udp"
);
...
...
@@ -847,7 +818,7 @@ void installWebApi() {
});
});
api_regist
(
"/index/api/stopSendRtp"
,[](
API_ARGS
1
){
api_regist
(
"/index/api/stopSendRtp"
,[](
API_ARGS
_MAP
){
CHECK_SECRET
();
CHECK_ARGS
(
"vhost"
,
"app"
,
"stream"
);
...
...
@@ -862,7 +833,7 @@ void installWebApi() {
}
});
api_regist
(
"/index/api/pauseRtpCheck"
,
[](
API_ARGS
1
)
{
api_regist
(
"/index/api/pauseRtpCheck"
,
[](
API_ARGS
_MAP
)
{
CHECK_SECRET
();
CHECK_ARGS
(
"stream_id"
);
//只是暂停流的检查,流媒体服务器做为流负载服务,收流就转发,RTSP/RTMP有自己暂停协议
...
...
@@ -877,7 +848,7 @@ void installWebApi() {
val
[
"hit"
]
=
1
;
});
api_regist
(
"/index/api/resumeRtpCheck"
,
[](
API_ARGS
1
)
{
api_regist
(
"/index/api/resumeRtpCheck"
,
[](
API_ARGS
_MAP
)
{
CHECK_SECRET
();
CHECK_ARGS
(
"stream_id"
);
...
...
@@ -895,7 +866,7 @@ void installWebApi() {
#endif//ENABLE_RTPPROXY
// 开始录制hls或MP4
api_regist
(
"/index/api/startRecord"
,[](
API_ARGS
1
){
api_regist
(
"/index/api/startRecord"
,[](
API_ARGS
_MAP
){
CHECK_SECRET
();
CHECK_ARGS
(
"type"
,
"vhost"
,
"app"
,
"stream"
);
auto
result
=
Recorder
::
startRecord
((
Recorder
::
type
)
allArgs
[
"type"
].
as
<
int
>
(),
...
...
@@ -909,7 +880,7 @@ void installWebApi() {
});
// 停止录制hls或MP4
api_regist
(
"/index/api/stopRecord"
,[](
API_ARGS
1
){
api_regist
(
"/index/api/stopRecord"
,[](
API_ARGS
_MAP
){
CHECK_SECRET
();
CHECK_ARGS
(
"type"
,
"vhost"
,
"app"
,
"stream"
);
auto
result
=
Recorder
::
stopRecord
((
Recorder
::
type
)
allArgs
[
"type"
].
as
<
int
>
(),
...
...
@@ -922,7 +893,7 @@ void installWebApi() {
});
// 获取hls或MP4录制状态
api_regist
(
"/index/api/isRecording"
,[](
API_ARGS
1
){
api_regist
(
"/index/api/isRecording"
,[](
API_ARGS
_MAP
){
CHECK_SECRET
();
CHECK_ARGS
(
"type"
,
"vhost"
,
"app"
,
"stream"
);
val
[
"status"
]
=
Recorder
::
isRecording
((
Recorder
::
type
)
allArgs
[
"type"
].
as
<
int
>
(),
...
...
@@ -933,7 +904,7 @@ void installWebApi() {
//获取录像文件夹列表或mp4文件列表
//http://127.0.0.1/index/api/getMp4RecordFile?vhost=__defaultVhost__&app=live&stream=ss&period=2020-01
api_regist
(
"/index/api/getMp4RecordFile"
,
[](
API_ARGS
1
){
api_regist
(
"/index/api/getMp4RecordFile"
,
[](
API_ARGS
_MAP
){
CHECK_SECRET
();
CHECK_ARGS
(
"vhost"
,
"app"
,
"stream"
);
auto
record_path
=
Recorder
::
getRecordPath
(
Recorder
::
type_mp4
,
allArgs
[
"vhost"
],
allArgs
[
"app"
],
allArgs
[
"stream"
]);
...
...
@@ -988,7 +959,7 @@ void installWebApi() {
//获取截图缓存或者实时截图
//http://127.0.0.1/index/api/getSnap?url=rtmp://127.0.0.1/record/robot.mp4&timeout_sec=10&expire_sec=3
api_regist
(
"/index/api/getSnap"
,
[](
API_ARGS
2
){
api_regist
(
"/index/api/getSnap"
,
[](
API_ARGS
_MAP_ASYNC
){
CHECK_SECRET
();
CHECK_ARGS
(
"url"
,
"timeout_sec"
,
"expire_sec"
);
GET_CONFIG
(
string
,
snap_root
,
API
::
kSnapRoot
);
...
...
@@ -1051,7 +1022,7 @@ void installWebApi() {
});
////////////以下是注册的Hook API////////////
api_regist
(
"/index/hook/on_publish"
,[](
API_ARGS
1
){
api_regist
(
"/index/hook/on_publish"
,[](
API_ARGS
_MAP
){
//开始推流事件
//转换成rtsp或rtmp
val
[
"enableRtxp"
]
=
true
;
...
...
@@ -1061,21 +1032,21 @@ void installWebApi() {
val
[
"enableMP4"
]
=
false
;
});
api_regist
(
"/index/hook/on_play"
,[](
API_ARGS
1
){
api_regist
(
"/index/hook/on_play"
,[](
API_ARGS
_MAP
){
//开始播放事件
});
api_regist
(
"/index/hook/on_flow_report"
,[](
API_ARGS
1
){
api_regist
(
"/index/hook/on_flow_report"
,[](
API_ARGS
_MAP
){
//流量统计hook api
});
api_regist
(
"/index/hook/on_rtsp_realm"
,[](
API_ARGS
1
){
api_regist
(
"/index/hook/on_rtsp_realm"
,[](
API_ARGS
_MAP
){
//rtsp是否需要鉴权,默认需要鉴权
val
[
"code"
]
=
API
::
Success
;
val
[
"realm"
]
=
"zlmediakit_reaml"
;
});
api_regist
(
"/index/hook/on_rtsp_auth"
,[](
API_ARGS
1
){
api_regist
(
"/index/hook/on_rtsp_auth"
,[](
API_ARGS
_MAP
){
//rtsp鉴权密码,密码等于用户名
//rtsp可以有双重鉴权!后面还会触发on_play事件
CHECK_ARGS
(
"user_name"
);
...
...
@@ -1084,13 +1055,13 @@ void installWebApi() {
val
[
"passwd"
]
=
allArgs
[
"user_name"
].
data
();
});
api_regist
(
"/index/hook/on_stream_changed"
,[](
API_ARGS
1
){
api_regist
(
"/index/hook/on_stream_changed"
,[](
API_ARGS
_MAP
){
//媒体注册或反注册事件
});
#if !defined(_WIN32)
api_regist
(
"/index/hook/on_stream_not_found_ffmpeg"
,[](
API_ARGS
2
){
api_regist
(
"/index/hook/on_stream_not_found_ffmpeg"
,[](
API_ARGS
_MAP_ASYNC
){
//媒体未找到事件,我们都及时拉流hks作为替代品,目的是为了测试按需拉流
CHECK_SECRET
();
CHECK_ARGS
(
"vhost"
,
"app"
,
"stream"
);
...
...
@@ -1122,7 +1093,7 @@ void installWebApi() {
});
#endif//!defined(_WIN32)
api_regist
(
"/index/hook/on_stream_not_found"
,[](
API_ARGS
2
){
api_regist
(
"/index/hook/on_stream_not_found"
,[](
API_ARGS
_MAP_ASYNC
){
//媒体未找到事件,我们都及时拉流hks作为替代品,目的是为了测试按需拉流
CHECK_SECRET
();
CHECK_ARGS
(
"vhost"
,
"app"
,
"stream"
);
...
...
@@ -1146,15 +1117,15 @@ void installWebApi() {
});
});
api_regist
(
"/index/hook/on_record_mp4"
,[](
API_ARGS
1
){
api_regist
(
"/index/hook/on_record_mp4"
,[](
API_ARGS
_MAP
){
//录制mp4分片完毕事件
});
api_regist
(
"/index/hook/on_shell_login"
,[](
API_ARGS
1
){
api_regist
(
"/index/hook/on_shell_login"
,[](
API_ARGS
_MAP
){
//shell登录调试事件
});
api_regist
(
"/index/hook/on_stream_none_reader"
,[](
API_ARGS
1
){
api_regist
(
"/index/hook/on_stream_none_reader"
,[](
API_ARGS
_MAP
){
//无人观看流默认关闭
val
[
"close"
]
=
true
;
});
...
...
@@ -1164,7 +1135,7 @@ void installWebApi() {
return
true
;
};
api_regist
(
"/index/hook/on_http_access"
,[](
API_ARGS
1
){
api_regist
(
"/index/hook/on_http_access"
,[](
API_ARGS
_MAP
){
//在这里根据allArgs["params"](url参数)来判断该http客户端是否有权限访问该文件
if
(
!
checkAccess
(
allArgs
[
"params"
])){
//无访问权限
...
...
@@ -1185,7 +1156,7 @@ void installWebApi() {
});
api_regist
(
"/index/hook/on_server_started"
,[](
API_ARGS
1
){
api_regist
(
"/index/hook/on_server_started"
,[](
API_ARGS
_MAP
){
//服务器重启报告
});
}
...
...
server/WebApi.h
100644 → 100755
查看文件 @
f9f9cde2
...
...
@@ -12,10 +12,21 @@
#define ZLMEDIAKIT_WEBAPI_H
#include <string>
#include <functional>
#include "jsoncpp/json.h"
#include "Common/Parser.h"
#include "Network/Socket.h"
#include "Http/HttpSession.h"
using
namespace
std
;
using
namespace
Json
;
using
namespace
toolkit
;
using
namespace
mediakit
;
namespace
mediakit
{
//配置文件路径
extern
string
g_ini_file
;
namespace
mediakit
{
////////////RTSP服务器配置///////////
namespace
Rtsp
{
extern
const
string
kPort
;
...
...
@@ -25,13 +36,93 @@ extern const string kPort;
namespace
Rtmp
{
extern
const
string
kPort
;
}
//namespace RTMP
}
// namespace mediakit
namespace
API
{
typedef
enum
{
NotFound
=
-
500
,
//未找到
Exception
=
-
400
,
//代码抛异常
InvalidArgs
=
-
300
,
//参数不合法
SqlFailed
=
-
200
,
//sql执行失败
AuthFailed
=
-
100
,
//鉴权失败
OtherFailed
=
-
1
,
//业务代码执行失败,
Success
=
0
//执行成功
}
ApiErr
;
}
//namespace API
class
ApiRetException
:
public
std
::
runtime_error
{
public
:
ApiRetException
(
const
char
*
str
=
"success"
,
int
code
=
API
::
Success
)
:
runtime_error
(
str
){
_code
=
code
;
}
~
ApiRetException
()
=
default
;
int
code
(){
return
_code
;
}
private
:
int
_code
;
};
class
AuthException
:
public
ApiRetException
{
public
:
AuthException
(
const
char
*
str
)
:
ApiRetException
(
str
,
API
::
AuthFailed
){}
~
AuthException
()
=
default
;
};
class
InvalidArgsException
:
public
ApiRetException
{
public
:
InvalidArgsException
(
const
char
*
str
)
:
ApiRetException
(
str
,
API
::
InvalidArgs
){}
~
InvalidArgsException
()
=
default
;
};
class
SuccessException
:
public
ApiRetException
{
public
:
SuccessException
()
:
ApiRetException
(
"success"
,
API
::
Success
){}
~
SuccessException
()
=
default
;
};
using
ApiArgsType
=
map
<
string
,
variant
,
StrCaseCompare
>
;
#define API_ARGS_MAP SockInfo &sender, HttpSession::KeyValue &headerIn, HttpSession::KeyValue &headerOut, ApiArgsType &allArgs, Json::Value &val
#define API_ARGS_MAP_ASYNC API_ARGS_MAP, const HttpSession::HttpResponseInvoker &invoker
#define API_ARGS_JSON SockInfo &sender, HttpSession::KeyValue &headerIn, HttpSession::KeyValue &headerOut, Json::Value &allArgs, Json::Value &val
#define API_ARGS_JSON_ASYNC API_ARGS_JSON, const HttpSession::HttpResponseInvoker &invoker
#define API_ARGS_VALUE sender, headerIn, headerOut, allArgs, val
//注册http请求参数是map<string, variant, StrCaseCompare>类型的http api
void
api_regist
(
const
string
&
api_path
,
const
function
<
void
(
API_ARGS_MAP
)
>
&
func
);
//注册http请求参数是map<string, variant, StrCaseCompare>类型,但是可以异步回复的的http api
void
api_regist
(
const
string
&
api_path
,
const
function
<
void
(
API_ARGS_MAP_ASYNC
)
>
&
func
);
//注册http请求参数是Json::Value类型的http api(可以支持多级嵌套的json参数对象)
void
api_regist
(
const
string
&
api_path
,
const
function
<
void
(
API_ARGS_JSON
)
>
&
func
);
//注册http请求参数是Json::Value类型,但是可以异步回复的的http api
void
api_regist
(
const
string
&
api_path
,
const
function
<
void
(
API_ARGS_JSON_ASYNC
)
>
&
func
);
template
<
typename
Args
,
typename
First
>
bool
checkArgs
(
Args
&&
args
,
First
&&
first
)
{
return
!
args
[
first
].
empty
();
}
template
<
typename
Args
,
typename
First
,
typename
...
KeyTypes
>
bool
checkArgs
(
Args
&&
args
,
First
&&
first
,
KeyTypes
&&
...
keys
)
{
return
!
args
[
first
].
empty
()
&&
checkArgs
(
std
::
forward
<
Args
>
(
args
),
std
::
forward
<
KeyTypes
>
(
keys
)...);
}
//检查http参数是否为空的宏
#define CHECK_ARGS(...) \
if(!checkArgs(allArgs,##__VA_ARGS__)){ \
throw InvalidArgsException("缺少必要参数:" #__VA_ARGS__); \
}
//检查http参数中是否附带secret密钥的宏,127.0.0.1的ip不检查密钥
#define CHECK_SECRET() \
if(sender.get_peer_ip() != "127.0.0.1"){ \
CHECK_ARGS("secret"); \
if(api_secret != allArgs["secret"]){ \
throw AuthException("secret错误"); \
} \
}
void
installWebApi
();
void
unInstallWebApi
();
//配置文件路径
extern
string
g_ini_file
;
#endif //ZLMEDIAKIT_WEBAPI_H
server/WebHook.cpp
100644 → 100755
查看文件 @
f9f9cde2
...
...
@@ -9,9 +9,7 @@
*/
#include <sstream>
#include "jsoncpp/json.h"
#include "Util/logger.h"
#include "Util/util.h"
#include "Util/onceToken.h"
#include "Util/NoticeCenter.h"
#include "Common/config.h"
...
...
@@ -22,21 +20,9 @@
#include "Http/HttpSession.h"
#include "WebHook.h"
using
namespace
Json
;
using
namespace
toolkit
;
using
namespace
mediakit
;
//支持json或urlencoded方式传输参数
#define JSON_ARGS
#ifdef JSON_ARGS
typedef
Value
ArgsType
;
#else
typedef
HttpArgs
ArgsType
;
#endif
namespace
Hook
{
#define HOOK_FIELD "hook."
...
...
@@ -126,35 +112,35 @@ const char *getContentType(const HttpArgs &value){
return
"application/x-www-form-urlencoded"
;
}
static
void
do_http_hook
(
const
string
&
url
,
const
ArgsType
&
body
,
const
function
<
void
(
const
Value
&
,
const
string
&
)
>
&
fun
){
GET_CONFIG
(
string
,
mediaServerId
,
General
::
kMediaServerId
);
const_cast
<
ArgsType
&>
(
body
)[
"mediaServerId"
]
=
mediaServerId
;
void
do_http_hook
(
const
string
&
url
,
const
ArgsType
&
body
,
const
function
<
void
(
const
Value
&
,
const
string
&
)
>
&
func
){
GET_CONFIG
(
string
,
mediaServerId
,
General
::
kMediaServerId
);
GET_CONFIG
(
float
,
hook_timeoutSec
,
Hook
::
kTimeoutSec
)
;
GET_CONFIG
(
float
,
hook_timeoutSec
,
Hook
::
kTimeoutSec
)
;
const_cast
<
ArgsType
&>
(
body
)[
"mediaServerId"
]
=
mediaServerId
;
HttpRequester
::
Ptr
requester
(
new
HttpRequester
);
requester
->
setMethod
(
"POST"
);
auto
bodyStr
=
to_string
(
body
);
requester
->
setBody
(
bodyStr
);
requester
->
addHeader
(
"Content-Type"
,
getContentType
(
body
));
requester
->
addHeader
(
"Content-Type"
,
getContentType
(
body
));
std
::
shared_ptr
<
Ticker
>
pTicker
(
new
Ticker
);
requester
->
startRequester
(
url
,
[
url
,
fun
,
bodyStr
,
requester
,
pTicker
](
const
SockException
&
ex
,
const
string
&
status
,
const
HttpClient
::
HttpHeader
&
header
,
const
string
&
strRecvBody
)
{
onceToken
token
(
nullptr
,
[
&
]()
{
requester
->
startRequester
(
url
,
[
url
,
func
,
bodyStr
,
requester
,
pTicker
](
const
SockException
&
ex
,
const
string
&
status
,
const
HttpClient
::
HttpHeader
&
header
,
const
string
&
strRecvBody
)
{
onceToken
token
(
nullptr
,
[
&
]()
{
const_cast
<
HttpRequester
::
Ptr
&>
(
requester
).
reset
();
});
parse_http_response
(
ex
,
status
,
header
,
strRecvBody
,[
&
](
const
Value
&
obj
,
const
string
&
err
){
if
(
fun
)
{
fun
(
obj
,
err
);
if
(
func
)
{
fun
c
(
obj
,
err
);
}
if
(
!
err
.
empty
())
{
WarnL
<<
"hook "
<<
url
<<
" "
<<
pTicker
->
elapsedTime
()
<<
"ms,failed"
<<
err
<<
":"
<<
bodyStr
;
}
else
if
(
pTicker
->
elapsedTime
()
>
500
)
{
DebugL
<<
"hook "
<<
url
<<
" "
<<
pTicker
->
elapsedTime
()
<<
"ms,success:"
<<
bodyStr
;
if
(
!
err
.
empty
())
{
WarnL
<<
"hook "
<<
url
<<
" "
<<
pTicker
->
elapsedTime
()
<<
"ms,failed"
<<
err
<<
":"
<<
bodyStr
;
}
else
if
(
pTicker
->
elapsedTime
()
>
500
)
{
DebugL
<<
"hook "
<<
url
<<
" "
<<
pTicker
->
elapsedTime
()
<<
"ms,success:"
<<
bodyStr
;
}
});
},
hook_timeoutSec
);
},
hook_timeoutSec
);
}
static
ArgsType
make_json
(
const
MediaInfo
&
args
){
...
...
server/WebHook.h
100644 → 100755
查看文件 @
f9f9cde2
...
...
@@ -12,13 +12,32 @@
#define ZLMEDIAKIT_WEBHOOK_H
#include <string>
#include <functional>
#include "jsoncpp/json.h"
using
namespace
std
;
using
namespace
Json
;
//支持json或urlencoded方式传输参数
#define JSON_ARGS
#ifdef JSON_ARGS
typedef
Value
ArgsType
;
#else
typedef
HttpArgs
ArgsType
;
#endif
namespace
Hook
{
//web hook回复最大超时时间
extern
const
string
kTimeoutSec
;
}
//namespace Hook
void
installWebHook
();
void
unInstallWebHook
();
/**
* 触发http hook请求
* @param url 请求地址
* @param body 请求body
* @param func 回调
*/
void
do_http_hook
(
const
string
&
url
,
const
ArgsType
&
body
,
const
function
<
void
(
const
Value
&
,
const
string
&
)
>
&
func
=
nullptr
);
#endif //ZLMEDIAKIT_WEBHOOK_H
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论