介绍
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
GET用于检索数据。这是迄今为止最常用的动词。每次查看网站或从API中提取数据时,都会看到GET请求的结果。事实上,你的浏览器向你正在阅读这篇文章的服务器发送了一个GET请求,并要求提供用于构建这篇文章的数据。
POST
POST用于将数据发送到服务器,以便服务器以某种方式进行操作。例如,联系人表单。当您在表单字段中输入数据并单击“提交”按钮时,浏览器会获取数据并将POST请求与您在表单中输入的文本一起发送到服务器。服务器将从那里处理联系人请求。
HEAD
HEAD的知名度远不如其他两个。HEAD本质上与GET请求相同,只是它不检索数据,只检索有关数据的信息。这些数据描述了数据上次更新的时间、客户端是否应缓存数据、数据类型等。现代浏览器通常会向您以前访问过的页面发送HEAD请求,以确定是否有任何更新。如果没有,您可能实际上看到的是以前下载的页面副本,而不是不必要地使用带宽拉入同一副本。
所有好的API客户端在执行GET请求之前都会使用HEAD,以潜在地节省带宽。虽然如果HEAD说有新数据,则需要两个单独的HTTP请求,但GET请求的数据量可能非常大。只有在HEAD说数据是新的或不应该缓存时才使用GET,这将有助于节省昂贵的带宽和加载时间。
自定义方法
还有其他HTTP方法,例如PUT、DELETE、TRACE和CONNECT。本文将不讨论这些方法,因为在WordPress中没有预构建的方法来使用它们,API实现它们也不常见。
根据服务器的配置方式,您还可以实现自己的其他HTTP方法。跳出标准方法始终是一场冒险,并对其他开发人员创建客户端以使用您的站点或API施加了巨大的潜在限制,然而,您可以使用WordPress的任何方法。在本文中,我们将简要介绍如何做到这一点。
响应(Response)代码
HTTP同时利用数字和字符串响应代码。以下是标准响应代码,而不是对每种代码进行冗长的解释。您可以在创建API时定义自己的响应代码,但是,除非您需要支持特定类型的响应,否则最好坚持使用标准代码。自定义代码通常在1xx范围内。
代码分类
响应类型可以通过三位代码中最左边的数字快速看到。
状态码 | 描述 |
---|---|
2xx | 请求成功 |
3xx | 请求被重定向到另一个URL |
4xx | 由于客户端错误,请求失败。通常是无效的认证或丢失数据 |
5xx | 请求因服务器错误而失败。常见的是丢失或配置错误的配置文件 |
常见代码
这些是您将遇到的最常见的代码。
状态码 | 描述 |
---|---|
200 | OK - 请求成功 |
301 | 资源被永久地移动了 |
302 | 资源被暂时移动 |
403 | 禁止 - 通常是由于无效的认证 |
404 | 没有找到资源 |
500 | 内部服务器错误 |
503 | 服务不可用 |
从API获取数据
GitHub提供了一个优秀的API,在很多公共方面不需要应用注册,因此为了演示其中一些方法,示例将针对GitHub API。
在WordPress中,通过wp_remote_get()
函数获取数据非常简单。此函数有以下两个参数:
- $url – 从中检索数据的资源,必须是标准HTTP格式
- $args – 可选 – 您可以在这里传递一个参数数组来改变行为和header,例如cookie、遵循重定向等。
假设以下默认值,但可以通过$args参数进行更改:
- method – GET
- timeout – 5 – 放弃前等待多长时间
- redirection – 5 – 遵循重定向的次数
- httpversion – 1.0
- blocking – true – 页面的其余部分是否应等待完成加载,直到此操作完成?
- headers – array()
- body – null
- cookies – array()
让我们使用GitHub用户帐户的URL,看看可以获得什么样的信息
$response = wp_remote_get( 'https://api.github.com/users/blobaugh' );
$response 将包含关于我们的请求的所有header、内容和其他元数据
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] => )
获取你想要的body
只需使用wp_remote_retrieve_body()
检索body。该函数只接受一个参数,即来自任何其他 wp_remote_X 函数的响应,其中retrieve不是下一个值。
$response = wp_remote_get( 'https://api.github.com/users/blobaugh' ); $body = wp_remote_retrieve_body( $response );
仍然使用上一个示例中的GitHub资源,$body将得到
{"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"}
如果除了获取body之外,没有任何其他操作要对响应执行,那么可以使用
$body = wp_remote_retrieve_body( wp_remote_get( 'https://api.github.com/users/blobaugh' ) );
许多辅助函数可以在一行代码上类似地使用。
获取响应代码
您可能需要检查响应代码以确保检索成功。这可以通过wp_remote_retrieve_response_code()
函数完成:
$response = wp_remote_get( 'https://api.github.com/users/blobaugh' ); $http_code = wp_remote_retrieve_response_code( $response );
如果成功,$http_code
将包含200
。
获取特定header
如果您希望检索特定的header,比如最后修改时间,那么可以使用wp_remote_retrieve_header()
。此函数采用两个参数
$response
– GET调用的响应$header
– 要检索的header的名称
检索上次修改的header
$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 )
检索数组中的所有header。
使用基本身份验证的GET
安全的API提供了多种不同类型的身份验证中的一种或多种。一种常见但安全性不高的身份验证方法是HTTP基本身份验证。它可以通过将“Authorization”传递给wp_remote_get()
函数的第二个参数以及其他HTTP方法函数在WordPress中使用。
$args = array( 'headers' => array( 'Authorization' => 'Basic ' . base64_encode( YOUR_USERNAME . ':' . YOUR_PASSWORD ) ) ); wp_remote_get( $url, $args );
将数据POST到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,因此本示例将假设它允许。通常,如果您想将数据POST到API,您需要联系API的维护人员,并获取API密钥或其他形式的身份验证令牌。这仅仅证明了您的应用程序可以像用户登录网站一样操作API上的数据。
假设我们正在提交一份包含以下字段的联系表单:姓名、电子邮件、主题、评论。要设置body,我们需要执行以下操作:
$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()
的第二个参数的其余值
$args = array( 'body' => $body, 'timeout' => '5', 'redirection' => '5', 'httpversion' => '1.0', 'blocking' => true, 'headers' => array(), 'cookies' => array(), );
那么当然要调用了
$response = wp_remote_post( 'http://your-contact-form.com', $args );
HEAD减少带宽使用
在检索资源之前,使用HEAD检查资源状态可能非常重要,有时API会要求这样做。在高流量API上,GET通常限制为每分钟或每小时的请求数。甚至不需要尝试GET请求,除非HEAD请求显示API上的数据已更新。
如前所述,HEAD包含有关数据是否已更新、是否应缓存数据、缓存副本何时过期以及有时对API请求的速率限制的数据。
回到GitHub示例,这里有几个需要注意的header。这些header中的大多数都是标准的,但您应该始终检查API文档,以确保您了解哪些header被命名为什么,以及它们的用途。
x-ratelimit-limit
– 一段时间内允许的请求数x-ratelimit-remaining
– 时间段内剩余可用请求的数量content-length
– 内容的大小(字节),如果内容相当大,可以警告用户last-modified
– 上次修改资源的时间,对缓存工具非常有用cache-control
– 客户端应该如何处理缓存
以下内容将检查我的GitHub用户帐户的HEAD值:
$response = wp_remote_head( 'https://api.github.com/users/blobaugh' );
$response应该类似于
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永远不会返回body,所以元素总是空的。
任意请求方法
如果需要使用上述任何函数都不支持的HTTP方法发出请求,请不要死机。WordPress杰出的开发人员已经想到了这一点,并热情地提供了wp_remote_request()
。该函数采用与wp_remote_get()
相同的两个参数,并允许您指定HTTP方法。您需要传递什么数据取决于您的方法。
要发送DELETE方法示例,您可能需要类似以下内容:
$args = array( 'method' => 'DELETE', ); $response = wp_remote_request( 'http://some-api.com/object/to/delete', $args );
缓存简介
缓存是一种做法,将常用对象或需要大量时间构建的对象保存到快速对象存储中,以便在以后的请求中快速检索。这可以避免再次花费时间获取和构建对象。缓存是一个庞大的主题,它是网站优化的一部分,可以单独包含在整个系列的文章中。接下来的内容只是对缓存的介绍,以及为API响应快速设置缓存的简单而有效的方法。
为什么要缓存API响应?嗯,一个很关键的原因是外部API拖慢了你的网站。许多顾问会告诉你,利用外部API可以减少连接量和处理量,以及昂贵的带宽,从而提高网站的性能,但有时情况并非如此。
在服务器发送数据的速度和远程服务器处理请求、生成数据并将其发回所需的时间之间,这是一种很好的平衡。第二个引人注目的方面是,许多API在一个时间段内的请求数量有限,并且可能限制应用程序一次连接的数量。缓存通过将数据的副本放置在服务器上,直到需要刷新为止,从而帮助解决这些难题。
你应该什么时候缓存
简单的答案是“总是”,但也有一些时候你不应该这样做。如果您正在处理实时数据,或者API在header中特别指出不要缓存,您可能不想缓存,但对于所有其他情况,通常最好缓存从API检索的任何资源。
WordPress Transients(瞬态)
WordPress瞬态提供了一种存储和使用缓存对象的方便方法。瞬态存在一段指定的时间,或者直到您需要它们在API中的资源更新后过期。在WordPress中使用瞬态功能可能是您遇到过的最容易使用的缓存系统。仅三个函数就可以帮助你完成所有繁重的工作。
缓存对象(设置瞬态)
缓存对象是通过set_transient()
函数完成的。此函数采用以下三个参数:
$transient
– 瞬态名称,供之后参考$value
– 瞬态值$expiration
– 从保存瞬态到其过期的时间是多少秒
将上面的GitHub用户信息响应缓存一小时的示例如下:
$response = wp_remote_get( 'https://api.github.com/users/blobaugh' ); set_transient( 'prefix_github_userinfo', $response, 60 * 60 );
获取缓存对象(获取瞬态)
获取缓存对象比设置瞬态要复杂得多。您需要请求瞬态,但还需要检查瞬态是否已过期,如果已过期,请获取更新的数据。通常,set_transient()
调用在get_transient()
调用内部进行。以下是获取GitHub用户信息的瞬态数据的示例:
$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用户信息:
delete_transient( 'blobaugh_github_userinfo' );
有关瞬态的更多信息,请参见此处。