HttpClient.h 5.82 KB
Newer Older
xiongziliang committed
1
/*
xiongziliang committed
2 3
 * MIT License
 *
xiongziliang committed
4
 * Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
xiongziliang committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 *
 * This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
xiongziliang committed
26 27 28 29

#ifndef Http_HttpClient_h
#define Http_HttpClient_h

30
#include <stdio.h>
xiongziliang committed
31 32 33 34
#include <string.h>
#include <functional>
#include <memory>
#include "Util/util.h"
xiongziliang committed
35
#include "Util/mini.h"
xiongziliang committed
36
#include "Network/TcpClient.h"
xiongziliang committed
37
#include "Common/Parser.h"
38
#include "HttpRequestSplitter.h"
39
#include "HttpCookie.h"
40
#include "HttpChunkedSplitter.h"
xiongziliang committed
41
#include "strCoding.h"
42
#include "HttpBody.h"
xiongziliang committed
43
using namespace std;
xiongziliang committed
44
using namespace toolkit;
xiongziliang committed
45

xiongziliang committed
46
namespace mediakit {
xiongziliang committed
47

xiongziliang committed
48
class HttpArgs : public map<string, variant, StrCaseCompare>  {
xiongziliang committed
49 50 51 52 53 54 55 56
public:
    HttpArgs(){}
    virtual ~HttpArgs(){}
    string make() const {
        string ret;
        for(auto &pr : *this){
            ret.append(pr.first);
            ret.append("=");
xiongziliang committed
57
            ret.append(strCoding::UrlEncode(pr.second));
xiongziliang committed
58 59 60 61 62 63 64 65
            ret.append("&");
        }
        if(ret.size()){
            ret.pop_back();
        }
        return ret;
    }
};
66

67
class HttpClient : public TcpClient , public HttpRequestSplitter
xiongziliang committed
68 69 70 71 72 73
{
public:
    typedef StrCaseMap HttpHeader;
    typedef std::shared_ptr<HttpClient> Ptr;
    HttpClient();
    virtual ~HttpClient();
xiongziliang committed
74
    virtual void sendRequest(const string &url,float fTimeOutSec);
75 76

    virtual void clear(){
xiongziliang committed
77
        _header.clear();
78
        _body.reset();
xiongziliang committed
79 80 81
        _method.clear();
        _path.clear();
        _parser.Clear();
82 83 84 85 86
        _recvedBodySize = 0;
        _totalBodySize = 0;
        _aliveTicker.resetTime();
        _chunkedSplitter.reset();
        HttpRequestSplitter::reset();
xiongziliang committed
87
    }
88

xiongziliang committed
89 90 91 92
    void setMethod(const string &method){
        _method = method;
    }
    void setHeader(const HttpHeader &header){
xzl committed
93
        _header = header;
xiongziliang committed
94
    }
95 96 97 98 99 100 101
    HttpClient & addHeader(const string &key,const string &val,bool force = false){
        if(!force){
            _header.emplace(key,val);
        }else{
            _header[key] = val;
        }
        return *this;
xiongziliang committed
102 103
    }
    void setBody(const string &body){
104
        _body.reset(new HttpStringBody(body));
105 106
    }
    void setBody(const HttpBody::Ptr &body){
xiongziliang committed
107 108
        _body = body;
    }
xiongziliang committed
109
    const string &responseStatus() const{
xiongziliang committed
110 111
        return _parser.Url();
    }
xiongziliang committed
112
    const HttpHeader &responseHeader() const{
xiongziliang committed
113 114
        return _parser.getValues();
    }
xiongziliang committed
115 116 117
    const Parser& response() const{
        return _parser;
    }
118 119 120 121

    const string &getUrl() const{
        return _url;
    }
xiongziliang committed
122
protected:
123 124 125 126
    /**
     * 收到http回复头
     * @param status 状态码,譬如:200 OK
     * @param headers http头
127 128
     * @return 返回后续content的长度;-1:后续数据全是content;>=0:固定长度content
     *          需要指出的是,在http头中带有Content-Length字段时,该返回值无效
129
     */
130
    virtual int64_t onResponseHeader(const string &status,const HttpHeader &headers){
xiongziliang committed
131
        DebugL << status;
132 133
        //无Content-Length字段时默认后面全是content
        return -1;
xiongziliang committed
134
    };
135 136 137 138 139 140 141 142

    /**
     * 收到http conten数据
     * @param buf 数据指针
     * @param size 数据大小
     * @param recvedSize 已收数据大小(包含本次数据大小),当其等于totalSize时将触发onResponseCompleted回调
     * @param totalSize 总数据大小
     */
143
    virtual void onResponseBody(const char *buf,int64_t size,int64_t recvedSize,int64_t totalSize){
xiongziliang committed
144 145
        DebugL << size << " " <<  recvedSize << " " << totalSize;
    };
146 147

    /**
xiongziliang committed
148
     * 接收http回复完毕,
149
     */
150
    virtual void onResponseCompleted(){
xiongziliang committed
151 152
    	DebugL;
    }
153 154 155 156 157

    /**
     * http链接断开回调
     * @param ex 断开原因
     */
xiongziliang committed
158
    virtual void onDisconnect(const SockException &ex){}
159

160 161 162 163 164 165 166 167
    /**
     * 重定向事件
     * @param url 重定向url
     * @param temporary 是否为临时重定向
     * @return 是否继续
     */
    virtual bool onRedirectUrl(const string &url,bool temporary){ return true;};

168 169 170
    //HttpRequestSplitter override
    int64_t onRecvHeader(const char *data,uint64_t len) override ;
    void onRecvContent(const char *data,uint64_t len) override;
171
protected:
xiongziliang committed
172
    virtual void onConnect(const SockException &ex) override;
173
    virtual void onRecv(const Buffer::Ptr &pBuf) override;
xiongziliang committed
174
    virtual void onErr(const SockException &ex) override;
xiongziliang committed
175
    virtual void onFlush() override;
176
    virtual void onManager() override;
177
private:
178
    void onResponseCompleted_l();
179
    void checkCookie(HttpHeader &headers );
180 181 182
protected:
    bool _isHttps;
private:
183
    string _url;
xiongziliang committed
184
    HttpHeader _header;
185
    HttpBody::Ptr _body;
xiongziliang committed
186 187 188
    string _method;
    string _path;
    //recv
189 190
    int64_t _recvedBodySize;
    int64_t _totalBodySize;
xiongziliang committed
191 192
    Parser _parser;
    string _lastHost;
193 194
    Ticker _aliveTicker;
    float _fTimeOutSec = 0;
195
    std::shared_ptr<HttpChunkedSplitter> _chunkedSplitter;
xiongziliang committed
196 197
};

xiongziliang committed
198
} /* namespace mediakit */
xiongziliang committed
199 200

#endif /* Http_HttpClient_h */