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
13221ad7
Commit
13221ad7
authored
Jan 02, 2021
by
xiongziliang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
http回复根据状态码自动生成status message: #602
parent
c69e9b8e
隐藏空白字符变更
内嵌
并排
正在显示
10 个修改的文件
包含
318 行增加
和
188 行删除
+318
-188
api/include/mk_events_objects.h
+4
-4
api/source/mk_events_objects.cpp
+2
-2
server/WebApi.cpp
+13
-13
src/Http/HttpConst.cpp
+216
-0
src/Http/HttpConst.h
+35
-0
src/Http/HttpFileManager.cpp
+18
-141
src/Http/HttpFileManager.h
+6
-5
src/Http/HttpSession.cpp
+22
-21
src/Http/HttpSession.h
+1
-1
tests/test_httpApi.cpp
+1
-1
没有找到文件。
api/include/mk_events_objects.h
查看文件 @
13221ad7
...
...
@@ -169,23 +169,23 @@ typedef void* mk_http_response_invoker;
/**
* HttpSession::HttpResponseInvoker(const string &codeOut, const StrCaseMap &headerOut, const HttpBody::Ptr &body);
* @param response_code 譬如200
OK
* @param response_code 譬如200
* @param response_header 返回的http头,譬如 {"Content-Type","text/html",NULL} 必须以NULL结尾
* @param response_body body对象
*/
API_EXPORT
void
API_CALL
mk_http_response_invoker_do
(
const
mk_http_response_invoker
ctx
,
const
char
*
response_code
,
int
response_code
,
const
char
**
response_header
,
const
mk_http_body
response_body
);
/**
* HttpSession::HttpResponseInvoker(const string &codeOut, const StrCaseMap &headerOut, const string &body);
* @param response_code 譬如200
OK
* @param response_code 譬如200
* @param response_header 返回的http头,譬如 {"Content-Type","text/html",NULL} 必须以NULL结尾
* @param response_content 返回的content部分,譬如一个网页内容
*/
API_EXPORT
void
API_CALL
mk_http_response_invoker_do_string
(
const
mk_http_response_invoker
ctx
,
const
char
*
response_code
,
int
response_code
,
const
char
**
response_header
,
const
char
*
response_content
);
/**
...
...
api/source/mk_events_objects.cpp
查看文件 @
13221ad7
...
...
@@ -288,7 +288,7 @@ API_EXPORT void API_CALL mk_http_body_release(mk_http_body ctx){
///////////////////////////////////////////HttpResponseInvoker/////////////////////////////////////////////
API_EXPORT
void
API_CALL
mk_http_response_invoker_do_string
(
const
mk_http_response_invoker
ctx
,
const
char
*
response_code
,
int
response_code
,
const
char
**
response_header
,
const
char
*
response_content
){
assert
(
ctx
&&
response_code
&&
response_header
&&
response_content
);
...
...
@@ -308,7 +308,7 @@ API_EXPORT void API_CALL mk_http_response_invoker_do_file(const mk_http_response
}
API_EXPORT
void
API_CALL
mk_http_response_invoker_do
(
const
mk_http_response_invoker
ctx
,
const
char
*
response_code
,
int
response_code
,
const
char
**
response_header
,
const
mk_http_body
response_body
){
assert
(
ctx
&&
response_code
&&
response_header
&&
response_body
);
...
...
server/WebApi.cpp
查看文件 @
13221ad7
...
...
@@ -62,7 +62,7 @@ static void responseApi(const Json::Value &res, const HttpSession::HttpResponseI
GET_CONFIG
(
string
,
charSet
,
Http
::
kCharSet
);
HttpSession
::
KeyValue
headerOut
;
headerOut
[
"Content-Type"
]
=
string
(
"application/json; charset="
)
+
charSet
;
invoker
(
"200 OK"
,
headerOut
,
res
.
toStyledString
());
invoker
(
200
,
headerOut
,
res
.
toStyledString
());
};
static
void
responseApi
(
int
code
,
const
string
&
msg
,
const
HttpSession
::
HttpResponseInvoker
&
invoker
){
...
...
@@ -92,7 +92,7 @@ static HttpApi toApi(const function<void(API_ARGS_MAP_ASYNC)> &cb) {
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
());
invoker
(
200
,
headerOut
,
val
.
toStyledString
());
});
}
...
...
@@ -120,7 +120,7 @@ static HttpApi toApi(const function<void(API_ARGS_JSON_ASYNC)> &cb) {
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
());
invoker
(
200
,
headerOut
,
val
.
toStyledString
());
});
}
...
...
@@ -182,7 +182,7 @@ static inline void addHttpListener(){
consumed
=
true
;
if
(
api_debug
){
auto
newInvoker
=
[
invoker
,
parser
](
const
string
&
codeOut
,
auto
newInvoker
=
[
invoker
,
parser
](
int
code
,
const
HttpSession
::
KeyValue
&
headerOut
,
const
HttpBody
::
Ptr
&
body
)
{
...
...
@@ -199,13 +199,13 @@ static inline void addHttpListener(){
<<
"# content:
\r\n
"
<<
parser
.
Content
()
<<
"
\r\n
"
<<
"# response:
\r\n
"
<<
contentOut
<<
"
\r\n
"
;
invoker
(
code
Out
,
headerOut
,
contentOut
);
invoker
(
code
,
headerOut
,
contentOut
);
}
else
{
DebugL
<<
"
\r\n
# request:
\r\n
"
<<
parser
.
Method
()
<<
" "
<<
parser
.
FullUrl
()
<<
"
\r\n
"
<<
"# content:
\r\n
"
<<
parser
.
Content
()
<<
"
\r\n
"
<<
"# response size:"
<<
size
<<
"
\r\n
"
;
invoker
(
code
Out
,
headerOut
,
body
);
invoker
(
code
,
headerOut
,
body
);
}
};
((
HttpSession
::
HttpResponseInvoker
&
)
invoker
)
=
newInvoker
;
...
...
@@ -268,7 +268,7 @@ void installWebApi() {
val
[
"data"
].
append
(
obj
);
}
val
[
"code"
]
=
API
::
Success
;
invoker
(
"200 OK"
,
headerOut
,
val
.
toStyledString
());
invoker
(
200
,
headerOut
,
val
.
toStyledString
());
});
});
...
...
@@ -286,7 +286,7 @@ void installWebApi() {
val
[
"data"
].
append
(
obj
);
}
val
[
"code"
]
=
API
::
Success
;
invoker
(
"200 OK"
,
headerOut
,
val
.
toStyledString
());
invoker
(
200
,
headerOut
,
val
.
toStyledString
());
});
});
...
...
@@ -649,7 +649,7 @@ void installWebApi() {
}
else
{
const_cast
<
Value
&>
(
val
)[
"data"
][
"key"
]
=
key
;
}
invoker
(
"200 OK"
,
headerOut
,
val
.
toStyledString
());
invoker
(
200
,
headerOut
,
val
.
toStyledString
());
});
});
...
...
@@ -712,7 +712,7 @@ void installWebApi() {
}
else
{
const_cast
<
Value
&>
(
val
)[
"data"
][
"key"
]
=
key
;
}
invoker
(
"200 OK"
,
headerOut
,
val
.
toStyledString
());
invoker
(
200
,
headerOut
,
val
.
toStyledString
());
});
});
...
...
@@ -818,7 +818,7 @@ void installWebApi() {
const_cast
<
Value
&>
(
val
)[
"msg"
]
=
ex
.
what
();
}
const_cast
<
Value
&>
(
val
)[
"local_port"
]
=
local_port
;
invoker
(
"200 OK"
,
headerOut
,
val
.
toStyledString
());
invoker
(
200
,
headerOut
,
val
.
toStyledString
());
});
});
...
...
@@ -1092,7 +1092,7 @@ void installWebApi() {
}
else
{
const_cast
<
Value
&>
(
val
)[
"data"
][
"key"
]
=
key
;
}
invoker
(
"200 OK"
,
headerOut
,
val
.
toStyledString
());
invoker
(
200
,
headerOut
,
val
.
toStyledString
());
});
});
#endif//!defined(_WIN32)
...
...
@@ -1117,7 +1117,7 @@ void installWebApi() {
}
else
{
const_cast
<
Value
&>
(
val
)[
"data"
][
"key"
]
=
key
;
}
invoker
(
"200 OK"
,
headerOut
,
val
.
toStyledString
());
invoker
(
200
,
headerOut
,
val
.
toStyledString
());
});
});
...
...
src/Http/HttpConst.cpp
0 → 100644
查看文件 @
13221ad7
/*
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
* Use of this source code is governed by MIT license that can be found in the
* LICENSE file in the root of the source tree. All contributing project authors
* may be found in the AUTHORS file in the root of the source tree.
*/
#include <string.h>
#include "HttpConst.h"
#include "Common/Parser.h"
#include "Util/onceToken.h"
namespace
mediakit
{
const
char
*
getHttpStatusMessage
(
int
status
)
{
switch
(
status
)
{
case
100
:
return
"Continue"
;
case
101
:
return
"Switching Protocol"
;
case
102
:
return
"Processing"
;
case
103
:
return
"Early Hints"
;
case
200
:
return
"OK"
;
case
201
:
return
"Created"
;
case
202
:
return
"Accepted"
;
case
203
:
return
"Non-Authoritative Information"
;
case
204
:
return
"No Content"
;
case
205
:
return
"Reset Content"
;
case
206
:
return
"Partial Content"
;
case
207
:
return
"Multi-Status"
;
case
208
:
return
"Already Reported"
;
case
226
:
return
"IM Used"
;
case
300
:
return
"Multiple Choice"
;
case
301
:
return
"Moved Permanently"
;
case
302
:
return
"Found"
;
case
303
:
return
"See Other"
;
case
304
:
return
"Not Modified"
;
case
305
:
return
"Use Proxy"
;
case
306
:
return
"unused"
;
case
307
:
return
"Temporary Redirect"
;
case
308
:
return
"Permanent Redirect"
;
case
400
:
return
"Bad Request"
;
case
401
:
return
"Unauthorized"
;
case
402
:
return
"Payment Required"
;
case
403
:
return
"Forbidden"
;
case
404
:
return
"Not Found"
;
case
405
:
return
"Method Not Allowed"
;
case
406
:
return
"Not Acceptable"
;
case
407
:
return
"Proxy Authentication Required"
;
case
408
:
return
"Request Timeout"
;
case
409
:
return
"Conflict"
;
case
410
:
return
"Gone"
;
case
411
:
return
"Length Required"
;
case
412
:
return
"Precondition Failed"
;
case
413
:
return
"Payload Too Large"
;
case
414
:
return
"URI Too Long"
;
case
415
:
return
"Unsupported Media Type"
;
case
416
:
return
"Range Not Satisfiable"
;
case
417
:
return
"Expectation Failed"
;
case
418
:
return
"I'm a teapot"
;
case
421
:
return
"Misdirected Request"
;
case
422
:
return
"Unprocessable Entity"
;
case
423
:
return
"Locked"
;
case
424
:
return
"Failed Dependency"
;
case
425
:
return
"Too Early"
;
case
426
:
return
"Upgrade Required"
;
case
428
:
return
"Precondition Required"
;
case
429
:
return
"Too Many Requests"
;
case
431
:
return
"Request Header Fields Too Large"
;
case
451
:
return
"Unavailable For Legal Reasons"
;
case
501
:
return
"Not Implemented"
;
case
502
:
return
"Bad Gateway"
;
case
503
:
return
"Service Unavailable"
;
case
504
:
return
"Gateway Timeout"
;
case
505
:
return
"HTTP Version Not Supported"
;
case
506
:
return
"Variant Also Negotiates"
;
case
507
:
return
"Insufficient Storage"
;
case
508
:
return
"Loop Detected"
;
case
510
:
return
"Not Extended"
;
case
511
:
return
"Network Authentication Required"
;
default
:
case
500
:
return
"Internal Server Error"
;
}
}
static
const
char
*
s_mime_src
[][
2
]
=
{
{
"html"
,
"text/html"
},
{
"htm"
,
"text/html"
},
{
"shtml"
,
"text/html"
},
{
"css"
,
"text/css"
},
{
"xml"
,
"text/xml"
},
{
"gif"
,
"image/gif"
},
{
"jpeg"
,
"image/jpeg"
},
{
"jpg"
,
"image/jpeg"
},
{
"js"
,
"application/javascript"
},
{
"map"
,
"application/javascript"
},
{
"atom"
,
"application/atom+xml"
},
{
"rss"
,
"application/rss+xml"
},
{
"mml"
,
"text/mathml"
},
{
"txt"
,
"text/plain"
},
{
"jad"
,
"text/vnd.sun.j2me.app-descriptor"
},
{
"wml"
,
"text/vnd.wap.wml"
},
{
"htc"
,
"text/x-component"
},
{
"png"
,
"image/png"
},
{
"tif"
,
"image/tiff"
},
{
"tiff"
,
"image/tiff"
},
{
"wbmp"
,
"image/vnd.wap.wbmp"
},
{
"ico"
,
"image/x-icon"
},
{
"jng"
,
"image/x-jng"
},
{
"bmp"
,
"image/x-ms-bmp"
},
{
"svg"
,
"image/svg+xml"
},
{
"svgz"
,
"image/svg+xml"
},
{
"webp"
,
"image/webp"
},
{
"woff"
,
"application/font-woff"
},
{
"woff2"
,
"application/font-woff"
},
{
"jar"
,
"application/java-archive"
},
{
"war"
,
"application/java-archive"
},
{
"ear"
,
"application/java-archive"
},
{
"json"
,
"application/json"
},
{
"hqx"
,
"application/mac-binhex40"
},
{
"doc"
,
"application/msword"
},
{
"pdf"
,
"application/pdf"
},
{
"ps"
,
"application/postscript"
},
{
"eps"
,
"application/postscript"
},
{
"ai"
,
"application/postscript"
},
{
"rtf"
,
"application/rtf"
},
{
"m3u8"
,
"application/vnd.apple.mpegurl"
},
{
"xls"
,
"application/vnd.ms-excel"
},
{
"eot"
,
"application/vnd.ms-fontobject"
},
{
"ppt"
,
"application/vnd.ms-powerpoint"
},
{
"wmlc"
,
"application/vnd.wap.wmlc"
},
{
"kml"
,
"application/vnd.google-earth.kml+xml"
},
{
"kmz"
,
"application/vnd.google-earth.kmz"
},
{
"7z"
,
"application/x-7z-compressed"
},
{
"cco"
,
"application/x-cocoa"
},
{
"jardiff"
,
"application/x-java-archive-diff"
},
{
"jnlp"
,
"application/x-java-jnlp-file"
},
{
"run"
,
"application/x-makeself"
},
{
"pl"
,
"application/x-perl"
},
{
"pm"
,
"application/x-perl"
},
{
"prc"
,
"application/x-pilot"
},
{
"pdb"
,
"application/x-pilot"
},
{
"rar"
,
"application/x-rar-compressed"
},
{
"rpm"
,
"application/x-redhat-package-manager"
},
{
"sea"
,
"application/x-sea"
},
{
"swf"
,
"application/x-shockwave-flash"
},
{
"sit"
,
"application/x-stuffit"
},
{
"tcl"
,
"application/x-tcl"
},
{
"tk"
,
"application/x-tcl"
},
{
"der"
,
"application/x-x509-ca-cert"
},
{
"pem"
,
"application/x-x509-ca-cert"
},
{
"crt"
,
"application/x-x509-ca-cert"
},
{
"xpi"
,
"application/x-xpinstall"
},
{
"xhtml"
,
"application/xhtml+xml"
},
{
"xspf"
,
"application/xspf+xml"
},
{
"zip"
,
"application/zip"
},
{
"bin"
,
"application/octet-stream"
},
{
"exe"
,
"application/octet-stream"
},
{
"dll"
,
"application/octet-stream"
},
{
"deb"
,
"application/octet-stream"
},
{
"dmg"
,
"application/octet-stream"
},
{
"iso"
,
"application/octet-stream"
},
{
"img"
,
"application/octet-stream"
},
{
"msi"
,
"application/octet-stream"
},
{
"msp"
,
"application/octet-stream"
},
{
"msm"
,
"application/octet-stream"
},
{
"docx"
,
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
},
{
"xlsx"
,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
},
{
"pptx"
,
"application/vnd.openxmlformats-officedocument.presentationml.presentation"
},
{
"mid"
,
"audio/midi"
},
{
"midi"
,
"audio/midi"
},
{
"kar"
,
"audio/midi"
},
{
"mp3"
,
"audio/mpeg"
},
{
"ogg"
,
"audio/ogg"
},
{
"m4a"
,
"audio/x-m4a"
},
{
"ra"
,
"audio/x-realaudio"
},
{
"3gpp"
,
"video/3gpp"
},
{
"3gp"
,
"video/3gpp"
},
{
"ts"
,
"video/mp2t"
},
{
"mp4"
,
"video/mp4"
},
{
"mpeg"
,
"video/mpeg"
},
{
"mpg"
,
"video/mpeg"
},
{
"mov"
,
"video/quicktime"
},
{
"webm"
,
"video/webm"
},
{
"flv"
,
"video/x-flv"
},
{
"m4v"
,
"video/x-m4v"
},
{
"mng"
,
"video/x-mng"
},
{
"asx"
,
"video/x-ms-asf"
},
{
"asf"
,
"video/x-ms-asf"
},
{
"wmv"
,
"video/x-ms-wmv"
},
{
"avi"
,
"video/x-msvideo"
},
};
const
string
&
getHttpContentType
(
const
char
*
name
)
{
const
char
*
dot
;
dot
=
strrchr
(
name
,
'.'
);
static
StrCaseMap
mapType
;
static
onceToken
token
([
&
]()
{
for
(
unsigned
int
i
=
0
;
i
<
sizeof
(
s_mime_src
)
/
sizeof
(
s_mime_src
[
0
]);
++
i
)
{
mapType
.
emplace
(
s_mime_src
[
i
][
0
],
s_mime_src
[
i
][
1
]);
}
});
static
string
defaultType
=
"text/plain"
;
if
(
!
dot
)
{
return
defaultType
;
}
auto
it
=
mapType
.
find
(
dot
+
1
);
if
(
it
==
mapType
.
end
())
{
return
defaultType
;
}
return
it
->
second
;
}
}
//namespace mediakit
src/Http/HttpConst.h
0 → 100644
查看文件 @
13221ad7
/*
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
* Use of this source code is governed by MIT license that can be found in the
* LICENSE file in the root of the source tree. All contributing project authors
* may be found in the AUTHORS file in the root of the source tree.
*/
#ifndef ZLMEDIAKIT_HTTPCONST_H
#define ZLMEDIAKIT_HTTPCONST_H
#include <string>
using
namespace
std
;
namespace
mediakit
{
/**
* 根据http错误代码获取字符说明
* @param status 譬如404
* @return 错误代码字符说明,譬如Not Found
*/
const
char
*
getHttpStatusMessage
(
int
status
);
/**
* 根据文件后缀返回http mime
* @param name 文件后缀,譬如html
* @return mime值,譬如text/html
*/
const
string
&
getHttpContentType
(
const
char
*
name
);
}
//mediakit
#endif //ZLMEDIAKIT_HTTPCONST_H
src/Http/HttpFileManager.cpp
查看文件 @
13221ad7
...
...
@@ -15,6 +15,7 @@
#include <iomanip>
#include "HttpFileManager.h"
#include "Util/File.h"
#include "HttpConst.h"
#include "HttpSession.h"
#include "Record/HlsMediaSource.h"
...
...
@@ -47,132 +48,8 @@ public:
bool
_have_find_media_source
=
false
;
};
static
const
char
*
s_mime_src
[][
2
]
=
{
{
"html"
,
"text/html"
},
{
"htm"
,
"text/html"
},
{
"shtml"
,
"text/html"
},
{
"css"
,
"text/css"
},
{
"xml"
,
"text/xml"
},
{
"gif"
,
"image/gif"
},
{
"jpeg"
,
"image/jpeg"
},
{
"jpg"
,
"image/jpeg"
},
{
"js"
,
"application/javascript"
},
{
"map"
,
"application/javascript"
},
{
"atom"
,
"application/atom+xml"
},
{
"rss"
,
"application/rss+xml"
},
{
"mml"
,
"text/mathml"
},
{
"txt"
,
"text/plain"
},
{
"jad"
,
"text/vnd.sun.j2me.app-descriptor"
},
{
"wml"
,
"text/vnd.wap.wml"
},
{
"htc"
,
"text/x-component"
},
{
"png"
,
"image/png"
},
{
"tif"
,
"image/tiff"
},
{
"tiff"
,
"image/tiff"
},
{
"wbmp"
,
"image/vnd.wap.wbmp"
},
{
"ico"
,
"image/x-icon"
},
{
"jng"
,
"image/x-jng"
},
{
"bmp"
,
"image/x-ms-bmp"
},
{
"svg"
,
"image/svg+xml"
},
{
"svgz"
,
"image/svg+xml"
},
{
"webp"
,
"image/webp"
},
{
"woff"
,
"application/font-woff"
},
{
"woff2"
,
"application/font-woff"
},
{
"jar"
,
"application/java-archive"
},
{
"war"
,
"application/java-archive"
},
{
"ear"
,
"application/java-archive"
},
{
"json"
,
"application/json"
},
{
"hqx"
,
"application/mac-binhex40"
},
{
"doc"
,
"application/msword"
},
{
"pdf"
,
"application/pdf"
},
{
"ps"
,
"application/postscript"
},
{
"eps"
,
"application/postscript"
},
{
"ai"
,
"application/postscript"
},
{
"rtf"
,
"application/rtf"
},
{
"m3u8"
,
"application/vnd.apple.mpegurl"
},
{
"xls"
,
"application/vnd.ms-excel"
},
{
"eot"
,
"application/vnd.ms-fontobject"
},
{
"ppt"
,
"application/vnd.ms-powerpoint"
},
{
"wmlc"
,
"application/vnd.wap.wmlc"
},
{
"kml"
,
"application/vnd.google-earth.kml+xml"
},
{
"kmz"
,
"application/vnd.google-earth.kmz"
},
{
"7z"
,
"application/x-7z-compressed"
},
{
"cco"
,
"application/x-cocoa"
},
{
"jardiff"
,
"application/x-java-archive-diff"
},
{
"jnlp"
,
"application/x-java-jnlp-file"
},
{
"run"
,
"application/x-makeself"
},
{
"pl"
,
"application/x-perl"
},
{
"pm"
,
"application/x-perl"
},
{
"prc"
,
"application/x-pilot"
},
{
"pdb"
,
"application/x-pilot"
},
{
"rar"
,
"application/x-rar-compressed"
},
{
"rpm"
,
"application/x-redhat-package-manager"
},
{
"sea"
,
"application/x-sea"
},
{
"swf"
,
"application/x-shockwave-flash"
},
{
"sit"
,
"application/x-stuffit"
},
{
"tcl"
,
"application/x-tcl"
},
{
"tk"
,
"application/x-tcl"
},
{
"der"
,
"application/x-x509-ca-cert"
},
{
"pem"
,
"application/x-x509-ca-cert"
},
{
"crt"
,
"application/x-x509-ca-cert"
},
{
"xpi"
,
"application/x-xpinstall"
},
{
"xhtml"
,
"application/xhtml+xml"
},
{
"xspf"
,
"application/xspf+xml"
},
{
"zip"
,
"application/zip"
},
{
"bin"
,
"application/octet-stream"
},
{
"exe"
,
"application/octet-stream"
},
{
"dll"
,
"application/octet-stream"
},
{
"deb"
,
"application/octet-stream"
},
{
"dmg"
,
"application/octet-stream"
},
{
"iso"
,
"application/octet-stream"
},
{
"img"
,
"application/octet-stream"
},
{
"msi"
,
"application/octet-stream"
},
{
"msp"
,
"application/octet-stream"
},
{
"msm"
,
"application/octet-stream"
},
{
"docx"
,
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
},
{
"xlsx"
,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
},
{
"pptx"
,
"application/vnd.openxmlformats-officedocument.presentationml.presentation"
},
{
"mid"
,
"audio/midi"
},
{
"midi"
,
"audio/midi"
},
{
"kar"
,
"audio/midi"
},
{
"mp3"
,
"audio/mpeg"
},
{
"ogg"
,
"audio/ogg"
},
{
"m4a"
,
"audio/x-m4a"
},
{
"ra"
,
"audio/x-realaudio"
},
{
"3gpp"
,
"video/3gpp"
},
{
"3gp"
,
"video/3gpp"
},
{
"ts"
,
"video/mp2t"
},
{
"mp4"
,
"video/mp4"
},
{
"mpeg"
,
"video/mpeg"
},
{
"mpg"
,
"video/mpeg"
},
{
"mov"
,
"video/quicktime"
},
{
"webm"
,
"video/webm"
},
{
"flv"
,
"video/x-flv"
},
{
"m4v"
,
"video/x-m4v"
},
{
"mng"
,
"video/x-mng"
},
{
"asx"
,
"video/x-ms-asf"
},
{
"asf"
,
"video/x-ms-asf"
},
{
"wmv"
,
"video/x-ms-wmv"
},
{
"avi"
,
"video/x-msvideo"
},
};
const
string
&
HttpFileManager
::
getContentType
(
const
char
*
name
)
{
const
char
*
dot
;
dot
=
strrchr
(
name
,
'.'
);
static
StrCaseMap
mapType
;
static
onceToken
token
([
&
]()
{
for
(
unsigned
int
i
=
0
;
i
<
sizeof
(
s_mime_src
)
/
sizeof
(
s_mime_src
[
0
]);
++
i
)
{
mapType
.
emplace
(
s_mime_src
[
i
][
0
],
s_mime_src
[
i
][
1
]);
}
});
static
string
defaultType
=
"text/plain"
;
if
(
!
dot
)
{
return
defaultType
;
}
auto
it
=
mapType
.
find
(
dot
+
1
);
if
(
it
==
mapType
.
end
())
{
return
defaultType
;
}
return
it
->
second
;
return
getHttpContentType
(
name
);
}
static
string
searchIndexFile
(
const
string
&
dir
){
...
...
@@ -460,7 +337,7 @@ static void canAccessPath(TcpSession &sender, const Parser &parser, const MediaI
*/
static
void
sendNotFound
(
const
HttpFileManager
::
invoker
&
cb
)
{
GET_CONFIG
(
string
,
notFound
,
Http
::
kNotFound
);
cb
(
"404 Not Found"
,
"text/html"
,
StrCaseMap
(),
std
::
make_shared
<
HttpStringBody
>
(
notFound
));
cb
(
404
,
"text/html"
,
StrCaseMap
(),
std
::
make_shared
<
HttpStringBody
>
(
notFound
));
}
/**
...
...
@@ -511,7 +388,7 @@ static void accessFile(TcpSession &sender, const Parser &parser, const MediaInfo
auto
lck
=
cookie
->
getLock
();
headerOut
[
"Set-Cookie"
]
=
cookie
->
getCookie
((
*
cookie
)[
kCookieName
].
get
<
HttpCookieAttachment
>
().
_path
);
}
cb
(
"401 Unauthorized"
,
"text/html"
,
headerOut
,
std
::
make_shared
<
HttpStringBody
>
(
errMsg
));
cb
(
401
,
"text/html"
,
headerOut
,
std
::
make_shared
<
HttpStringBody
>
(
errMsg
));
return
;
}
...
...
@@ -521,7 +398,7 @@ static void accessFile(TcpSession &sender, const Parser &parser, const MediaInfo
auto
lck
=
cookie
->
getLock
();
httpHeader
[
"Set-Cookie"
]
=
cookie
->
getCookie
((
*
cookie
)[
kCookieName
].
get
<
HttpCookieAttachment
>
().
_path
);
}
HttpSession
::
HttpResponseInvoker
invoker
=
[
&
](
const
string
&
codeOut
,
const
StrCaseMap
&
headerOut
,
const
HttpBody
::
Ptr
&
body
)
{
HttpSession
::
HttpResponseInvoker
invoker
=
[
&
](
int
code
,
const
StrCaseMap
&
headerOut
,
const
HttpBody
::
Ptr
&
body
)
{
if
(
cookie
&&
file_exist
)
{
auto
lck
=
cookie
->
getLock
();
auto
is_hls
=
(
*
cookie
)[
kCookieName
].
get
<
HttpCookieAttachment
>
().
_is_hls
;
...
...
@@ -529,7 +406,7 @@ static void accessFile(TcpSession &sender, const Parser &parser, const MediaInfo
(
*
cookie
)[
kCookieName
].
get
<
HttpCookieAttachment
>
().
_hls_data
->
addByteUsage
(
body
->
remainSize
());
}
}
cb
(
code
Out
.
data
()
,
HttpFileManager
::
getContentType
(
strFile
.
data
()),
headerOut
,
body
);
cb
(
code
,
HttpFileManager
::
getContentType
(
strFile
.
data
()),
headerOut
,
body
);
};
invoker
.
responseFile
(
parser
.
getHeader
(),
httpHeader
,
strFile
);
};
...
...
@@ -625,7 +502,7 @@ void HttpFileManager::onAccessPath(TcpSession &sender, Parser &parser, const Htt
if
(
cookie
)
{
headerOut
[
"Set-Cookie"
]
=
cookie
->
getCookie
((
*
cookie
)[
kCookieName
].
get
<
HttpCookieAttachment
>
().
_path
);
}
cb
(
errMsg
.
empty
()
?
"200 OK"
:
"401 Unauthorized"
,
"text/html"
,
headerOut
,
std
::
make_shared
<
HttpStringBody
>
(
strMenu
));
cb
(
errMsg
.
empty
()
?
200
:
401
,
"text/html"
,
headerOut
,
std
::
make_shared
<
HttpStringBody
>
(
strMenu
));
});
return
;
}
...
...
@@ -637,14 +514,14 @@ void HttpFileManager::onAccessPath(TcpSession &sender, Parser &parser, const Htt
////////////////////////////////////HttpResponseInvokerImp//////////////////////////////////////
void
HttpResponseInvokerImp
::
operator
()(
const
string
&
codeOut
,
const
StrCaseMap
&
headerOut
,
const
HttpBody
::
Ptr
&
body
)
const
{
void
HttpResponseInvokerImp
::
operator
()(
int
code
,
const
StrCaseMap
&
headerOut
,
const
HttpBody
::
Ptr
&
body
)
const
{
if
(
_lambad
)
{
_lambad
(
code
Out
,
headerOut
,
body
);
_lambad
(
code
,
headerOut
,
body
);
}
}
void
HttpResponseInvokerImp
::
operator
()(
const
string
&
codeOut
,
const
StrCaseMap
&
headerOut
,
const
string
&
body
)
const
{
this
->
operator
()(
code
Out
,
headerOut
,
std
::
make_shared
<
HttpStringBody
>
(
body
));
void
HttpResponseInvokerImp
::
operator
()(
int
code
,
const
StrCaseMap
&
headerOut
,
const
string
&
body
)
const
{
this
->
operator
()(
code
,
headerOut
,
std
::
make_shared
<
HttpStringBody
>
(
body
));
}
HttpResponseInvokerImp
::
HttpResponseInvokerImp
(
const
HttpResponseInvokerImp
::
HttpResponseInvokerLambda0
&
lambda
){
...
...
@@ -656,12 +533,12 @@ HttpResponseInvokerImp::HttpResponseInvokerImp(const HttpResponseInvokerImp::Htt
_lambad
=
nullptr
;
return
;
}
_lambad
=
[
lambda
](
const
string
&
codeOut
,
const
StrCaseMap
&
headerOut
,
const
HttpBody
::
Ptr
&
body
)
{
_lambad
=
[
lambda
](
int
code
,
const
StrCaseMap
&
headerOut
,
const
HttpBody
::
Ptr
&
body
)
{
string
str
;
if
(
body
&&
body
->
remainSize
())
{
str
=
body
->
readData
(
body
->
remainSize
())
->
toString
();
}
lambda
(
code
Out
,
headerOut
,
str
);
lambda
(
code
,
headerOut
,
str
);
};
}
...
...
@@ -682,7 +559,7 @@ void HttpResponseInvokerImp::responseFile(const StrCaseMap &requestHeader,
auto
strContentType
=
StrPrinter
<<
"text/html; charset="
<<
charSet
<<
endl
;
httpHeader
[
"Content-Type"
]
=
strContentType
;
(
*
this
)(
"404 Not Found"
,
httpHeader
,
notFound
);
(
*
this
)(
404
,
httpHeader
,
notFound
);
return
;
}
...
...
@@ -691,14 +568,14 @@ void HttpResponseInvokerImp::responseFile(const StrCaseMap &requestHeader,
int64_t
iRangeEnd
=
0
;
int64_t
fileSize
=
HttpMultiFormBody
::
fileSize
(
fp
.
get
());
const
char
*
pcHttpResult
=
NULL
;
int
code
=
NULL
;
if
(
strRange
.
size
()
==
0
)
{
//全部下载
pcHttpResult
=
"200 OK"
;
code
=
200
;
iRangeEnd
=
fileSize
-
1
;
}
else
{
//分节下载
pcHttpResult
=
"206 Partial Content"
;
code
=
206
;
iRangeStart
=
atoll
(
FindField
(
strRange
.
data
(),
"bytes="
,
"-"
).
data
());
iRangeEnd
=
atoll
(
FindField
(
strRange
.
data
(),
"-"
,
"
\r\n
"
).
data
());
if
(
iRangeEnd
==
0
)
{
...
...
@@ -710,7 +587,7 @@ void HttpResponseInvokerImp::responseFile(const StrCaseMap &requestHeader,
//回复文件
HttpBody
::
Ptr
fileBody
=
std
::
make_shared
<
HttpFileBody
>
(
fp
,
iRangeStart
,
iRangeEnd
-
iRangeStart
+
1
);
(
*
this
)(
pcHttpResult
,
httpHeader
,
fileBody
);
(
*
this
)(
code
,
httpHeader
,
fileBody
);
}
HttpResponseInvokerImp
::
operator
bool
(){
...
...
src/Http/HttpFileManager.h
查看文件 @
13221ad7
...
...
@@ -21,8 +21,8 @@ namespace mediakit {
class
HttpResponseInvokerImp
{
public
:
typedef
std
::
function
<
void
(
const
string
&
codeOut
,
const
StrCaseMap
&
headerOut
,
const
HttpBody
::
Ptr
&
body
)
>
HttpResponseInvokerLambda0
;
typedef
std
::
function
<
void
(
const
string
&
codeOut
,
const
StrCaseMap
&
headerOut
,
const
string
&
body
)
>
HttpResponseInvokerLambda1
;
typedef
std
::
function
<
void
(
int
code
,
const
StrCaseMap
&
headerOut
,
const
HttpBody
::
Ptr
&
body
)
>
HttpResponseInvokerLambda0
;
typedef
std
::
function
<
void
(
int
code
,
const
StrCaseMap
&
headerOut
,
const
string
&
body
)
>
HttpResponseInvokerLambda1
;
HttpResponseInvokerImp
(){}
~
HttpResponseInvokerImp
(){}
...
...
@@ -31,8 +31,9 @@ public:
HttpResponseInvokerImp
(
const
HttpResponseInvokerLambda0
&
lambda
);
HttpResponseInvokerImp
(
const
HttpResponseInvokerLambda1
&
lambda
);
void
operator
()(
const
string
&
codeOut
,
const
StrCaseMap
&
headerOut
,
const
HttpBody
::
Ptr
&
body
)
const
;
void
operator
()(
const
string
&
codeOut
,
const
StrCaseMap
&
headerOut
,
const
string
&
body
)
const
;
void
operator
()(
int
code
,
const
StrCaseMap
&
headerOut
,
const
HttpBody
::
Ptr
&
body
)
const
;
void
operator
()(
int
code
,
const
StrCaseMap
&
headerOut
,
const
string
&
body
)
const
;
void
responseFile
(
const
StrCaseMap
&
requestHeader
,
const
StrCaseMap
&
responseHeader
,
const
string
&
filePath
)
const
;
operator
bool
();
private
:
...
...
@@ -44,7 +45,7 @@ private:
*/
class
HttpFileManager
{
public
:
typedef
function
<
void
(
const
string
&
status_
code
,
const
string
&
content_type
,
const
StrCaseMap
&
responseHeader
,
const
HttpBody
::
Ptr
&
body
)
>
invoker
;
typedef
function
<
void
(
int
code
,
const
string
&
content_type
,
const
StrCaseMap
&
responseHeader
,
const
HttpBody
::
Ptr
&
body
)
>
invoker
;
/**
* 访问文件或文件夹
...
...
src/Http/HttpSession.cpp
查看文件 @
13221ad7
...
...
@@ -14,6 +14,7 @@
#include "Common/config.h"
#include "strCoding.h"
#include "HttpSession.h"
#include "HttpConst.h"
#include "Util/base64.h"
#include "Util/SHA1.h"
using
namespace
toolkit
;
...
...
@@ -34,7 +35,7 @@ void HttpSession::Handle_Req_HEAD(int64_t &content_len){
//暂时全部返回200 OK,因为HTTP GET存在按需生成流的操作,所以不能按照HTTP GET的流程返回
//如果直接返回404,那么又会导致按需生成流的逻辑失效,所以HTTP HEAD在静态文件或者已存在资源时才有效
//对于按需生成流的直播场景并不适用
sendResponse
(
"200 OK"
,
true
);
sendResponse
(
200
,
true
);
}
int64_t
HttpSession
::
onRecvHeader
(
const
char
*
header
,
uint64_t
len
)
{
...
...
@@ -52,7 +53,7 @@ int64_t HttpSession::onRecvHeader(const char *header,uint64_t len) {
auto
it
=
s_func_map
.
find
(
cmd
);
if
(
it
==
s_func_map
.
end
())
{
WarnP
(
this
)
<<
"不支持该命令:"
<<
cmd
;
sendResponse
(
"405 Not Allowed"
,
true
);
sendResponse
(
405
,
true
);
return
0
;
}
...
...
@@ -139,7 +140,7 @@ bool HttpSession::checkWebSocket(){
auto
res_cb
=
[
this
,
headerOut
]()
{
_live_over_websocket
=
true
;
sendResponse
(
"101 Switching Protocols"
,
false
,
nullptr
,
headerOut
,
nullptr
,
true
);
sendResponse
(
101
,
false
,
nullptr
,
headerOut
,
nullptr
,
true
);
};
//判断是否为websocket-flv
...
...
@@ -162,10 +163,10 @@ bool HttpSession::checkWebSocket(){
//这是普通的websocket连接
if
(
!
onWebSocketConnect
(
_parser
))
{
sendResponse
(
"501 Not Implemented"
,
true
,
nullptr
,
headerOut
);
sendResponse
(
501
,
true
,
nullptr
,
headerOut
);
return
true
;
}
sendResponse
(
"101 Switching Protocols"
,
false
,
nullptr
,
headerOut
,
nullptr
,
true
);
sendResponse
(
101
,
false
,
nullptr
,
headerOut
,
nullptr
,
true
);
return
true
;
}
...
...
@@ -198,7 +199,7 @@ bool HttpSession::checkLiveStream(const string &schema, const string &url_suffi
if
(
!
err
.
empty
())
{
//播放鉴权失败
strong_self
->
sendResponse
(
"401 Unauthorized"
,
close_flag
,
nullptr
,
KeyValue
(),
std
::
make_shared
<
HttpStringBody
>
(
err
));
strong_self
->
sendResponse
(
401
,
close_flag
,
nullptr
,
KeyValue
(),
std
::
make_shared
<
HttpStringBody
>
(
err
));
return
;
}
...
...
@@ -245,7 +246,7 @@ bool HttpSession::checkLiveStreamFMP4(const function<void()> &cb){
assert
(
fmp4_src
);
if
(
!
cb
)
{
//找到源,发送http头,负载后续发送
sendResponse
(
"200 OK"
,
false
,
HttpFileManager
::
getContentType
(
".mp4"
).
data
(),
KeyValue
(),
nullptr
,
true
);
sendResponse
(
200
,
false
,
HttpFileManager
::
getContentType
(
".mp4"
).
data
(),
KeyValue
(),
nullptr
,
true
);
}
else
{
//自定义发送http头
cb
();
...
...
@@ -286,7 +287,7 @@ bool HttpSession::checkLiveStreamTS(const function<void()> &cb){
assert
(
ts_src
);
if
(
!
cb
)
{
//找到源,发送http头,负载后续发送
sendResponse
(
"200 OK"
,
false
,
HttpFileManager
::
getContentType
(
".ts"
).
data
(),
KeyValue
(),
nullptr
,
true
);
sendResponse
(
200
,
false
,
HttpFileManager
::
getContentType
(
".ts"
).
data
(),
KeyValue
(),
nullptr
,
true
);
}
else
{
//自定义发送http头
cb
();
...
...
@@ -326,7 +327,7 @@ bool HttpSession::checkLiveStreamFlv(const function<void()> &cb){
assert
(
rtmp_src
);
if
(
!
cb
)
{
//找到源,发送http头,负载后续发送
sendResponse
(
"200 OK"
,
false
,
HttpFileManager
::
getContentType
(
".flv"
).
data
(),
KeyValue
(),
nullptr
,
true
);
sendResponse
(
200
,
false
,
HttpFileManager
::
getContentType
(
".flv"
).
data
(),
KeyValue
(),
nullptr
,
true
);
}
else
{
//自定义发送http头
cb
();
...
...
@@ -375,18 +376,18 @@ void HttpSession::Handle_Req_GET_l(int64_t &content_len, bool sendBody) {
bool
bClose
=
!
strcasecmp
(
_parser
[
"Connection"
].
data
(),
"close"
);
weak_ptr
<
HttpSession
>
weakSelf
=
dynamic_pointer_cast
<
HttpSession
>
(
shared_from_this
());
HttpFileManager
::
onAccessPath
(
*
this
,
_parser
,
[
weakSelf
,
bClose
](
const
string
&
status_
code
,
const
string
&
content_type
,
HttpFileManager
::
onAccessPath
(
*
this
,
_parser
,
[
weakSelf
,
bClose
](
int
code
,
const
string
&
content_type
,
const
StrCaseMap
&
responseHeader
,
const
HttpBody
::
Ptr
&
body
)
{
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
return
;
}
strongSelf
->
async
([
weakSelf
,
bClose
,
status_
code
,
content_type
,
responseHeader
,
body
]()
{
strongSelf
->
async
([
weakSelf
,
bClose
,
code
,
content_type
,
responseHeader
,
body
]()
{
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
return
;
}
strongSelf
->
sendResponse
(
status_code
.
data
()
,
bClose
,
content_type
.
data
(),
responseHeader
,
body
);
strongSelf
->
sendResponse
(
code
,
bClose
,
content_type
.
data
(),
responseHeader
,
body
);
});
});
}
...
...
@@ -480,7 +481,7 @@ static const string kContentLength = "Content-Length";
static
const
string
kAccessControlAllowOrigin
=
"Access-Control-Allow-Origin"
;
static
const
string
kAccessControlAllowCredentials
=
"Access-Control-Allow-Credentials"
;
void
HttpSession
::
sendResponse
(
const
char
*
pcStatus
,
void
HttpSession
::
sendResponse
(
int
code
,
bool
bClose
,
const
char
*
pcContentType
,
const
HttpSession
::
KeyValue
&
header
,
...
...
@@ -543,7 +544,7 @@ void HttpSession::sendResponse(const char *pcStatus,
string
str
;
str
.
reserve
(
256
);
str
+=
"HTTP/1.1 "
;
str
+=
pcStatus
;
str
+=
getHttpStatusMessage
(
code
)
;
str
+=
"
\r\n
"
;
for
(
auto
&
pr
:
header
)
{
str
+=
pr
.
first
;
...
...
@@ -558,7 +559,7 @@ void HttpSession::sendResponse(const char *pcStatus,
if
(
!
size
){
//没有body
if
(
bClose
){
shutdown
(
SockException
(
Err_shutdown
,
StrPrinter
<<
"close connection after send http header completed with status code:"
<<
pcStatus
));
shutdown
(
SockException
(
Err_shutdown
,
StrPrinter
<<
"close connection after send http header completed with status code:"
<<
code
));
}
return
;
}
...
...
@@ -600,18 +601,18 @@ bool HttpSession::emitHttpEvent(bool doInvoke){
bool
bClose
=
!
strcasecmp
(
_parser
[
"Connection"
].
data
(),
"close"
);
/////////////////////异步回复Invoker///////////////////////////////
weak_ptr
<
HttpSession
>
weakSelf
=
dynamic_pointer_cast
<
HttpSession
>
(
shared_from_this
());
HttpResponseInvoker
invoker
=
[
weakSelf
,
bClose
](
const
string
&
codeOut
,
const
KeyValue
&
headerOut
,
const
HttpBody
::
Ptr
&
body
){
HttpResponseInvoker
invoker
=
[
weakSelf
,
bClose
](
int
code
,
const
KeyValue
&
headerOut
,
const
HttpBody
::
Ptr
&
body
){
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
return
;
}
strongSelf
->
async
([
weakSelf
,
bClose
,
codeOut
,
headerOut
,
body
]()
{
strongSelf
->
async
([
weakSelf
,
bClose
,
code
,
headerOut
,
body
]()
{
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
if
(
!
strongSelf
)
{
//本对象已经销毁
return
;
}
strongSelf
->
sendResponse
(
code
Out
.
data
()
,
bClose
,
nullptr
,
headerOut
,
body
);
strongSelf
->
sendResponse
(
code
,
bClose
,
nullptr
,
headerOut
,
body
);
});
};
///////////////////广播HTTP事件///////////////////////////
...
...
@@ -619,7 +620,7 @@ bool HttpSession::emitHttpEvent(bool doInvoke){
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastHttpRequest
,
_parser
,
invoker
,
consumed
,
static_cast
<
SockInfo
&>
(
*
this
));
if
(
!
consumed
&&
doInvoke
){
//该事件无人消费,所以返回404
invoker
(
"404 Not Found"
,
KeyValue
(),
HttpBody
::
Ptr
());
invoker
(
404
,
KeyValue
(),
HttpBody
::
Ptr
());
}
return
consumed
;
}
...
...
@@ -690,7 +691,7 @@ void HttpSession::Handle_Req_POST(int64_t &content_len) {
void
HttpSession
::
sendNotFound
(
bool
bClose
)
{
GET_CONFIG
(
string
,
notFound
,
Http
::
kNotFound
);
sendResponse
(
"404 Not Found"
,
bClose
,
"text/html"
,
KeyValue
(),
std
::
make_shared
<
HttpStringBody
>
(
notFound
));
sendResponse
(
404
,
bClose
,
"text/html"
,
KeyValue
(),
std
::
make_shared
<
HttpStringBody
>
(
notFound
));
}
void
HttpSession
::
setSocketFlags
(){
...
...
src/Http/HttpSession.h
查看文件 @
13221ad7
...
...
@@ -116,7 +116,7 @@ private:
bool
emitHttpEvent
(
bool
doInvoke
);
void
urlDecode
(
Parser
&
parser
);
void
sendNotFound
(
bool
bClose
);
void
sendResponse
(
const
char
*
pcStatus
,
bool
bClose
,
const
char
*
pcContentType
=
nullptr
,
void
sendResponse
(
int
code
,
bool
bClose
,
const
char
*
pcContentType
=
nullptr
,
const
HttpSession
::
KeyValue
&
header
=
HttpSession
::
KeyValue
(),
const
HttpBody
::
Ptr
&
body
=
nullptr
,
bool
no_content_length
=
false
);
...
...
tests/test_httpApi.cpp
查看文件 @
13221ad7
...
...
@@ -79,7 +79,7 @@ void initEventListener(){
//请勿覆盖Connection、Content-Length键
//键名覆盖时不区分大小写
headerOut
[
"TestHeader"
]
=
"HeaderValue"
;
invoker
(
"200 OK"
,
headerOut
,
contentOut
);
invoker
(
200
,
headerOut
,
contentOut
);
});
});
},
nullptr
);
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论