cURL - 学习/实践

1.应用场景

用于文件传输, 发送请求等网络通信等 [PRC 进程远程调用/微服务~] -- RPC也不是就一定不能使用http协议

可用于篡改参数,发送请求,比如要测试某个功能, 是否能正常响应。

Note:

熟练地使用cURL能帮助我们极大地提高工作效率【开发/测试】 // 20210115 家里

2.学习/操作

1. 文档阅读

 <<PHP核心技术与最佳实践>> -- 列旭松, 陈文

PHP: cURL - Manual  //php扩展curl的用法

PHP: curl_setopt - Manual  //setopt的选项详细用法

https://www.php.cn/php-weizijiaocheng-403656.html  //php中cURL的使用方法 --  实践一遍, 会有初步认识.

https://www.php.cn/php-weizijiaocheng-393305.html  //PHP中使用CURL之php curl详细解析和常见大坑

https://PHP: addslashes - Manualwww.php.net/manual/zh/function.strip-tags.php  //strip_tags()

// 下面的函数用法,有些不是很熟悉

https://www.php.net/manual/zh/function.addslashes.php  // addslashes()

https://www.php.net/manual/zh/function.urlencode.php // urlencode()

https://www.php.net/manual/zh/function.tempnam.php  // tempnam()

https://www.php.net/manual/zh/function.iconv.php // iconv()

https://www.php.net/manual/zh/function.mb-convert-encoding.php // mb_convert_encoding()

PHP: curl_multi_init - Manual

2. 整理输出

2.1 介绍

英文介绍:

PHP supports libcurl, a library created by Daniel Stenberg, that allows you to connect and communicate to many different types of servers with many different types of protocols. libcurl currently supports the http, https, ftp, gopher, telnet, dict, file, and ldap protocols. libcurl also supports HTTPS certificates, HTTP POST, HTTP PUT, FTP uploading (this can also be done with PHP's ftp extension), HTTP form based upload, proxies, cookies, and user+password authentication.

中文翻译

PHP支持Daniel Stenberg创建的libcurl库,它允许您使用许多不同类型的协议与许多不同类型的服务器进行连接和通信。libcurl目前支持http、https、ftp、gopher、telnet、dict、文件和ldap协议。libcurl还支持HTTPS证书、HTTP POST、HTTP PUT、FTP上传(这也可以通过PHP的FTP扩展来实现)、基于HTTP表单的上传、代理、cookie和用户+密码认证。

简单地说

curl是一个库,能让你通过URL和许多不同种的服务器进行勾搭、搭讪和深入交流,并且还支持许多协议。

Note

说了那么多其实没什么感觉,在应用中才有感觉,起初也是需要在服务器端向另一个服务器发起一个POST请求才开始接触curl的.  

2.2 操作

1). 安装cURL

curl - Download // 下载地址,一般操作会自带,如果没有,下载安装即可

2). curl命令支持各种请求
curl - Tutorial -- 查阅

curl localhost:8088/head --head
curl localhost:8088/get
curl -X POST localhost:8088/post
curl -X PUT localhost:8088/put
curl -X PATCH localhost:8088/patch
curl -X DELETE localhost:8088/delete
curl -X OPTIONS localhost:8088/options

Golang api testing

➜  gin-demo curl localhost:8088/head --head
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Date: Thu, 24 Feb 2022 06:16:43 GMT
Content-Length: 16

➜  gin-demo curl localhost:8088/get
HTTP GET Method%                                                                                                                                                     
➜  gin-demo curl -X POST localhost:8088/post
HTTP POST Method%                                                                                                                                                    
➜  gin-demo curl -X PUT localhost:8088/put
HTTP PUT Method%                                                                                                                                                     
➜  gin-demo curl -X PATCH localhost:8088/patch
HTTP PATCH Method%                                                                                                                                                   
➜  gin-demo curl -X DELETE localhost:8088/delete
HTTP DELETE Method%                                                                                                                                                  
➜  gin-demo curl -X OPTIONS localhost:8088/options
HTTP OPTIONS Method%                                                                                                                                                 
➜  gin-demo 

GET请求 // 正常执行

POST请求

curl -H 'Content-Type: application/json' -X POST -d '{"name":"XBox","price":3999}' http://localhost:3000/api/products

截图:win10 下

请求出现问题!

原因与解决方式: 

在cmd环境下的输入:{\"userName\":\"helo\",\"id\":1} 双引号要转义, 且不能使用单引号.

Git bash中 // POST请求

Postman中 // POST请求

Note

更加复杂的请求,也是处理有余.

插入 //  20210115 家里

同时借助Chrome devTools, 可以做很多事情,如下:

拷贝之后,便可以在相应的终端窗口中执行,很方便~

其他请求方式

PHP代码实现方式参考

https://github.com/ningxiaofa/learning_of_php/tree/master/curl // PHP curl practice

https://github.com/ningxiaofa/learning_of_php/blob/master/curl/cURL-request-motheds.php

Code

<?php

/** 
检测 curl扩展是否打开,  避免报错.
因为curl是php的扩展,有的主机为了安全会禁用curl.
另外php本地调试的时候也是关闭curl的,所以会发生报错.
 */


if(!function_exists('curl_init')){
    die('please open curl extension of php first.');
} else {
    echo '已经加载php curl 扩展.';
}

// get 请求
function geturl($url){
        $headerArray = array("Content-type:application/json;", "Accept:application/json");
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); 
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); 
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch,CURLOPT_HTTPHEADER,$headerArray);
        $output = curl_exec($ch);
        curl_close($ch);
        $output = json_decode($output, true);
        return $output;
}

// post 请求
function posturl($url, $data){
        $data  = json_encode($data);    
        $headerArray =array("Content-type:application/json;charset='utf-8'", "Accept:application/json");
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST,FALSE);
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        curl_setopt($curl,CURLOPT_HTTPHEADER,$headerArray);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $output = curl_exec($curl);
        curl_close($curl);
        return json_decode($output, true);
}

// put 请求
function puturl($url, $data){
    $data = json_encode($data);
    $ch = curl_init(); //初始化CURL句柄 
    curl_setopt($ch, CURLOPT_URL, $url); //设置请求的URL
    curl_setopt ($ch, CURLOPT_HTTPHEADER, array('Content-type:application/json'));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); //设为TRUE把curl_exec()结果转化为字串,而不是直接输出 
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT"); //设置请求方式
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);//设置提交的字符串
    $output = curl_exec($ch);
    curl_close($ch);
    return json_decode($output,true);
}

// delete 请求
function delurl($url, $data){
    $data  = json_encode($data);
    $ch = curl_init();
    curl_setopt ($ch,CURLOPT_URL, $url);
    curl_setopt ($ch, CURLOPT_HTTPHEADER, array('Content-type:application/json'));
    curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt ($ch, CURLOPT_CUSTOMREQUEST, "DELETE");   
    curl_setopt($ch, CURLOPT_POSTFIELDS,$data);
    $output = curl_exec($ch);
    curl_close($ch);
    $output = json_decode($output,true);
}

// patch 请求
function patchurl($url, $data){
    $data  = json_encode($data);
    $ch = curl_init();
    curl_setopt ($ch,CURLOPT_URL, $url);
    curl_setopt ($ch, CURLOPT_HTTPHEADER, array('Content-type:application/json'));
    curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt ($ch, CURLOPT_CUSTOMREQUEST, "PATCH");  
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);     //20170611修改接口,用/id的方式传递,直接写在url中了
    $output = curl_exec($ch);
    curl_close($ch);
    $output = json_decode($output);
    return $output;
}

3). curl超时控制

https://blog.csdn.net/william_n/article/details/124931236

4). cURL支持并发操作

CURL扩展已支持毫秒配置,将 CURLOPT_TIMEOUT 改为 CURLOPT_TIMEOUT_MS 即可生效

(cURL 版本 >= libcurl/7.21.0,老服务器要检查版本),但还是我前面说的需要服务端配合,

不然接口的调用成功失败不可控。

CURL扩展已支持并发,我们能一次访问N个接口,执行时间取最长接口的时间。

比如我们能一次访问 京东支付(1s),微信支付(1.2s),支付宝(0.8s)不同服务的三个接口,

总耗时才1.2s。

详细用法 curl_multi_init

...

cURL 请求汇总
20220424 周日


1. POSTMAN
在postman中直接copy
curl --location --request POST 'https://dev-api.coolapi.com/search/mentions' \
--header 'x-cool-token: c2b040323f3a68c254a4d42d18804a2f' \
--header 'device-id: 97DAA27580D5420CAF1E0CF48F8ED777' \
--header 'device-type: ios' \
--header 'version-code: 1095' \
--header 'x-cool-userid: BCRdNJx1RUxWThvJ' \
--header 'Content-Type: application/json' \
--data-raw '{
    "keyword": "jak"
}'

回车即正常请求

2. Chrome console中copy的cURL

2.1 带有不同的压缩格式
 curl 'https://dev-liveapi.cool.live/feed/commentlist' \
  -H 'authority: dev-liveapi.cool.live' \
  -H 'accept: application/json, text/plain, */*' \
  -H 'accept-language: zh-CN,zh;q=0.9,en;q=0.8,ja;q=0.7' \
  -H 'content-type: multipart/form-data; boundary=----WebKitFormBoundarySovJ8cI3KpgAs4Yc' \
  -H 'device-id: l2cwql0c' \
  -H 'dnt: 1' \
  -H 'origin: https://react-dev.cool.live' \
  -H 'sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="100", "Google Chrome";v="100"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-platform: "macOS"' \
  -H 'sec-fetch-dest: empty' \
  -H 'sec-fetch-mode: cors' \
  -H 'sec-fetch-site: same-site' \
  -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) \
  Chrome/100.0.4896.127 Safari/537.36' \
  --data-raw $'------WebKitFormBoundarySovJ8cI3KpgAs4Yc\r\nContent-Disposition: form-data; name="feed_id"\r\n\r\n1E895A9CC2A2968F311572678592B351\r\n------WebKitFormBoundarySovJ8cI3KpgAs4Yc--\r\n' \
  --compressed

  执行后,出现如下报错:
  curl: (61) Unrecognized content encoding type. libcurl understands deflate, gzip content encodings.

  原因:
  https://github.com/guzzle/guzzle/issues/2146
  原因输出的错误信息已经说了,这里使用了不能识别的内容编码类型,libcurl只支持deflate, gzip编码类型。

  有说,解决办法
  设置请求头
  "accept-encoding" => "gzip, deflate"
  'decode_content' => false

  -H 'accept-encoding: gzip, deflate' \
  -H 'decode_content: false' \

  实际上未生效,TDB


  真正生效:
  https://cloud.tencent.com/developer/ask/sof/1423531
  取消压缩即可,即删除--compressed
  既然因为压缩编码的问题,那就不要压缩进行编码了,而且只是本地测试接口,没有影响。

2.2 这里虽然进行压缩,默认是采用deflate, gzip方式,可以正常解码解压缩进行响应

curl 'https://zq99299.github.io/note-book/elasticsearch-senior/depth-search/12-dis-max-tie-breaker.html' \
  -H 'Referer: https://www.google.com.hk/' \
  -H 'Upgrade-Insecure-Requests: 1' \
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36' \
  -H 'sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="100", "Google Chrome";v="100"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-platform: "macOS"' \
  --compressed


3. 关于前端请求工具,如postman,请求参数的json字符串中的双引号,根据不同的请求方式,而是否重新转义。。
3.1 application/json -- 不会转义
payload
{
    "is_new_comment": 1,
    "feed_id": "1E895A9CC2A2968F311572678592B351",
    "page": 1,
    "since_id": "{\"created\":1649059510,\"cid\":\"3381D7AA121A91AEE4A25F7CD0525677\",\"fid\":\"1E895A9CC2A2968F311572678592B351\"}"
}

curl --location --request POST 'https://dev-api.coolapi.com/feed/commentlist' \
--header 'x-cool-token: c2b040323f3a68c254a4d42d18804a2f' \
--header 'device-id: C625A84ABD0E441A9CE248FEFFABE9D7' \
--header 'device-type: ios' \
--header 'version-code: 1043' \
--header 'x-cool-userid: BCRdNJx1RUxWThvJ' \
--header 'Content-Type: application/json' \
--data-raw '{
    "is_new_comment": 1,
    "feed_id": "1E895A9CC2A2968F311572678592B351",
    "page": 1,
    "since_id": "{\"created\":1649059510,\"cid\":\"3381D7AA121A91AEE4A25F7CD0525677\",\"fid\":\"1E895A9CC2A2968F311572678592B351\"}"
}'

3.2 form-data 请求方式,而且postman中要post方式,如果json请求方式,get方式也会被传输出去。

正常可直接解析的json
since_id: {"created":1649059550,"cid":"BDD9710FB4C4B68BBBC13AEE3D1A2A0A","fid":"1E895A9CC2A2968F311572678592B351"}

curl如下
...
--header 'sec-fetch-mode: cors' \
--header 'sec-fetch-site: same-site' \
--header 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36' \
--form 'feed_id="1E895A9CC2A2968F311572678592B351"' \
--form 'since_id="{\"created\":1649059550,\"cid\":\"BDD9710FB4C4B68BBBC13AEE3D1A2A0A\",\"fid\":\"1E895A9CC2A2968F311572678592B351\"}"'

如果是已经转义的json字符串,会再次被转义
since_id: "{\"created\":1649059550,\"cid\":\"BDD9710FB4C4B68BBBC13AEE3D1A2A0A\",\"fid\":\"1E895A9CC2A2968F311572678592B351\"}"

curl如下
...
--header 'sec-fetch-mode: cors' \
--header 'sec-fetch-site: same-site' \
--header 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36' \
--form 'feed_id="1E895A9CC2A2968F311572678592B351"' \
--form 'since_id="\"{\\\"created\\\":1649059550,\\\"cid\\\":\\\"BDD9710FB4C4B68BBBC13AEE3D1A2A0A\\\",\\\"fid\\\":\\\"1E895A9CC2A2968F311572678592B351\\\"}\""'

5). curl如何实现异步调用?

PHP - 回调函数概念与用法实例分析 - 学习/实践_穿素白衫的中少年的博客-CSDN博客

后续补充

...

3.问题/补充

1.PHP cURL HTTP CODE return 0

PHP cURL HTTP CODE return 0 - Stack Overflow

简单讲

如果你已经连接到服务器上了,那么你将会返回一个状态码;否则,将会失败并返回一个0, 所以如下:

如果你连接到www.google.com/lksdfk时,你会收到一个400的状态码,

如果你连接到google.com,你会收到一个302的状态码(如果继续访问的话,将会收到200的状态码,因为被重定向到了www.google.com.hk), 

如果你访问googlecom,你会收到一个0状态码,并提示找不到host。

错误的详细原因可以通过函数curl_error()进行查询.

原因可能有: 一次请求多次, 这里超过80个请求[针对第三方服务], 就会导致返回0的状态码.使用curl_error没有错误信息输出[应该是屏蔽掉, 安全处理].

2.为了优化性能,请首先阻止cURL尝试IPv6 // 20200323

更多详细用法:

\CurlModel::setRequestOptions    D:\william\provision\src\papi\app\models\CurlModel.php

# For tune performance, prevent cURL from trying IPv6 first.
curl_setopt($this->request, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);

3.遇到问题

CURL ERROR: SSL certificate problem: unable to get local issuer certificate with https://xxxx.net

解决办法:

方式一: // 不推荐

直接添加两行代码即可, 很简单.

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

方式二:  // 推荐 

这是 SSL 证书问题所致,包括在使用 SDK 调用微信支付等相关的操作时也可能会遇到报 “SSL certificate problem: unable to get local issuer certificate” 的错误。

解决方法:

下载ca证书    http://curl.haxx.se/ca/cacert.pem   进行下载 // 或者 使用微信官方提供的证书中的 CA 证书 rootca.pem

php.ini 中配置 CA 证书

将下载好的ca证书放置到服务器的任意位置 

修改php.ini 文件 找到curl位置 写入

curl.cainfo = /path/to/downloaded/cacert.pem 

重启服务器 

4.参考

参见文档阅读列表

后续补充

...

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值