2019-08-08 19:01:45 +08:00
/*
2023-12-09 16:23:51 +08:00
* Copyright ( c ) 2016 - present The ZLMediaKit project authors . All Rights Reserved .
2020-04-04 20:30:09 +08:00
*
2023-12-09 16:23:51 +08:00
* This file is part of ZLMediaKit ( https : //github.com/ZLMediaKit/ZLMediaKit).
2020-04-04 20:30:09 +08:00
*
2023-12-09 16:23:51 +08:00
* Use of this source code is governed by MIT - like license that can be found in the
2020-04-04 20:30:09 +08:00
* 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 .
*/
2017-05-05 18:02:54 +08:00
2019-01-16 14:26:06 +08:00
# include <cstdlib>
2021-12-17 17:48:05 +08:00
# include "Util/base64.h"
2017-05-05 18:02:54 +08:00
# include "HttpClient.h"
2019-06-28 16:48:02 +08:00
# include "Common/config.h"
2017-05-05 18:02:54 +08:00
2022-02-02 20:34:50 +08:00
using namespace std ;
using namespace toolkit ;
2018-10-24 17:17:55 +08:00
namespace mediakit {
2017-05-05 18:02:54 +08:00
2022-01-19 22:50:44 +08:00
void HttpClient : : sendRequest ( const string & url ) {
2021-12-24 11:22:17 +08:00
clearResponse ( ) ;
_url = url ;
2023-06-10 12:28:49 +08:00
auto protocol = findSubString ( url . data ( ) , NULL , " :// " ) ;
2022-05-08 16:33:33 +08:00
uint16_t port ;
2021-12-24 11:22:17 +08:00
bool is_https ;
2018-11-27 11:05:44 +08:00
if ( strcasecmp ( protocol . data ( ) , " http " ) = = 0 ) {
2022-05-08 16:33:33 +08:00
port = 80 ;
2021-12-24 11:22:17 +08:00
is_https = false ;
2018-11-27 11:05:44 +08:00
} else if ( strcasecmp ( protocol . data ( ) , " https " ) = = 0 ) {
2022-05-08 16:33:33 +08:00
port = 443 ;
2021-12-24 11:22:17 +08:00
is_https = true ;
2018-09-23 21:10:17 +08:00
} else {
2021-12-24 11:22:17 +08:00
auto strErr = StrPrinter < < " 非法的http url: " < < url < < endl ;
2017-05-05 18:02:54 +08:00
throw std : : invalid_argument ( strErr ) ;
}
2018-09-23 21:10:17 +08:00
2023-06-10 12:28:49 +08:00
auto host = findSubString ( url . data ( ) , " :// " , " / " ) ;
2017-05-05 18:02:54 +08:00
if ( host . empty ( ) ) {
2023-06-10 12:28:49 +08:00
host = findSubString ( url . data ( ) , " :// " , NULL ) ;
2017-05-05 18:02:54 +08:00
}
2023-06-10 12:28:49 +08:00
_path = findSubString ( url . data ( ) , host . data ( ) , NULL ) ;
2017-05-05 18:02:54 +08:00
if ( _path . empty ( ) ) {
_path = " / " ;
}
2024-09-19 14:53:50 +08:00
// 重新设置header, 防止上次请求的header干扰 [AUTO-TRANSLATED:d8d06841]
// Reset the header to prevent interference from the previous request's header
2022-01-11 10:44:49 +08:00
_header = _user_set_header ;
2021-12-17 17:48:05 +08:00
auto pos = host . find ( ' @ ' ) ;
if ( pos ! = string : : npos ) {
2024-09-19 14:53:50 +08:00
// 去除?后面的字符串 [AUTO-TRANSLATED:0ccb41c2]
// Remove the string after the "?"
2021-12-17 17:48:05 +08:00
auto authStr = host . substr ( 0 , pos ) ;
host = host . substr ( pos + 1 , host . size ( ) ) ;
_header . emplace ( " Authorization " , " Basic " + encodeBase64 ( authStr ) ) ;
}
2020-11-21 22:16:58 +08:00
auto host_header = host ;
2022-05-08 16:33:33 +08:00
splitUrl ( host , host , port ) ;
2020-11-21 22:16:58 +08:00
_header . emplace ( " Host " , host_header ) ;
2021-12-24 11:22:17 +08:00
_header . emplace ( " User-Agent " , kServerName ) ;
2019-06-13 18:39:57 +08:00
_header . emplace ( " Accept " , " */* " ) ;
_header . emplace ( " Accept-Language " , " zh-CN,zh;q=0.8 " ) ;
2023-12-01 17:56:08 +08:00
if ( _http_persistent ) {
_header . emplace ( " Connection " , " keep-alive " ) ;
} else {
_header . emplace ( " Connection " , " close " ) ;
}
_http_persistent = true ;
2018-09-23 21:10:17 +08:00
if ( _body & & _body - > remainSize ( ) ) {
2019-06-13 18:39:57 +08:00
_header . emplace ( " Content-Length " , to_string ( _body - > remainSize ( ) ) ) ;
2024-04-20 22:25:21 +08:00
GET_CONFIG ( string , charSet , Http : : kCharSet ) ;
_header . emplace ( " Content-Type " , " application/x-www-form-urlencoded; charset= " + charSet ) ;
2017-05-05 18:02:54 +08:00
}
2021-12-24 11:22:17 +08:00
bool host_changed = ( _last_host ! = host + " : " + to_string ( port ) ) | | ( _is_https ! = is_https ) ;
_last_host = host + " : " + to_string ( port ) ;
_is_https = is_https ;
2018-09-24 00:50:02 +08:00
2021-12-24 11:22:17 +08:00
auto cookies = HttpCookieStorage : : Instance ( ) . get ( _last_host , _path ) ;
2018-09-24 00:50:02 +08:00
_StrPrinter printer ;
2021-09-30 16:10:09 +08:00
for ( auto & cookie : cookies ) {
2018-09-24 00:50:02 +08:00
printer < < cookie - > getKey ( ) < < " = " < < cookie - > getVal ( ) < < " ; " ;
}
2021-09-30 16:10:09 +08:00
if ( ! printer . empty ( ) ) {
2018-09-24 00:50:02 +08:00
printer . pop_back ( ) ;
2019-06-13 18:39:57 +08:00
_header . emplace ( " Cookie " , printer ) ;
2018-09-24 00:50:02 +08:00
}
2023-12-01 17:56:08 +08:00
if ( ! alive ( ) | | host_changed | | ! _http_persistent ) {
2023-12-01 14:33:07 +08:00
if ( isUsedProxy ( ) ) {
_proxy_connected = false ;
startConnect ( _proxy_host , _proxy_port , _wait_header_ms / 1000.0f ) ;
2023-11-23 11:09:01 +08:00
} else {
2023-12-01 14:33:07 +08:00
startConnect ( host , port , _wait_header_ms / 1000.0f ) ;
2023-11-23 11:09:01 +08:00
}
2023-12-01 14:33:07 +08:00
} else {
SockException ex ;
onConnect_l ( ex ) ;
2017-05-05 18:02:54 +08:00
}
}
2021-09-30 16:10:09 +08:00
void HttpClient : : clear ( ) {
2021-12-22 11:33:40 +08:00
_url . clear ( ) ;
2022-01-11 10:44:49 +08:00
_user_set_header . clear ( ) ;
2021-09-30 16:10:09 +08:00
_body . reset ( ) ;
_method . clear ( ) ;
2025-04-10 15:09:46 +08:00
// 重置代理连接状态
_proxy_connected = false ;
2021-12-22 11:33:40 +08:00
clearResponse ( ) ;
}
void HttpClient : : clearResponse ( ) {
2021-12-24 13:10:52 +08:00
_complete = false ;
2022-01-19 22:50:44 +08:00
_header_recved = false ;
2021-12-24 11:22:17 +08:00
_recved_body_size = 0 ;
_total_body_size = 0 ;
2023-06-10 11:04:52 +08:00
_parser . clear ( ) ;
2021-12-24 11:22:17 +08:00
_chunked_splitter = nullptr ;
2022-01-19 22:50:44 +08:00
_wait_header . resetTime ( ) ;
_wait_body . resetTime ( ) ;
_wait_complete . resetTime ( ) ;
2021-09-30 16:10:09 +08:00
HttpRequestSplitter : : reset ( ) ;
}
void HttpClient : : setMethod ( string method ) {
_method = std : : move ( method ) ;
}
void HttpClient : : setHeader ( HttpHeader header ) {
2022-01-11 10:44:49 +08:00
_user_set_header = std : : move ( header ) ;
2021-09-30 16:10:09 +08:00
}
HttpClient & HttpClient : : addHeader ( string key , string val , bool force ) {
if ( ! force ) {
2022-01-11 10:44:49 +08:00
_user_set_header . emplace ( std : : move ( key ) , std : : move ( val ) ) ;
2021-09-30 16:10:09 +08:00
} else {
2022-01-11 10:44:49 +08:00
_user_set_header [ std : : move ( key ) ] = std : : move ( val ) ;
2021-09-30 16:10:09 +08:00
}
return * this ;
}
void HttpClient : : setBody ( string body ) {
_body . reset ( new HttpStringBody ( std : : move ( body ) ) ) ;
}
void HttpClient : : setBody ( HttpBody : : Ptr body ) {
_body = std : : move ( body ) ;
}
const Parser & HttpClient : : response ( ) const {
return _parser ;
}
2022-01-20 14:48:45 +08:00
ssize_t HttpClient : : responseBodyTotalSize ( ) const {
return _total_body_size ;
}
size_t HttpClient : : responseBodySize ( ) const {
return _recved_body_size ;
}
2021-09-30 16:10:09 +08:00
const string & HttpClient : : getUrl ( ) const {
return _url ;
}
2017-05-05 18:02:54 +08:00
2018-09-23 21:10:17 +08:00
void HttpClient : : onConnect ( const SockException & ex ) {
2021-12-22 11:33:40 +08:00
onConnect_l ( ex ) ;
}
void HttpClient : : onConnect_l ( const SockException & ex ) {
2018-09-23 21:10:17 +08:00
if ( ex ) {
2022-01-20 14:48:45 +08:00
onResponseCompleted_l ( ex ) ;
2018-09-23 21:10:17 +08:00
return ;
}
2018-06-21 14:03:43 +08:00
_StrPrinter printer ;
2024-09-19 14:53:50 +08:00
// 不使用代理或者代理服务器已经连接成功 [AUTO-TRANSLATED:e051567c]
// No proxy is used or the proxy server has connected successfully
2023-11-23 11:09:01 +08:00
if ( _proxy_connected | | ! isUsedProxy ( ) ) {
printer < < _method + " " < < _path + " HTTP/1.1 \r \n " ;
for ( auto & pr : _header ) {
printer < < pr . first + " : " ;
printer < < pr . second + " \r \n " ;
}
_header . clear ( ) ;
_path . clear ( ) ;
} else {
printer < < " CONNECT " < < _last_host < < " HTTP/1.1 \r \n " ;
2025-04-10 15:09:46 +08:00
printer < < " Host: " < < _last_host < < " \r \n " ;
printer < < " User-Agent: " < < kServerName < < " \r \n " ;
2023-11-23 11:09:01 +08:00
printer < < " Proxy-Connection: keep-alive \r \n " ;
if ( ! _proxy_auth . empty ( ) ) {
printer < < " Proxy-Authorization: Basic " < < _proxy_auth < < " \r \n " ;
}
2017-05-05 18:02:54 +08:00
}
2020-04-23 17:50:12 +08:00
SockSender : : send ( printer < < " \r \n " ) ;
2019-05-29 18:08:50 +08:00
onFlush ( ) ;
2017-05-05 18:02:54 +08:00
}
2018-09-23 21:10:17 +08:00
void HttpClient : : onRecv ( const Buffer : : Ptr & pBuf ) {
2022-01-19 22:50:44 +08:00
_wait_body . resetTime ( ) ;
2019-03-27 10:01:18 +08:00
HttpRequestSplitter : : input ( pBuf - > data ( ) , pBuf - > size ( ) ) ;
2017-05-05 18:02:54 +08:00
}
2023-04-28 22:03:16 +08:00
void HttpClient : : onError ( const SockException & ex ) {
2023-12-01 17:56:08 +08:00
if ( ex . getErrCode ( ) = = Err_reset & & _allow_resend_request & & _http_persistent & & _recved_body_size = = 0 & & ! _header_recved ) {
2024-09-19 14:53:50 +08:00
// 连接被重置,可能是服务器主动断开了连接, 或者服务器内核参数或防火墙的持久连接空闲时间超时或不一致. [AUTO-TRANSLATED:8a78f452]
// The connection was reset, possibly because the server actively closed the connection, or the server kernel parameters or firewall's persistent connection idle timeout or inconsistency.
// 如果是持久化连接,那么我们可以通过重连来解决这个问题 [AUTO-TRANSLATED:6c113e17]
// If it is a persistent connection, we can solve this problem by reconnecting
2023-12-01 17:56:08 +08:00
// The connection was reset, possibly because the server actively disconnected the connection,
// or the persistent connection idle time of the server kernel parameters or firewall timed out or inconsistent.
// If it is a persistent connection, then we can solve this problem by reconnecting
WarnL < < " http persistent connect reset, try reconnect " ;
_http_persistent = false ;
sendRequest ( _url ) ;
return ;
}
2022-01-20 14:48:45 +08:00
onResponseCompleted_l ( ex ) ;
2017-05-05 18:02:54 +08:00
}
2021-01-19 16:05:38 +08:00
ssize_t HttpClient : : onRecvHeader ( const char * data , size_t len ) {
2023-06-10 12:22:28 +08:00
_parser . parse ( data , len ) ;
2023-06-10 11:04:52 +08:00
if ( _parser . status ( ) = = " 302 " | | _parser . status ( ) = = " 301 " | | _parser . status ( ) = = " 303 " ) {
auto new_url = Parser : : mergeUrl ( _url , _parser [ " Location " ] ) ;
2021-12-24 11:22:17 +08:00
if ( new_url . empty ( ) ) {
2022-01-20 14:48:45 +08:00
throw invalid_argument ( " 未找到Location字段(跳转url) " ) ;
2019-07-01 09:53:58 +08:00
}
2023-06-10 11:04:52 +08:00
if ( onRedirectUrl ( new_url , _parser . status ( ) = = " 302 " ) ) {
2022-01-19 22:50:44 +08:00
HttpClient : : sendRequest ( new_url ) ;
2019-07-01 20:55:31 +08:00
return 0 ;
}
2019-07-01 09:53:58 +08:00
}
2020-04-20 18:13:45 +08:00
checkCookie ( _parser . getHeader ( ) ) ;
2023-06-10 11:04:52 +08:00
onResponseHeader ( _parser . status ( ) , _parser . getHeader ( ) ) ;
2022-01-19 22:50:44 +08:00
_header_recved = true ;
2018-09-23 21:19:24 +08:00
2021-09-30 16:10:09 +08:00
if ( _parser [ " Transfer-Encoding " ] = = " chunked " ) {
2024-09-19 14:53:50 +08:00
// 如果Transfer-Encoding字段等于chunked, 则认为后续的content是不限制长度的 [AUTO-TRANSLATED:ebbcb35c]
// If the Transfer-Encoding field is equal to chunked, it is considered that the subsequent content is unlimited in length
2021-12-24 11:22:17 +08:00
_total_body_size = - 1 ;
_chunked_splitter = std : : make_shared < HttpChunkedSplitter > ( [ this ] ( const char * data , size_t len ) {
2021-09-30 16:10:09 +08:00
if ( len > 0 ) {
2022-01-20 14:48:45 +08:00
_recved_body_size + = len ;
onResponseBody ( data , len ) ;
2021-09-30 16:10:09 +08:00
} else {
2022-01-20 14:48:45 +08:00
_total_body_size = _recved_body_size ;
2023-02-20 10:52:00 +08:00
if ( _recved_body_size > 0 ) {
onResponseCompleted_l ( SockException ( Err_success , " success " ) ) ;
2023-12-09 16:23:51 +08:00
} else {
2023-02-20 10:52:00 +08:00
onResponseCompleted_l ( SockException ( Err_other , " no body " ) ) ;
}
2018-11-13 23:59:06 +08:00
}
} ) ;
2024-09-19 14:53:50 +08:00
// 后续为源源不断的body [AUTO-TRANSLATED:bf551bbd]
// The following is a continuous body
2022-01-20 14:48:45 +08:00
return - 1 ;
}
if ( ! _parser [ " Content-Length " ] . empty ( ) ) {
2024-09-19 14:53:50 +08:00
// 有Content-Length字段时忽略onResponseHeader的返回值 [AUTO-TRANSLATED:50380ba8]
// Ignore the return value of onResponseHeader when there is a Content-Length field
2022-01-20 14:48:45 +08:00
_total_body_size = atoll ( _parser [ " Content-Length " ] . data ( ) ) ;
} else {
_total_body_size = - 1 ;
2018-11-13 23:59:06 +08:00
}
2025-06-30 20:46:18 +08:00
if ( _total_body_size = = 0 | | _method = = " HEAD " ) {
2024-09-19 14:53:50 +08:00
// 后续没content, 本次http请求结束 [AUTO-TRANSLATED:8532172f]
// There is no content afterwards, this http request ends
2023-04-28 01:33:17 +08:00
onResponseCompleted_l ( SockException ( Err_success , " The request is successful but has no body " ) ) ;
2018-09-23 21:19:24 +08:00
return 0 ;
}
2018-09-23 21:10:17 +08:00
2024-09-19 14:53:50 +08:00
// 当_total_body_size != 0时到达这里, 代表后续有content [AUTO-TRANSLATED:3a55b268]
// When _total_body_size != 0, it means there is content afterwards
// 虽然我们在_total_body_size >0 时知道content的确切大小, [AUTO-TRANSLATED:af91f74f]
// Although we know the exact size of the content when _total_body_size > 0,
// 但是由于我们没必要等content接收完毕才回调onRecvContent(因为这样浪费内存并且要多次拷贝数据) [AUTO-TRANSLATED:fd71692c]
// But because we don't need to wait for the content to be received before calling onRecvContent (because this wastes memory and requires multiple data copies)
// 所以返回-1代表我们接下来分段接收content [AUTO-TRANSLATED:388756f6]
// So returning -1 means we will receive the content in segments next
2021-12-24 11:22:17 +08:00
_recved_body_size = 0 ;
2018-09-23 21:10:17 +08:00
return - 1 ;
}
2021-01-17 18:31:50 +08:00
void HttpClient : : onRecvContent ( const char * data , size_t len ) {
2021-12-24 11:22:17 +08:00
if ( _chunked_splitter ) {
_chunked_splitter - > input ( data , len ) ;
2018-11-13 23:59:06 +08:00
return ;
}
2022-01-20 14:48:45 +08:00
_recved_body_size + = len ;
2021-12-24 11:22:17 +08:00
if ( _total_body_size < 0 ) {
2024-09-19 14:53:50 +08:00
// 不限长度的content [AUTO-TRANSLATED:325a9dbc]
// Unlimited length content
2022-01-20 14:48:45 +08:00
onResponseBody ( data , len ) ;
2018-11-13 22:50:43 +08:00
return ;
}
2024-09-19 14:53:50 +08:00
// 固定长度的content [AUTO-TRANSLATED:4d169746]
// Fixed length content
2022-01-20 14:48:45 +08:00
if ( _recved_body_size < ( size_t ) _total_body_size ) {
2024-09-19 14:53:50 +08:00
// content还未接收完毕 [AUTO-TRANSLATED:b30ca92c]
// Content has not been received yet
2022-01-20 14:48:45 +08:00
onResponseBody ( data , len ) ;
2018-11-13 22:50:43 +08:00
return ;
}
2022-01-20 14:48:45 +08:00
if ( _recved_body_size = = ( size_t ) _total_body_size ) {
2024-09-19 14:53:50 +08:00
// content接收完毕 [AUTO-TRANSLATED:e730ea8c]
// Content received
2022-01-20 14:48:45 +08:00
onResponseBody ( data , len ) ;
2023-04-28 01:33:17 +08:00
onResponseCompleted_l ( SockException ( Err_success , " completed " ) ) ;
2022-01-20 14:48:45 +08:00
return ;
2018-09-23 21:10:17 +08:00
}
2022-01-20 14:48:45 +08:00
2024-09-19 14:53:50 +08:00
// 声明的content数据比真实的小, 断开链接 [AUTO-TRANSLATED:38204302]
// The declared content data is smaller than the real one, disconnect
2022-01-20 14:48:45 +08:00
onResponseBody ( data , len ) ;
throw invalid_argument ( " http response content size bigger than expected " ) ;
2017-05-05 18:02:54 +08:00
}
2018-06-21 14:03:43 +08:00
2019-05-29 18:08:50 +08:00
void HttpClient : : onFlush ( ) {
2021-12-24 11:22:17 +08:00
GET_CONFIG ( uint32_t , send_buf_size , Http : : kSendBufSize ) ;
2018-09-23 21:10:17 +08:00
while ( _body & & _body - > remainSize ( ) & & ! isSocketBusy ( ) ) {
2021-12-24 11:22:17 +08:00
auto buffer = _body - > readData ( send_buf_size ) ;
2018-09-23 21:10:17 +08:00
if ( ! buffer ) {
2024-09-19 14:53:50 +08:00
// 数据发送结束或读取数据异常 [AUTO-TRANSLATED:75179972]
// Data transmission ends or data reading exception
2018-06-21 14:03:43 +08:00
break ;
}
2018-09-23 21:10:17 +08:00
if ( send ( buffer ) < = 0 ) {
2024-09-19 14:53:50 +08:00
// 发送数据失败, 不需要回滚数据, 因为发送前已经通过isSocketBusy()判断socket可写 [AUTO-TRANSLATED:30762202]
// Data transmission failed, no need to roll back data, because the socket is writable before sending
// 所以发送缓存区肯定未满,该buffer肯定已经写入socket [AUTO-TRANSLATED:769fff52]
// So the send buffer is definitely not full, this buffer must have been written to the socket
2018-06-21 14:03:43 +08:00
break ;
}
}
}
void HttpClient : : onManager ( ) {
2024-09-19 14:53:50 +08:00
// onManager回调在连接中或已连接状态才会调用 [AUTO-TRANSLATED:acf86dce]
// The onManager callback is only called when the connection is in progress or connected
2022-01-19 22:50:44 +08:00
if ( _wait_complete_ms > 0 ) {
2024-09-19 14:53:50 +08:00
// 设置了总超时时间 [AUTO-TRANSLATED:ac47c234]
// Total timeout is set
2022-01-19 22:50:44 +08:00
if ( ! _complete & & _wait_complete . elapsedTime ( ) > _wait_complete_ms ) {
2024-09-19 14:53:50 +08:00
// 等待http回复完毕超时 [AUTO-TRANSLATED:711ebc7b]
// Timeout waiting for http reply to finish
2022-01-19 22:50:44 +08:00
shutdown ( SockException ( Err_timeout , " wait http response complete timeout " ) ) ;
return ;
}
return ;
2018-06-21 14:03:43 +08:00
}
2024-09-19 14:53:50 +08:00
// 未设置总超时时间 [AUTO-TRANSLATED:a936338f]
// Total timeout is not set
2022-01-19 22:50:44 +08:00
if ( ! _header_recved ) {
2024-09-19 14:53:50 +08:00
// 等待header中 [AUTO-TRANSLATED:f8635de6]
// Waiting for header
2022-01-19 22:50:44 +08:00
if ( _wait_header . elapsedTime ( ) > _wait_header_ms ) {
2024-09-19 14:53:50 +08:00
// 等待header中超时 [AUTO-TRANSLATED:860d3a16]
// Timeout waiting for header
2022-01-19 22:50:44 +08:00
shutdown ( SockException ( Err_timeout , " wait http response header timeout " ) ) ;
return ;
}
} else if ( _wait_body_ms > 0 & & _wait_body . elapsedTime ( ) > _wait_body_ms ) {
2024-09-19 14:53:50 +08:00
// 等待body中, 等待超时 [AUTO-TRANSLATED:f9bb1d66]
// Waiting for body, timeout
2022-01-19 22:50:44 +08:00
shutdown ( SockException ( Err_timeout , " wait http response body timeout " ) ) ;
return ;
2018-06-21 14:03:43 +08:00
}
}
2022-01-20 14:48:45 +08:00
void HttpClient : : onResponseCompleted_l ( const SockException & ex ) {
if ( _complete ) {
return ;
}
2021-12-24 13:10:52 +08:00
_complete = true ;
2022-01-19 22:50:44 +08:00
_wait_complete . resetTime ( ) ;
2022-01-20 14:48:45 +08:00
if ( ! ex ) {
2024-09-19 14:53:50 +08:00
// 确认无疑的成功 [AUTO-TRANSLATED:e1db8ce2]
// Confirmed success
2022-01-20 14:48:45 +08:00
onResponseCompleted ( ex ) ;
return ;
}
2024-09-19 14:53:50 +08:00
// 可疑的失败 [AUTO-TRANSLATED:1258a436]
// Suspicious failure
2022-01-20 14:48:45 +08:00
2022-01-24 10:48:15 +08:00
if ( _total_body_size > 0 & & _recved_body_size > = ( size_t ) _total_body_size ) {
2024-09-19 14:53:50 +08:00
// 回复header中有content-length信息, 那么收到的body大于等于声明值则认为成功 [AUTO-TRANSLATED:2f813650]
// If the response header contains content-length information, then the received body is considered successful if it is greater than or equal to the declared value
2023-04-28 01:33:17 +08:00
onResponseCompleted ( SockException ( Err_success , " read body completed " ) ) ;
2022-01-20 14:48:45 +08:00
return ;
}
if ( _total_body_size = = - 1 & & _recved_body_size > 0 ) {
2024-09-19 14:53:50 +08:00
// 回复header中无content-length信息, 那么收到一点body也认为成功 [AUTO-TRANSLATED:6c0e87fc]
// If the response header does not contain content-length information, then receiving any body is considered successful
2022-01-20 14:48:45 +08:00
onResponseCompleted ( SockException ( Err_success , ex . what ( ) ) ) ;
return ;
}
2024-09-19 14:53:50 +08:00
// 确认无疑的失败 [AUTO-TRANSLATED:33b216d9]
// Confirmed failure
2022-01-20 14:48:45 +08:00
onResponseCompleted ( ex ) ;
2018-09-23 21:10:17 +08:00
}
2021-12-24 13:10:52 +08:00
bool HttpClient : : waitResponse ( ) const {
return ! _complete & & alive ( ) ;
}
2022-01-19 22:50:44 +08:00
bool HttpClient : : isHttps ( ) const {
return _is_https ;
}
2019-03-14 09:59:07 +08:00
void HttpClient : : checkCookie ( HttpClient : : HttpHeader & headers ) {
2018-09-24 00:50:02 +08:00
//Set-Cookie: IPTV_SERVER=8E03927B-CC8C-4389-BC00-31DBA7EC7B49;expires=Sun, Sep 23 2018 15:07:31 GMT;path=/index/api/
2021-09-30 16:10:09 +08:00
for ( auto it_set_cookie = headers . find ( " Set-Cookie " ) ; it_set_cookie ! = headers . end ( ) ; + + it_set_cookie ) {
auto key_val = Parser : : parseArgs ( it_set_cookie - > second , " ; " , " = " ) ;
2019-06-13 11:45:13 +08:00
HttpCookie : : Ptr cookie = std : : make_shared < HttpCookie > ( ) ;
2021-12-24 11:22:17 +08:00
cookie - > setHost ( _last_host ) ;
2019-06-13 11:45:13 +08:00
int index = 0 ;
auto arg_vec = split ( it_set_cookie - > second , " ; " ) ;
for ( string & key_val : arg_vec ) {
2023-06-10 12:28:49 +08:00
auto key = findSubString ( key_val . data ( ) , NULL , " = " ) ;
auto val = findSubString ( key_val . data ( ) , " = " , NULL ) ;
2019-06-13 11:45:13 +08:00
2021-09-30 16:10:09 +08:00
if ( index + + = = 0 ) {
cookie - > setKeyVal ( key , val ) ;
2019-06-13 11:45:13 +08:00
continue ;
}
2018-09-25 09:26:23 +08:00
2021-09-30 16:10:09 +08:00
if ( key = = " path " ) {
2019-06-13 11:45:13 +08:00
cookie - > setPath ( val ) ;
continue ;
}
2019-03-14 09:59:07 +08:00
2021-09-30 16:10:09 +08:00
if ( key = = " expires " ) {
cookie - > setExpires ( val , headers [ " Date " ] ) ;
2019-06-13 11:45:13 +08:00
continue ;
}
2019-03-14 09:59:07 +08:00
}
2021-09-30 16:10:09 +08:00
if ( ! ( * cookie ) ) {
2024-09-19 14:53:50 +08:00
// 无效的cookie [AUTO-TRANSLATED:5f06aec8]
// Invalid cookie
2019-03-14 09:59:07 +08:00
continue ;
2018-09-24 00:50:02 +08:00
}
2019-06-13 11:45:13 +08:00
HttpCookieStorage : : Instance ( ) . set ( cookie ) ;
2018-09-24 00:50:02 +08:00
}
}
2022-01-19 22:50:44 +08:00
void HttpClient : : setHeaderTimeout ( size_t timeout_ms ) {
CHECK ( timeout_ms > 0 ) ;
_wait_header_ms = timeout_ms ;
}
void HttpClient : : setBodyTimeout ( size_t timeout_ms ) {
_wait_body_ms = timeout_ms ;
}
void HttpClient : : setCompleteTimeout ( size_t timeout_ms ) {
_wait_complete_ms = timeout_ms ;
}
2023-11-23 11:09:01 +08:00
bool HttpClient : : isUsedProxy ( ) const {
return _used_proxy ;
}
bool HttpClient : : isProxyConnected ( ) const {
return _proxy_connected ;
}
void HttpClient : : setProxyUrl ( string proxy_url ) {
_proxy_url = std : : move ( proxy_url ) ;
if ( ! _proxy_url . empty ( ) ) {
parseProxyUrl ( _proxy_url , _proxy_host , _proxy_port , _proxy_auth ) ;
_used_proxy = true ;
} else {
_used_proxy = false ;
}
}
bool HttpClient : : checkProxyConnected ( const char * data , size_t len ) {
2025-04-10 15:09:46 +08:00
string response ( data , len ) ;
if ( response . find ( " HTTP/1.1 200 " ) ! = string : : npos | | response . find ( " HTTP/1.0 200 " ) ! = string : : npos ) {
_proxy_connected = true ;
return true ;
}
_proxy_connected = false ;
return false ;
2023-11-23 11:09:01 +08:00
}
2023-12-01 17:56:08 +08:00
void HttpClient : : setAllowResendRequest ( bool allow ) {
_allow_resend_request = allow ;
}
2021-12-17 17:48:05 +08:00
} /* namespace mediakit */