CURLRequest 类

The CURLRequest 类是一个基于 CURL 的轻量级 HTTP 客户端,允许您与其他网站和服务器进行通信。它可以用于获取 Google 搜索的内容,检索网页或图像,或与 API 通信,以及许多其他事情。

此类是根据 Guzzle HTTP 客户端 库建模的,因为它是使用最广泛的库之一。在可能的情况下,语法保持一致,因此如果您的应用程序需要比此库提供的功能更强大的功能,您只需进行很少的更改即可迁移到使用 Guzzle。

注意

此类需要在您的 PHP 版本中安装 cURL 库。这是一个非常常见的库,通常可用,但并非所有主机都提供它,因此如果您遇到问题,请与您的主机联系以确认。

CURLRequest 配置

共享选项

重要

此设置仅为了向后兼容而存在。在新项目中不要使用它。即使您已经在使用它,我们建议您禁用它。

注意

从 v4.4.0 开始,默认值已更改为 false

如果您想在请求之间共享所有选项,请在 app/Config/CURLRequest.php 中将 $shareOptions 设置为 true

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class CURLRequest extends BaseConfig
{
    // ...
    public bool $shareOptions = true;
}

如果您使用类实例发送多个请求,这种行为可能会导致错误请求,其中包含不必要的标头和正文。

注意

在 v4.2.0 之前,即使 $shareOptions 为 false,由于错误,请求正文也不会重置。

加载库

库可以通过手动方式或通过 服务类 加载。

要使用服务类加载,请调用 curlrequest() 方法。

<?php

$client = \Config\Services::curlrequest();

您可以将默认选项数组作为第一个参数传递,以修改 cURL 处理请求的方式。这些选项将在本文档的后面部分进行描述。

<?php

$options = [
    'baseURI' => 'http://example.com/api/v1/',
    'timeout' => 3,
];
$client = \Config\Services::curlrequest($options);

注意

$shareOptions 为 false 时,传递给类构造函数的默认选项将用于所有请求。其他选项将在发送请求后重置。

在手动创建类时,您需要传入一些依赖项。第一个参数是 Config\App 类的实例。第二个参数是 URI 实例。第三个参数是 Response 对象。第四个参数是可选的默认 $options 数组。

<?php

$client = new \CodeIgniter\HTTP\CURLRequest(
    new \Config\App(),
    new \CodeIgniter\HTTP\URI(),
    new \CodeIgniter\HTTP\Response(new \Config\App()),
    $options
);

使用库

使用 CURL 请求只需创建请求并获取 Response 对象。它旨在处理通信。之后,您可以完全控制如何处理信息。

发出请求

大多数通信都是通过 request() 方法完成的,该方法会发出请求,然后返回一个 Response 实例。它将 HTTP 方法、URL 和选项数组作为参数。

<?php

$client = \Config\Services::curlrequest();

$response = $client->request('GET', 'https://api.github.com/user', [
    'auth' => ['user', 'pass'],
]);

重要

默认情况下,如果返回的 HTTP 代码大于或等于 400,CURLRequest 将抛出 HTTPException。如果您想获取响应,请参阅 http_errors 选项。

注意

$shareOptions 为 false 时,传递给方法的选项将用于请求。发送请求后,它们将被清除。如果您想将选项用于所有请求,请在构造函数中传递选项。

由于响应是 CodeIgniter\HTTP\Response 的实例,因此您可以使用所有正常的信息。

<?php

echo $response->getStatusCode();
echo $response->getBody();
echo $response->header('Content-Type');
$language = $response->negotiateLanguage(['en', 'fr']);

虽然 request() 方法是最灵活的,但您也可以使用以下快捷方法。它们都将 URL 作为第一个参数,将选项数组作为第二个参数。

<?php

$client->get('http://example.com');
$client->delete('http://example.com');
$client->head('http://example.com');
$client->options('http://example.com');
$client->patch('http://example.com');
$client->put('http://example.com');
$client->post('http://example.com');

基本 URI

可以在类实例化期间将 baseURI 设置为选项之一。这允许您设置基本 URI,然后使用该客户端使用相对 URL 发出所有请求。这在使用 API 时特别有用。

<?php

$client = \Config\Services::curlrequest([
    'baseURI' => 'https://example.com/api/v1/',
]);

// GET http:example.com/api/v1/photos
$client->get('photos');

// GET http:example.com/api/v1/photos/13
$client->delete('photos/13');

当向 request() 方法或任何快捷方法提供相对 URI 时,它将根据 RFC 2986,第 2 节 中描述的规则与 baseURI 相结合。为了节省您的时间,以下是一些关于组合如何解析的示例。

baseURI

URI

结果

http://foo.com

/bar

http://foo.com/bar

http://foo.com/foo

/bar

http://foo.com/bar

http://foo.com/foo

bar

http://foo.com/bar

http://foo.com/foo/

bar

http://foo.com/foo/bar

http://foo.com

http://baz.com

http://baz.com

http://foo.com/?bar

bar

http://foo.com/bar

使用响应

每个 request() 调用都返回一个 Response 对象,其中包含许多有用的信息和一些有用的方法。最常用的方法可以让您确定响应本身。

您可以获取响应的状态代码和原因短语

<?php

$code   = $response->getStatusCode(); // 200
$reason = $response->getReason(); // OK

您可以从响应中检索标头

<?php

// Get a header line
echo $response->getHeaderLine('Content-Type');

// Get all headers
foreach ($response->headers() as $name => $value) {
    echo $name . ': ' . $response->getHeaderLine($name) . "\n";
}

可以使用 getBody() 方法检索主体

<?php

$body = $response->getBody();

主体是远程服务器提供的原始主体。如果内容类型需要格式化,您需要确保您的脚本处理它。

<?php

if (strpos($response->header('content-type'), 'application/json') !== false) {
    $body = json_decode($body);
}

请求选项

本节描述了您可以传递给构造函数、request() 方法或任何快捷方法的所有可用选项。

allow_redirects

默认情况下,cURL 将遵循远程服务器发回的所有“Location:” 标头。 allow_redirects 选项允许您修改其工作方式。

如果将值设置为 false,则它将完全不遵循任何重定向。

<?php

$client->request('GET', 'http://example.com', ['allow_redirects' => false]);

将其设置为 true 将将默认设置应用于请求。

<?php

$client->request('GET', 'http://example.com', ['allow_redirects' => true]);
/*
 * Sets the following defaults:
 * 'max'       => 5, // Maximum number of redirects to follow before stopping
 * 'strict'    => true, // Ensure POST requests stay POST requests through redirects
 * 'protocols' => ['http', 'https'] // Restrict redirects to one or more protocols
 */

您可以将数组作为 allow_redirects 选项的值传递,以指定新的设置来代替默认设置。

<?php

$client->request('GET', 'http://example.com', ['allow_redirects' => [
    'max'       => 10,
    'protocols' => ['https'], // Force HTTPS domains only.
]]);

注意

当 PHP 处于 safe_mode 或 open_basedir 启用时,重定向不起作用。

auth

允许您为 HTTP BasicDigest 身份验证提供身份验证详细信息。您的脚本可能需要做额外的工作来支持 Digest 身份验证 - 这只是为您传递用户名和密码。该值必须是一个数组,其中第一个元素是用户名,第二个是密码。第三个参数应该是要使用的身份验证类型,可以是 basicdigest

<?php

$client->request('GET', 'http://example.com', ['auth' => ['username', 'password', 'digest']]);

body

对于支持请求主体类型的请求,例如 PUT 或 POST,有两种方法可以设置请求主体。第一种方法是使用 setBody() 方法

<?php

$client->setBody($body)->request('put', 'http://example.com');

第二种方法是传入一个 body 选项。这是为了保持 Guzzle API 的兼容性,并且与前面的示例的功能完全相同。该值必须是字符串

<?php

$client->request('put', 'http://example.com', ['body' => $body]);

cert

要指定 PEM 格式的客户端证书的位置,请将包含文件完整路径的字符串作为 cert 选项的值传递。如果需要密码,请将该值设置为一个数组,第一个元素是证书的路径,第二个元素是密码

<?php

$client->request('get', '/', ['cert' => ['/path/server.pem', 'password']]);

connect_timeout

默认情况下,CodeIgniter 不会对 cURL 连接到网站的尝试设置限制。如果需要修改此值,可以通过 connect_timeout 选项传递以秒为单位的时间量来实现。可以传递 0 表示无限期等待

<?php

$client->request('GET', 'http://example.com', ['connect_timeout' => 0]);

debug

当传递 debug 并将其设置为 true 时,这将启用额外的调试信息,并在脚本执行期间回显到 STDERR。

这是通过传递 CURLOPT_VERBOSE 并回显输出完成的。因此,当通过 spark serve 运行内置服务器时,您将在控制台中看到输出。否则,输出将写入服务器的错误日志。

<?php

$client->request('GET', 'http://example.com', ['debug' => true]);

可以将文件名作为 debug 的值传递,以便将输出写入文件

<?php

$client->request('GET', 'http://example.com', ['debug' => '/usr/local/curl_log.txt']);

delay

允许您在发送请求之前暂停一定数量的毫秒

<?php

// Delay for 2 seconds
$client->request('GET', 'http://example.com', ['delay' => 2000]);

form_params

您可以通过在 form_params 选项中传递一个关联数组,在 application/x-www-form-urlencoded POST 请求中发送表单数据。这将设置 Content-Type 头部为 application/x-www-form-urlencoded,如果它尚未设置。

<?php

$client->request('POST', '/post', [
    'form_params' => [
        'foo' => 'bar',
        'baz' => ['hi', 'there'],
    ],
]);

注意

form_params 不能与 multipart 选项一起使用。您需要使用其中一个。使用 form_params 用于 application/x-www-form-urlencoded 请求,使用 multipart 用于 multipart/form-data 请求。

headers

虽然您可以使用 setHeader() 方法设置此请求所需的任何头部,但您也可以将头部关联数组作为选项传递。每个键都是一个头部的名称,每个值都是一个字符串或字符串数组,表示头部字段值。

<?php

$client->request('get', '/', [
    'headers' => [
        'User-Agent' => 'testing/1.0',
        'Accept'     => 'application/json',
        'X-Foo'      => ['Bar', 'Baz'],
    ],
]);

如果头部传递到构造函数中,它们将被视为默认值,这些默认值将在以后被任何进一步的头部数组或对 setHeader() 的调用覆盖。

http_errors

默认情况下,CURLRequest 如果返回的 HTTP 代码大于或等于 400,将抛出 HTTPException

如果您想查看响应主体,可以将 http_errors 设置为 false 以返回内容。

<?php

$client->request('GET', '/status/500');
// If the response code is 500, an HTTPException is thrown,
// and a detailed error report is displayed if in development mode.

$response = $client->request('GET', '/status/500', ['http_errors' => false]);
echo $response->getStatusCode(); // 500
echo $response->getBody();       // You can see the response body.

json

使用 json 选项可以轻松地将 JSON 编码的数据作为请求主体上传。它会添加一个 application/json 的 Content-Type 头,覆盖任何可能已经设置的 Content-Type。提供给此选项的数据可以是 json_encode() 接受的任何值。

<?php

$response = $client->request('PUT', '/put', ['json' => ['foo' => 'bar']]);

注意

此选项不允许对 json_encode() 函数或 Content-Type 头进行任何自定义。如果您需要这种功能,则需要手动编码数据,通过 CURLRequest 的 setBody() 方法传递它,并使用 setHeader() 方法设置 Content-Type 头。

multipart

当您需要通过 POST 请求发送文件和其他数据时,可以使用 multipart 选项以及 CURLFile 类。这些值应该是一个关联数组,包含要发送的 POST 数据。为了更安全的使用,通过在文件名之前添加 @ 来上传文件的传统方法已被禁用。您要发送的任何文件都必须作为 CURLFile 的实例传递。

<?php

$post_data = [
    'foo'      => 'bar',
    'userfile' => new \CURLFile('/path/to/file.txt'),
];

注意

multipart 不能与 form_params 选项一起使用。您只能使用其中一个。对于 application/x-www-form-urlencoded 请求,使用 form_params,对于 multipart/form-data 请求,使用 multipart

proxy

版本 4.4.0 中的新功能。

您可以通过将关联数组作为 proxy 选项传递来设置代理。

<?php

$client->request(
    'GET',
    'http://example.com',
    ['proxy' => 'https://:3128']
);

查询

您可以通过传递一个关联数组作为 query 选项来传递数据作为查询字符串变量。

<?php

// Send a GET request to /get?foo=bar
$client->request('GET', '/get', ['query' => ['foo' => 'bar']]);

超时

默认情况下,cURL 函数可以无限期运行,没有时间限制。您可以使用 timeout 选项修改此行为。该值应为希望函数执行的秒数。使用 0 表示无限期等待。

<?php

$client->request('GET', 'http://example.com', ['timeout' => 5]);

用户代理

允许指定请求的用户代理。

<?php

$client->request('GET', 'http://example.com', ['user_agent' => 'CodeIgniter Framework v4']);

验证

此选项描述 SSL 证书验证行为。如果 verify 选项为 true,则启用 SSL 证书验证并使用操作系统提供的默认 CA 捆绑包。如果设置为 false,则会禁用证书验证(这很不安全,并且允许中间人攻击!)。您可以将其设置为包含 CA 捆绑包路径的字符串,以使用自定义证书启用验证。默认值为 true。

<?php

// Use the system's CA bundle (this is the default setting)
$client->request('GET', '/', ['verify' => true]);

// Use a custom SSL certificate on disk.
$client->request('GET', '/', ['verify' => '/path/to/cert.pem']);

// Disable validation entirely. (Insecure!)
$client->request('GET', '/', ['verify' => false]);

版本

要设置要使用的 HTTP 协议,您可以传递一个包含版本号的字符串或浮点数(通常是 1.01.12.0 从 v4.3.0 开始支持)。

<?php

// Force HTTP/1.0
$client->request('GET', '/', ['version' => 1.0]);