完成http客户端cookie自动保存和设置

This commit is contained in:
xiongziliang 2018-09-24 00:50:02 +08:00
parent 3579a931a4
commit 8e4a2f25ba
4 changed files with 173 additions and 0 deletions

View File

@ -86,6 +86,18 @@ void HttpClient::sendRequest(const string &strUrl, float fTimeOutSec) {
_lastHost = host + ":" + to_string(port); _lastHost = host + ":" + to_string(port);
_isHttps = isHttps; _isHttps = isHttps;
_fTimeOutSec = fTimeOutSec; _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) { if (!alive() || bChanged) {
//InfoL << "reconnet:" << _lastHost; //InfoL << "reconnet:" << _lastHost;
startConnect(host, port, fTimeOutSec); startConnect(host, port, fTimeOutSec);
@ -138,6 +150,7 @@ void HttpClient::onErr(const SockException &ex) {
int64_t HttpClient::onRecvHeader(const char *data, uint64_t len) { int64_t HttpClient::onRecvHeader(const char *data, uint64_t len) {
_parser.Parse(data); _parser.Parse(data);
onResponseHeader(_parser.Url(), _parser.getValues()); onResponseHeader(_parser.Url(), _parser.getValues());
checkCookie(_parser.getValues());
if(_parser["Content-Length"].empty()){ if(_parser["Content-Length"].empty()){
//没有Content-Length字段 //没有Content-Length字段
@ -223,6 +236,33 @@ void HttpClient::onResponseCompleted_l() {
onResponseCompleted(); 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<HttpCookie>();
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 Http */
} /* namespace ZL */ } /* namespace ZL */

View File

@ -35,6 +35,7 @@
#include "Util/util.h" #include "Util/util.h"
#include "Network/TcpClient.h" #include "Network/TcpClient.h"
#include "HttpRequestSplitter.h" #include "HttpRequestSplitter.h"
#include "HttpCookie.h"
using namespace std; using namespace std;
using namespace ZL::Util; using namespace ZL::Util;
@ -292,6 +293,7 @@ protected:
virtual void onManager() override; virtual void onManager() override;
private: private:
void onResponseCompleted_l(); void onResponseCompleted_l();
void checkCookie(HttpHeader &headers );
protected: protected:
bool _isHttps; bool _isHttps;
private: private:

79
src/Http/HttpCookie.cpp Normal file
View File

@ -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<mutex> lck(_mtx_cookie);
if(!cookie || !(*cookie)){
return;
}
_all_cookie[cookie->_host][cookie->_path] = cookie;
}
vector<HttpCookie::Ptr> HttpCookieStorage::get(const string &host, const string &path) {
vector<HttpCookie::Ptr> ret(0);
lock_guard<mutex> 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;
}

52
src/Http/HttpCookie.h Normal file
View File

@ -0,0 +1,52 @@
//
// Created by xzl on 2018/9/23.
//
#ifndef ZLMEDIAKIT_HTTPCOOKIE_H
#define ZLMEDIAKIT_HTTPCOOKIE_H
#include <string>
#include <memory>
#include <vector>
#include <unordered_map>
#include <mutex>
using namespace std;
class HttpCookie {
public:
typedef std::shared_ptr<HttpCookie> 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<HttpCookie::Ptr> get(const string &host,const string &path);
private:
HttpCookieStorage(){};
private:
unordered_map<string,unordered_map<string,HttpCookie::Ptr> > _all_cookie;
mutex _mtx_cookie;
};
#endif //ZLMEDIAKIT_HTTPCOOKIE_H