ebredy / apichainning
Requires
- php: >=5.5.0
- ext-json: *
- flow/jsonpath: ^0.4
Requires (Dev)
- phpunit/phpunit: ^7
This package is auto-updated.
Last update: 2024-09-25 07:51:08 UTC
README
目前处于开发中。
要获取更多关于使用模拟 API 链接的示例,请访问 http://api-multi-request.demos.mikestowe.com/
REST API 多请求链接
在使用由超媒体驱动的 RESTful API 以及引入众多和广泛的微服务时,一个挑战是有时需要执行多个 API 调用来完成手头的任务。今天,这也需要许多 HTTP 调用,这取决于延迟,可能会极大地减慢脚本执行。
REST API 多请求链接是一种技术,它将多个 RESTful API 调用组合在一个单一的 HTTP 请求中。
例如,如下所示,您不必执行对 /users/5
和 /messages/?userId=5
的 GET 调用,而可以向类似 /multirequestchain
的资源发送链,该资源将为您处理多个调用。
REST API 多请求链接配置为允许条件调用,并提供所需的数据(而不是每个调用返回的所有数据)。这也可以用作类似于 GraphQL 的数据收集技术,在那里,您不是将对象作为模型嵌入,而是能够一次性执行多个调用并只获取请求的数据。
简单的 REST API 多请求链接
每个链接由5个组件组成,都是必需的
一个简单的请求,您想获取一个用户的消息,但首先需要调用 /users
资源以获取信息,可能看起来像这样
[
{
"doOn": "always",
"url": "/users/5",
"method": "get",
"data": {},
"return": "$.*._links"
},
{
"doOn": 200,
"url" : "$body._links.messages",
"method": "get",
"data": {
"emailAddress": "$body.email"
},
"headers": {
"Cache-Control": "no-cache",
"Connection": "keep-alive"
}
"return": true,
}
]
多个条件调用
REST API 多请求链接按时间顺序工作,每个调用都被视为下一个最高优先级或下一个自然步骤。
doOn
指定是否基于前一个调用的响应执行调用,或者是否跳过包含匹配前一个 HTTP 状态码的 doOn
的另一个调用,应用返回 true 的逻辑 IF 语句,或指定为 "always"。如果在当前操作链层的层面上找不到合适的匹配项,则链将认为这是一个错误并退出,返回所有数据以及包括最后一个尝试的调用。
例如,在我们的上一个链中,如果 /users/5
调用返回 404,则链将退出,为您提供该调用的详细信息,但 不 尝试下一个调用 $body._links.messages
,因为它需要一个状态码为 200。
您还可以通过将它们放在数组中分层多个条件调用,创建一个新层。但是,一旦链达到其子层的末尾,它将退出 - 不 遍历剩余的父层。
[
{
"doOn": "always",
"url": "/users/5",
"method": "get",
"data": {},
"return": [
"email", "_links"
]
},
[
{
"doOn": 200,
"url" : "$body._links.messages",
"method": "get",
"data": {
"emailAddress": "$body.email"
},
"return": true,
},
{
"doOn": "4*|5*",
"url" : "/users",
"method": "post",
"data": {
"firstName": "Jim",
"lastName": "Smith",
"emailAddress": "jim.smith@domain.ext"
},
"return": true,
},
[
{
"doOn": "201",
"url": "$headers.link",
"method": "get",
"data": {},
"return": [
"email", "_links"
]
},
{
"doOn": 200,
"url" : "$body._links.sendMessage",
"method": "post",
"data": {
"to": "$body.email",
"subject": "Welcome $body.firstName",
"body": "Hello and welcome to our site!"
},
"return": true,
}
]
]
]
复杂的 IF 语句
doOn
属性接受 HTTP 状态码、字符串 "always" 或条件逻辑 IF 语句
简单的等于/不等于
AND OR 语句
正则表达式
复杂示例 1
[
{
"doOn": "always",
"url": "/users/5",
"method": "get",
"data": {},
"return": [
"firstName", "lastName", "email", "_links"
]
},
{
"doOn": "($body.firstName == "Jim" && $body.lastName == "Smith") || regex('/Jim/i', $body.email)",
"url" : "$body._links.messages",
"method": "get",
"data": {
"emailAddress": "$body.email"
},
"return": true,
}
]
复杂示例 2
[
{
"doOn": "always",
"url": "https://www.tn-apis.com/catalog/v1/events/${global.eventId}",
"method": "get",
"name": "api:ticketnetwork:catalog:events",
"globals": {},
"data": {},
"headers": {
"Authorization": "Bearer 9750bc1c-178d-36f7-802b-b6b9ebcb3efd",
"x-listing-context": "website-config-id=3551",
"Accept": "application/json"
},
"return": {
"latitudeFromTN": "geoLocation.latitude",
"longitudeFromTN": "geoLocation.longitude",
// custom php callbacks are created with
//and called by prefixing them with callback. An addition any php function
//can be called using the prefix "callback_"
"dateFromTN": "${callback_extract_date(date.datetime,0,10)}",
"timeFromTN": "${callback_format_time(date.text.time)}",
"venueId": "venue.id",
"countryFromTN": "country.alphaCode",
"stateFromTN": "stateProvince.text.abbr",
"eventNameFromTN": "text.name",
"cityFromTN": "city.text.name",
"isResult": "${callback_has_results(venue.id)}"
}
},
{
"doOn": "200",
"url": "https://www.way.com/way-service/home/suggestions",
"method": "post",
"name": "api:way:suggestions",
"data": {
"latitude": "$body.latitudeFromTN",
"longitude": "$body.longitudeFromTN",
"searchQuery": "TNvenue${body.venueId}WAY ${body.dateFromTN} ${body.timeFromTN}",
"serviceType": "PARKING"
},
"headers": {
"Content-Type": "application/json"
},
"return": {
"wayEventId": "response[0].listingIdentifier",
"wayVenueId": "response[0].venueId",
"wayLatitude": "response[0].latitude",
"wayLongitude": "response[0].longitude",
"wayAddressLine1": "response[0].addressBo.addressLine1",
"wayCity": "response[0].addressBo.city.cityName",
"wayState": "response[0].addressBo.state.stateCode",
"wayZipcode": "response[0].addressBo.zipcode.zipcode",
"wayCountry": "response[0].addressBo.country.countryName",
"wayHasResult": "${callback_has_results(response)}"
}
},
{
"doOn": "$body.wayHasResult == true",
"url": "https://www.way.com/way-service/parking/search",
"method": "post",
"name": "api:way:parking:search:events",
"data": {
"eventId": "$body.wayEventId",
"reqType": "jump",
"venueId": "$body.wayVenueId",
"latitude": "$body.wayLatitude",
"longitude": "$body.wayLongitude",
"pageIndex": 1,
"parkingFilter": {
"nearBy": "Event"
},
"numberOfRecords": 10
},
"headers": {
"Content-Type": "application/json"
},
"return": true
}
]
复杂示例 3(使用头/接受:application/xml)
[
{
"doOn": "always",
"url": "https://link-search.api.cj.com/v2/link-search?website-id=9007016&link-type=banner&advertiser-ids=joined",
"method": "get",
"name": "api:cjmanual:v2:linksearch",
"globals": {},
"data": {},
"headers": {
"Authorization": "Bearer 351q6ebydq98pwv1fttxcgpsqs",
"Accept": "application/xml"
},
"return": true
}
]
响应
由于使用 REST API 多请求链接时可能出现条件链接和错误,因此响应对象需要返回三个主要属性
在响应数组中,每个调用对象需要包括
{
"callsRequested" : 2,
"callsCompleted" : 2,
"responses" : [
{
"url" : "/users/5",
"method" : "get",
"status" : 200,
"response" : {
"headers" : {},
"body" : {
"email": "user@user.ext",
"_links": {}
}
}
},
{
"url" : "/messages/?userId=5",
"method" : "get",
"status" : 200,
"response" : {
"headers" : {},
"body" : {}
}
}
]
}
常见问题解答
如何在 REST API 多请求链接中发送头信息?
头信息将与以往一样发送,并将自动应用于链中请求的每个调用。在此期间,REST API 多请求链不支持为每个调用独立发送特定头信息的能力——然而,如果需要,这肯定可以在未来添加。
这与 IO 状态驱动 API 有何不同?
REST API 多请求链是专门为使用超媒体在静态或缓存状态文件上运行的 RESTful API 设计的。这使得可用路径可以真正地根据链内单个调用而动态变化,并且也防止了需要多次请求来获取 IO 状态或可用 OPTIONS。REST API 多请求链还旨在超越仅使用主键的使用,让您在执行下一个链中的操作时,可以调用上一个调用中的头信息和正文信息。每个链接/调用也是条件性的,这意味着您可以指定何时调用该链接,并在链接/调用失败时收到适当的错误响应。更多内容,您可以查看 Owen 的 IO 状态实现 这里。