diff --git a/api/include/mk_events_objects.h b/api/include/mk_events_objects.h index 25473d4e..f348f511 100644 --- a/api/include/mk_events_objects.h +++ b/api/include/mk_events_objects.h @@ -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); /** diff --git a/api/source/mk_events_objects.cpp b/api/source/mk_events_objects.cpp index 23dd9f33..8ac9a4cb 100644 --- a/api/source/mk_events_objects.cpp +++ b/api/source/mk_events_objects.cpp @@ -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); diff --git a/server/WebApi.cpp b/server/WebApi.cpp index 6f4d4f0b..e43867f4 100755 --- a/server/WebApi.cpp +++ b/server/WebApi.cpp @@ -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 &cb) { static HttpApi toApi(const function &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 &cb) { static HttpApi toApi(const function &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(codeOut, 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(codeOut, 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(val)["data"]["key"] = key; } - invoker("200 OK", headerOut, val.toStyledString()); + invoker(200, headerOut, val.toStyledString()); }); }); @@ -712,7 +712,7 @@ void installWebApi() { } else { const_cast(val)["data"]["key"] = key; } - invoker("200 OK", headerOut, val.toStyledString()); + invoker(200, headerOut, val.toStyledString()); }); }); @@ -818,7 +818,7 @@ void installWebApi() { const_cast(val)["msg"] = ex.what(); } const_cast(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(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(val)["data"]["key"] = key; } - invoker("200 OK", headerOut, val.toStyledString()); + invoker(200, headerOut, val.toStyledString()); }); }); diff --git a/src/Http/HttpConst.cpp b/src/Http/HttpConst.cpp new file mode 100644 index 00000000..7b12548c --- /dev/null +++ b/src/Http/HttpConst.cpp @@ -0,0 +1,216 @@ +/* + * 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 +#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 diff --git a/src/Http/HttpConst.h b/src/Http/HttpConst.h new file mode 100644 index 00000000..f4be7596 --- /dev/null +++ b/src/Http/HttpConst.h @@ -0,0 +1,35 @@ +/* + * 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 +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 diff --git a/src/Http/HttpFileManager.cpp b/src/Http/HttpFileManager.cpp index 0e603e81..99b71316 100644 --- a/src/Http/HttpFileManager.cpp +++ b/src/Http/HttpFileManager.cpp @@ -15,6 +15,7 @@ #include #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(notFound)); + cb(404, "text/html", StrCaseMap(), std::make_shared(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()._path); } - cb("401 Unauthorized", "text/html", headerOut, std::make_shared(errMsg)); + cb(401, "text/html", headerOut, std::make_shared(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()._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()._is_hls; @@ -529,7 +406,7 @@ static void accessFile(TcpSession &sender, const Parser &parser, const MediaInfo (*cookie)[kCookieName].get()._hls_data->addByteUsage(body->remainSize()); } } - cb(codeOut.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()._path); } - cb(errMsg.empty() ? "200 OK" : "401 Unauthorized", "text/html", headerOut, std::make_shared(strMenu)); + cb(errMsg.empty() ? 200 : 401, "text/html", headerOut, std::make_shared(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(codeOut, headerOut, body); + _lambad(code, headerOut, body); } } -void HttpResponseInvokerImp::operator()(const string &codeOut, const StrCaseMap &headerOut, const string &body) const{ - this->operator()(codeOut, headerOut, std::make_shared(body)); +void HttpResponseInvokerImp::operator()(int code, const StrCaseMap &headerOut, const string &body) const{ + this->operator()(code, headerOut, std::make_shared(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(codeOut, 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(fp, iRangeStart, iRangeEnd - iRangeStart + 1); - (*this)(pcHttpResult, httpHeader, fileBody); + (*this)(code, httpHeader, fileBody); } HttpResponseInvokerImp::operator bool(){ diff --git a/src/Http/HttpFileManager.h b/src/Http/HttpFileManager.h index 9832cf81..e8a2181d 100644 --- a/src/Http/HttpFileManager.h +++ b/src/Http/HttpFileManager.h @@ -21,8 +21,8 @@ namespace mediakit { class HttpResponseInvokerImp{ public: - typedef std::function HttpResponseInvokerLambda0; - typedef std::function HttpResponseInvokerLambda1; + typedef std::function HttpResponseInvokerLambda0; + typedef std::function 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 invoker; + typedef function invoker; /** * 访问文件或文件夹 diff --git a/src/Http/HttpSession.cpp b/src/Http/HttpSession.cpp index 2d9740cc..d119f19e 100644 --- a/src/Http/HttpSession.cpp +++ b/src/Http/HttpSession.cpp @@ -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(err)); + strong_self->sendResponse(401, close_flag, nullptr, KeyValue(), std::make_shared(err)); return; } @@ -245,7 +246,7 @@ bool HttpSession::checkLiveStreamFMP4(const function &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 &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 &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 weakSelf = dynamic_pointer_cast(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 weakSelf = dynamic_pointer_cast(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(codeOut.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(*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(notFound)); + sendResponse(404, bClose,"text/html",KeyValue(),std::make_shared(notFound)); } void HttpSession::setSocketFlags(){ diff --git a/src/Http/HttpSession.h b/src/Http/HttpSession.h index d9d2047c..e3bc7e4a 100644 --- a/src/Http/HttpSession.h +++ b/src/Http/HttpSession.h @@ -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); diff --git a/tests/test_httpApi.cpp b/tests/test_httpApi.cpp index 5d24c40f..2c816714 100644 --- a/tests/test_httpApi.cpp +++ b/tests/test_httpApi.cpp @@ -79,7 +79,7 @@ void initEventListener(){ //请勿覆盖Connection、Content-Length键 //键名覆盖时不区分大小写 headerOut["TestHeader"] = "HeaderValue"; - invoker("200 OK",headerOut,contentOut); + invoker(200,headerOut,contentOut); }); }); }, nullptr);