# HTTP API #### 介绍 HTTP 代表超文本传输​​协议,是整个互联网的基础通信协议。即使这是您第一次使用 HTTP,您的理解可能比您意识到的要多。在最基本的层面上,HTTP 的工作原理如下: - “服务器 XYZ 您好,请问有文件 abc.html” - “你好,小客户,是的,可以,就是这里” 在 PHP 中发送 HTTP 请求有许多不同的方法。WordPress HTTP API 的目的是支持尽可能多的方法,并使用最适合特定请求的方法。 WordPress HTTP API 还可用于与其他 API(例如 Twitter API 或 Google Maps API)进行通信和交互。 #### HTTP 方法 HTTP 有多种方法或动词来描述特定类型的操作。虽然还有更多功能,但 WordPress 已经为其中三个最常见的功能预先构建了功能。每当发出 HTTP 请求时,也会传递一个方法来帮助服务器确定客户端请求的操作类型。 #### 得到 GET 用于检索数据。这是迄今为止最常用的动词。每次您查看网站或从 API 提取数据时,您都会看到 GET 请求的结果。事实上,您的浏览器向您正在阅读本文的服务器发送了一个 GET 请求,并请求用于构建这篇文章的数据。 #### 邮政 POST 用于将数据发送到服务器,以便服务器以某种方式执行操作。例如,联系表。当您在表单字段中输入数据并单击提交按钮时,浏览器会获取数据并向服务器发送 POST 请求,其中包含您在表单中输入的文本。服务器将从那里处理联系请求。 #### 头 HEAD 的知名度远不如其他两个。HEAD 本质上与 GET 请求相同,只是它不检索数据,仅检索有关数据的信息。这些数据描述了诸如数据上次更新的时间、客户端是否应该缓存数据、数据是什么类型等信息。现代浏览器经常向您以前访问过的页面发送 HEAD 请求,以确定是否有任何更新。如果没有,您实际上可能会看到以前下载的页面副本,而不是不必要地使用带宽拉入同一副本。 所有好的 API 客户端在执行 GET 请求之前都会利用 HEAD,以节省带宽。虽然如果 HEAD 表示有新数据,则需要两个单独的 HTTP 请求,但 GET 请求的数据大小可能非常大。仅当 HEAD 表示数据是新的或不应缓存时才使用 GET 将有助于节省昂贵的带宽和加载时间。 #### 自定义方法 还有其他 HTTP 方法,例如 PUT、DELETE、TRACE 和 CONNECT。本文不会介绍这些方法,因为在 WordPress 中没有预先构建的方法来使用它们,而且实现它们的 API 也并不常见。 根据服务器的配置方式,您还可以实现自己的其他 HTTP 方法。超出标准方法总是一场赌博,并且对创建客户端来使用您的网站或 API 的其他开发人员造成巨大的潜在限制,但是您可以在 WordPress 中使用您希望的任何方法。我们将在本文中简要介绍如何做到这一点。 #### 响应代码 HTTP 使用数字和字符串响应代码。下面是标准响应代码,而不是对每个代码进行冗长的解释。您可以在创建 API 时定义自己的响应代码,但是除非您需要支持特定类型的响应,否则最好坚持使用标准代码。自定义代码通常在 1xx 范围内。 #### 代码类 通过三位数代码中最左边的数字可以快速看出响应的类型。
状态码描述
2xx请求成功
3xx请求被重定向到另一个 URL
4xx由于客户端错误,请求失败。通常身份验证无效或数据丢失
5xx由于服务器错误,请求失败。配置文件通常丢失或配置错误
**通用代码** 这些是您会遇到的最常见的代码。
状态码描述
200确定 – 请求成功
301资源已永久移动
第302章资源已暂时移动
403禁止 – 通常是由于无效的身份验证
404找不到资源
500内部服务器错误
503暂停服务
#### 从 API 获取数据 [GitHub](https://github.com/ "GitHub")提供了一个优秀的 API,许多公共方面不需要应用程序注册,因此为了演示其中一些方法,示例将针对 GitHub API。 通过该功能,在 WordPress 中获取数据变得异常简单`wp_remote_get()`。该函数采用以下两个参数: 1. $url – 从中检索数据的资源。这必须是标准 HTTP 格式 2. $args – 可选 – 您可以在此处传递一组参数来更改行为和标头,例如 cookie、跟随重定向等。 假定以下默认值,但可以通过 $args 参数更改它们: - 方法——GET - timeout – 5 – 放弃之前等待多长时间 - 重定向 – 5 – 遵循重定向的次数。 - http版本 – 1.0 - blocking – true – 页面的其余部分是否应该等待完成加载,直到此操作完成? - 标题 – array() - 正文 – 空 - cookie – 数组() 让我们使用 GitHub 用户帐户的 URL 看看我们可以获得什么类型的信息
```php $response = wp_remote_get( 'https://api.github.com/users/blobaugh' ); ``` $response 将包含有关我们请求的所有标头、内容和其他元数据
```php Array( [headers] => Array( [server] => nginx [date] => Fri, 05 Oct 2012 04:43:50 GMT [content-type] => application/json; charset=utf-8 [connection] => close [status] => 200 OK [vary] => Accept [x-ratelimit-remaining] => 4988 [content-length] => 594 [last-modified] => Fri, 05 Oct 2012 04:39:58 GMT [etag] => "5d5e6f7a09462d6a2b473fb616a26d2a" [x-github-media-type] => github.beta [cache-control] => public, s-maxage=60, max-age=60 [x-content-type-options] => nosniff [x-ratelimit-limit] => 5000 ) [body] => {"type":"User","login":"blobaugh","gravatar_id":"f25f324a47a1efdf7a745e0b2e3c878f","public_gists":1,"followers":22,"created_at":"2011-05-23T21:38:50Z","public_repos":31,"email":"ben@lobaugh.net","hireable":true,"blog":"http://ben.lobaugh.net","bio":null,"following":30,"name":"Ben Lobaugh","company":null,"avatar_url":"https://secure.gravatar.com/avatar/f25f324a47a1efdf7a745e0b2e3c878f?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png","id":806179,"html_url":"https://github.com/blobaugh","location":null,"url":"https://api.github.com/users/blobaugh"} [response] => Array( [preserved_text 5237511b45884ac6db1ff9d7e407f225 /] => 200 [message] => OK ) [cookies] => Array() [filename] => ) ``` 与前两个函数一样,可以在此函数上使用所有相同的辅助函数。这里的例外是 HEAD 永远不会返回主体,因此该元素将始终为空。 #### 获得您一直想要的身体 只能使用 来取回尸体`wp_remote_retrieve_body()`。该函数仅采用一个参数,即来自任何其他[wp\_remote\_X](https://developer.wordpress.org/?s=wp_remote_&post_type%5B%5D=wp-parser-function)函数的响应,其中检索不是下一个值。
```php $response = wp_remote_get( 'https://api.github.com/users/blobaugh' ); $body = wp_remote_retrieve_body( $response ); ``` 仍然使用上一个示例中的 GitHub 资源,$body 将是
```php {"type":"User","login":"blobaugh","public_repos":31,"gravatar_id":"f25f324a47a1efdf7a745e0b2e3c878f","followers":22,"avatar_url":"https://secure.gravatar.com/avatar/f25f324a47a1efdf7a745e0b2e3c878f?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png","public_gists":1,"created_at":"2011-05-23T21:38:50Z","email":"ben@lobaugh.net","following":30,"name":"Ben Lobaugh","company":null,"hireable":true,"id":806179,"html_url":"https://github.com/blobaugh","blog":"http://ben.lobaugh.net","location":null,"bio":null,"url":"https://api.github.com/users/blobaugh"} ``` 如果除了获取正文之外,您没有对响应执行任何其他操作,您可以将代码减少到一行
```php $body = wp_remote_retrieve_body( wp_remote_get( 'https://api.github.com/users/blobaugh' ) ); ``` 许多这些辅助函数都可以类似地在一行中使用。 #### 获取响应代码 您可能需要检查响应代码以确保检索成功。这可以通过以下函数完成`wp_remote_retrieve_response_code()`:
```php $response = wp_remote_get( 'https://api.github.com/users/blobaugh' ); $http_code = wp_remote_retrieve_response_code( $response ); ``` 如果成功`$http_code`将包含`200`. #### 获取特定标头 如果您希望检索特定标头(例如上次修改的标头),您可以使用`wp_remote_retrieve_header()`. 该函数有两个参数 1. `$response`– get 调用的响应 2. `$header`– 要检索的标头名称 检索最后修改的标头
```php $response = wp_remote_get( 'https://api.github.com/users/blobaugh' ); $last_modified = wp_remote_retrieve_header( $response, 'last-modified' ); ``` `$last_modified`将包含`[last-modified] => Fri, 05 Oct 2012 04:39:58 GMT` 您还可以使用 检索数组中的所有标头`wp_remote_retrieve_headers( $response )`。 #### 使用基本身份验证获取 更安全的 API 提供多种不同类型的身份验证中的一种或多种。一种常见但安全性不高的身份验证方法是 HTTP 基本身份验证。`wp_remote_get()`通过将“授权”传递给函数的第二个参数以及其他 HTTP 方法函数,可以在 WordPress 中使用它。
```php $args = array( 'headers' => array( 'Authorization' => 'Basic ' . base64_encode( YOUR_USERNAME . ':' . YOUR_PASSWORD ) ) ); wp_remote_get( $url, $args ); ``` #### 将数据发布到 API 相同的帮助器方法(`wp_remote_retrieve_body()`等)可用于所有 HTTP 方法调用,并以相同的方式使用。 POST 数据是使用该`wp_remote_post()`函数完成的,并且采用与 完全相同的参数`wp_remote_get()`。这里需要注意的是,第二个参数需要传入数组中的所有元素。Codex 提供了默认的可接受值。您现在只需要关心正在发送的数据,因此其他值将被默认。 要将数据发送到服务器,您需要构建一个关联的数据数组。该数据将被分配给`'body'`值。从服务器端来看,该值将`$_POST`如您所期望的那样出现在变量中。即如果`body => array( 'myvar' => 5 )`在服务器上`$_POST['myvar'] = 5`。 由于 GitHub 不允许 POST 到上一示例中使用的 API,因此本示例将假装允许。通常,如果您想要将数据发布到 API,您需要联系 API 的维护者并获取 API 密钥或某种其他形式的身份验证令牌。这只是证明您的应用程序可以像用户登录网站一样操作 API 上的数据。 假设我们正在提交包含以下字段的联系表单:姓名、电子邮件、主题、评论。要设置主体,我们执行以下操作:
```php $body = array( 'name' => 'Jane Smith', 'email' => 'some@email.com', 'subject' => 'Checkout this API stuff', 'comment' => 'I just read a great tutorial. You gotta check it out!', ); ``` 现在我们需要设置将传递给第二个参数的其余值`wp_remote_post()`
```php $args = array( 'body' => $body, 'timeout' => '5', 'redirection' => '5', 'httpversion' => '1.0', 'blocking' => true, 'headers' => array(), 'cookies' => array(), ); ``` 然后当然要打电话
```php $response = wp_remote_post( 'http://your-contact-form.com', $args ); ``` #### 减少带宽使用 在检索资源之前使用 HEAD 检查资源状态可能非常重要,有时 API 也要求这样做。在高流量 API 上,GET 通常限制为每分钟或每小时的请求数量。甚至不需要尝试 GET 请求,除非 HEAD 请求显示 API 上的数据已更新。 如前所述,HEAD 包含有关数据是否已更新、是否应缓存数据、缓存副本何时过期以及有时对 API 请求的速率限制的数据。 回到 GitHub 示例,这里有一些需要注意的标头。大多数标头都是标准的,但您应该始终检查 API 文档,以确保您了解哪些标头的名称及其用途。 - `x-ratelimit-limit`– 一段时间内允许的请求数 - `x-ratelimit-remaining`– 时间段内剩余可用请求数 - `content-length`– 内容有多大(以字节为单位)。如果内容相当大,可以用于警告用户 - `last-modified`– 上次修改资源的时间。对于缓存工具非常有用 - `cache-control`– 客户端应该如何处理缓存 下面将检查我的 GitHub 用户帐户的 HEAD 值:
```php $response = wp_remote_head( 'https://api.github.com/users/blobaugh' ); ``` $response 应该类似于
```php Array( [headers] => Array ( [server] => nginx [date] => Fri, 05 Oct 2012 05:21:26 GMT [content-type] => application/json; charset=utf-8 [connection] => close [status] => 200 OK [vary] => Accept [x-ratelimit-remaining] => 4982 [content-length] => 594 [last-modified] => Fri, 05 Oct 2012 04:39:58 GMT [etag] => "5d5e6f7a09462d6a2b473fb616a26d2a" [x-github-media-type] => github.beta [cache-control] => public, s-maxage=60, max-age=60 [x-content-type-options] => nosniff [x-ratelimit-limit] => 5000 ) [body] => [response] => Array ( [preserved_text 39a8515bd2dce2aa06ee8a2a6656b1de /] => 200 [message] => OK ) [cookies] => Array( ) [filename] => ) ``` 与前两个函数一样,可以在此函数上使用所有相同的辅助函数。这里的例外是 HEAD 永远不会返回主体,因此该元素将始终为空。 #### 提出任何类型的请求 如果您需要使用上述任何功能都不支持的 HTTP 方法发出请求,请不要惊慌。开发 WordPress 的伟大人们已经想到了这一点并热情地提供了`wp_remote_request()`。此函数采用与 相同的两个参数`wp_remote_get()`,并且还允许您指定 HTTP 方法。您需要传递哪些数据取决于您的方法。 要发送 DELETE 方法示例,您可能有类似于以下内容的内容:
```php $args = array( 'method' => 'DELETE', ); $response = wp_remote_request( 'http://some-api.com/object/to/delete', $args ); ``` #### 缓存简介 缓存是一种实践,将常用的对象或需要大量时间构建的对象保存到快速对象存储中,以便在以后的请求时快速检索。这样就无需花费时间再次获取和构建对象。缓存是一个广泛的主题,是网站优化的一部分,可以单独包含在整个系列文章中。下面只是对缓存的介绍,以及快速为 API 响应设置缓存的简单而有效的方法。 为什么要缓存 API 响应?好吧,房间里的大大象是因为外部 API 降低了您网站的速度。许多顾问会告诉您,利用外部 API 可以减少连接量和执行的处理量以及昂贵的带宽,从而提高网站的性能,但有时事实并非如此。 这是服务器发送数据的速度与远程服务器处理请求、构建数据并将其发回所需的时间之间的良好平衡行为。第二个明显的方面是,许多 API 在一段时间内的请求数量有限,并且可能限制应用程序一次的连接数量。缓存通过在服务器上放置数据副本直至需要刷新来帮助解决这些难题。 #### 什么时候应该缓存? 对此的简单回答是“总是”,但有时您不应该这样做。如果您正在处理实时数据或 API 明确表示不要在标头中缓存,您可能不想缓存,但对于所有其他情况,缓存从 API 检索的任何资源通常是一个好主意。 #### WordPress 瞬变 WordPress Transients 提供了一种存储和使用缓存对象的便捷方法。瞬态会持续指定的时间,或者直到 API 中的资源更新后您需要它们过期为止。在 WordPress 中使用瞬态功能可能是您遇到过的最容易使用的缓存系统。只需三个函数即可为您完成所有繁重的工作。 #### 缓存一个对象(设置一个瞬态) 缓存对象是通过该`set_transient()`函数完成的。该函数采用以下三个参数: 1. `$transient`– 瞬态名称以供将来参考 2. `$value`– 瞬态值 3. `$expiration`– 从保存瞬态到过期需要多少秒 将上面的 GitHub 用户信息响应缓存一小时的示例是
```php $response = wp_remote_get( 'https://api.github.com/users/blobaugh' ); set_transient( 'prefix_github_userinfo', $response, 60 * 60 ); ``` #### 获取缓存对象(获取瞬态) 获取缓存对象比设置瞬态对象要复杂得多。您需要请求瞬态,但您还需要检查该瞬态是否已过期,如果已过期,则获取更新的数据。通常`set_transient()`调用是在调用内部进行的`get_transient()`。以下是获取 GitHub 用户配置文件的瞬态数据的示例:
```php $github_userinfo = get_transient( 'prefix_github_userinfo' ); if ( false === $github_userinfo ) { // Transient expired, refresh the data $response = wp_remote_get( 'https://api.github.com/users/blobaugh' ); set_transient( 'prefix_github_userinfo', $response, HOUR_IN_SECONDS ); } // Use $github_userinfo as you will ``` #### 删除缓存对象(删除瞬态) 删除缓存对象是所有瞬态函数中最简单的,只需向其传递瞬态名称的参数即可完成。 删除 Github 用户信息:
```php delete_transient( 'blobaugh_github_userinfo' ); ``` [有关瞬态的更多信息可以在此处](https://developer.wordpress.org/apis/handbook/transients/)找到。