diff --git a/src/Http/HttpClient.cpp b/src/Http/HttpClient.cpp index 0f010d27..7cd1d890 100644 --- a/src/Http/HttpClient.cpp +++ b/src/Http/HttpClient.cpp @@ -86,6 +86,18 @@ void HttpClient::sendRequest(const string &strUrl, float fTimeOutSec) { _lastHost = host + ":" + to_string(port); _isHttps = isHttps; _fTimeOutSec = fTimeOutSec; + + auto cookies = HttpCookieStorage::Instance().get(_lastHost,_path); + _StrPrinter printer; + for(auto &cookie : cookies){ + printer << cookie->getKey() << "=" << cookie->getVal() << ";"; + } + if(!printer.empty()){ + printer.pop_back(); + _header.emplace(string("Cookie"), printer); + } + + if (!alive() || bChanged) { //InfoL << "reconnet:" << _lastHost; startConnect(host, port, fTimeOutSec); @@ -138,6 +150,7 @@ void HttpClient::onErr(const SockException &ex) { int64_t HttpClient::onRecvHeader(const char *data, uint64_t len) { _parser.Parse(data); onResponseHeader(_parser.Url(), _parser.getValues()); + checkCookie(_parser.getValues()); if(_parser["Content-Length"].empty()){ //没有Content-Length字段 @@ -223,6 +236,33 @@ void HttpClient::onResponseCompleted_l() { onResponseCompleted(); } +void HttpClient::checkCookie(HttpClient::HttpHeader &headers) { + //Set-Cookie: IPTV_SERVER=8E03927B-CC8C-4389-BC00-31DBA7EC7B49;expires=Sun, Sep 23 2018 15:07:31 GMT;path=/index/api/ + auto set_cookie = headers["Set-Cookie"]; + if(set_cookie.empty()){ + return; + } + auto key_val = Parser::parseArgs(set_cookie,";","="); + + HttpCookie::Ptr cookie = std::make_shared(); + cookie->setHost(_lastHost); + + for(auto &pr : key_val){ + if(pr.first == "path"){ + cookie->setPath(pr.second); + }else if(pr.first == "expires"){ + cookie->setExpires(pr.second); + }else{ + cookie->setKeyVal(pr.first,pr.second); + } + } + if(!(*cookie)){ + //无效的cookie + return; + } + HttpCookieStorage::Instance().set(cookie); +} + } /* namespace Http */ } /* namespace ZL */ diff --git a/src/Http/HttpClient.h b/src/Http/HttpClient.h index 4305dd23..4e0c3241 100644 --- a/src/Http/HttpClient.h +++ b/src/Http/HttpClient.h @@ -35,6 +35,7 @@ #include "Util/util.h" #include "Network/TcpClient.h" #include "HttpRequestSplitter.h" +#include "HttpCookie.h" using namespace std; using namespace ZL::Util; @@ -292,6 +293,7 @@ protected: virtual void onManager() override; private: void onResponseCompleted_l(); + void checkCookie(HttpHeader &headers ); protected: bool _isHttps; private: diff --git a/src/Http/HttpCookie.cpp b/src/Http/HttpCookie.cpp new file mode 100644 index 00000000..df4789ed --- /dev/null +++ b/src/Http/HttpCookie.cpp @@ -0,0 +1,79 @@ +// +// Created by xzl on 2018/9/23. +// + +#include "HttpCookie.h" +#include "Util/util.h" +using namespace ZL::Util; + +void HttpCookie::setPath(const string &path){ + _path = path; +} +void HttpCookie::setHost(const string &host){ + _host = host; +} +void HttpCookie::setExpires(const string &expires){ + struct tm tt; + strptime(expires.data(),"%a, %b %d %Y %H:%M:%S %Z",&tt); + _expire = mktime(&tt); +} +void HttpCookie::setKeyVal(const string &key,const string &val){ + _key = key; + _val = val; +} +HttpCookie::operator bool (){ + return !_host.empty() && !_key.empty() && !_val.empty() && (_expire > time(NULL)); +} + +const string &HttpCookie::getVal() const { + return _val; +} + +const string &HttpCookie::getKey() const{ + return _key; +} + + +HttpCookieStorage &HttpCookieStorage::Instance(){ + static HttpCookieStorage instance; + return instance; +} + +void HttpCookieStorage::set(const HttpCookie::Ptr &cookie) { + lock_guard lck(_mtx_cookie); + if(!cookie || !(*cookie)){ + return; + } + _all_cookie[cookie->_host][cookie->_path] = cookie; +} + +vector HttpCookieStorage::get(const string &host, const string &path) { + vector ret(0); + lock_guard lck(_mtx_cookie); + auto it = _all_cookie.find(host); + if(it == _all_cookie.end()){ + return ret; + } + auto &path_cookie = it->second; + + auto lam = [&](const string &sub_path){ + auto it_cookie = path_cookie.find(sub_path); + if(it_cookie != path_cookie.end()){ + if(*(it_cookie->second)){ + ret.emplace_back(it_cookie->second); + }else{ + path_cookie.erase(it_cookie); + } + } + }; + + + int pos = 0; + do{ + auto sub_path = path.substr(0,pos + 1); + lam(sub_path); + pos = path.find('/',1 + pos); + }while (pos != string::npos); + lam(path); + return ret; +} diff --git a/src/Http/HttpCookie.h b/src/Http/HttpCookie.h new file mode 100644 index 00000000..a0f6b4e2 --- /dev/null +++ b/src/Http/HttpCookie.h @@ -0,0 +1,52 @@ +// +// Created by xzl on 2018/9/23. +// + +#ifndef ZLMEDIAKIT_HTTPCOOKIE_H +#define ZLMEDIAKIT_HTTPCOOKIE_H + +#include +#include +#include +#include +#include +using namespace std; + +class HttpCookie { +public: + typedef std::shared_ptr Ptr; + friend class HttpCookieStorage; + HttpCookie(){} + ~HttpCookie(){} + + void setPath(const string &path); + void setHost(const string &host); + void setExpires(const string &expires); + void setKeyVal(const string &key,const string &val); + operator bool (); + + const string &getKey() const ; + const string &getVal() const ; +private: + string _host; + string _path = "/"; + uint32_t _expire = 0; + string _key; + string _val; +}; + + +class HttpCookieStorage{ +public: + ~HttpCookieStorage(){} + static HttpCookieStorage &Instance(); + void set(const HttpCookie::Ptr &cookie); + vector get(const string &host,const string &path); +private: + HttpCookieStorage(){}; +private: + unordered_map > _all_cookie; + mutex _mtx_cookie; +}; + +#endif //ZLMEDIAKIT_HTTPCOOKIE_H