【问题标题】:Getting pages results from rest API: Best practice从 REST API 获取页面结果:最佳实践
【发布时间】:2017-03-06 03:27:12
【问题描述】:

对 REST API 来说还算新,到目前为止只做了一些相当基本的查询来获得我需要的东西。

编写一个新的 PowerShell 脚本,使用 rest 拉出所有设备:

$url = "https://my-site.com/internal/api"

然后查询所有设备并将这些结果分配给一个变量,这样我就可以在以后在整个脚本的不同点使用该变量执行操作:

$devices = Invoke-RestMethod -uri "$url/devices" -UseDefaultCredentials -Method Get -ContentType "application/json"

有上万条结果,我想做的是能够在所有返回的页面中搜索结果。

到目前为止,我已经知道我可以做这样的事情来在一页中获得所有结果:

$devicespagetest = Invoke-RestMethod -uri "$url/devices?pagesize=99999" -UseDefaultCredentials -Method Get -ContentType "application/json"

这是不好的做法吗?

有没有更有效或程序化的方式来实现这一点而无需像我上面那样做?

我实际上并不确定我们使用的是哪种 Rest API,但我知道我们没有将它与 Jira 或 Confluence 集成。

【问题讨论】:

    标签: powershell wordpress-rest-api


    【解决方案1】:

    你调用的API是自己开发的吗?

    编辑:刚刚看到您在标签中调用了 WordPress API。 WordPress offers pagination links,并通过自定义标题提供有用的分页信息。

    通常,REST API 在通过查询参数(例如:“offset”和“max”)返回资源列表时提供分页支持。 offset 参数指示应跳过多少结果,而 max(或在您的情况下为 pagesize)确定您要获取的最大结果。

    例如,http://myapi.com/persons?_offset=0&_max=20 代表您列表中的前 20 人。在 HATEOAS 约束的上下文中,建议提供 HTTP 链接响应标头,以便客户端知道如何使用“上一个”、“第一个”、“下一个”和“最后一个”关系(标准化在RFC 5988)。

    例如:

    GET /persons?_offset=30&_max=10 HTTP/1.1
    Host: myapi.com
    Accept: application/json
    

    导致以下响应:

    HTTP/1.1 200 OK
    Content-Type: application/json
    Content-Length: 934
    Link: <http://myapi.com/persons?_offset=0&_max=10>; rel="first"
    Link: <http://myapi.com/persons?_offset=20&_max=10>; rel="previous"
    Link: <http://myapi.com/persons?_offset=40&_max=10>; rel="next"
    {body}
    

    为了保护请求整个列表资源的客户端(即不指定分页参数)的服务器,建议使用以下方法。当客户端请求列表资源(例如http://myapi.com/persons)时,服务器会将客户端重定向到前 X(例如 10)项。

    对应的HTTP会话如下图:

    GET /persons HTTP/1.1
    Host: myapi.com
    Accept: application/json
    

    导致以下响应:

    HTTP/1.1 303 See Other
    Location: http://myapi.com/persons?_offset=0&_max=10
    

    接下来,客户端跟随重定向:

    GET /persons?_offset=0&_max=10 HTTP/1.1
    Host: myapi.com
    Accept: application/json
    

    这会导致以下响应:

    HTTP/1.1 200 OK
    Content-Type: application/json
    Content-Length: 850
    Link: <http://myapi.com/persons?_offset=40&_max=10>; rel="next"
    Link: <http://myapi.com/persons?_offset=120&_max=10>; rel="last"
    {body}
    

    请注意,但是在需要 CORS (Cross Origin Resource Sharing) 的环境中,重定向可能会导致问题。在这种情况下,通过 GET /persons 检索的部分列表的表示可以简单地指示检索了多少人以及总共有多少人(可选)。

    如果您的 API 提供此类导航链接,最好使用它们并使用 Invoke-RESTMethod 实现一个循环并为您的搜索动态构建索引,而不是一次获取 10000 个结果,这会给您带来不必要的压力服务器。但是在不了解您的用例的情况下,很难给您适当的建议。

    【讨论】:

    • 感谢大卫的回复和建议。不是我不,它已经存在于我们的组织中。看起来它确实支持这样的导航链接(剪切标准方法等以适应):PS C:\windows\system32> $devicespagetest | gm Name ---- Count NextUrl Pages PageSize PreviousUrl 我会看看用 Invoke-RESTMethod 实现一个循环
    【解决方案2】:

    谢谢大卫

    基于获取 previousurl 和 nexturl 值,我将以下内容放在一起:

    $Devurl = "https://my-site.com/internal/api"
    $restResults = Invoke-RestMethod -uri "$Devurl/$device" -UseDefaultCredentials -Method Get -ContentType "application/json"
    
    $resultpages = $restResults.Pages
    $incpages = ''
    $testarray = @()
    
    Do {
        [int]$incpages += 1
        $url = ($restResults.nexturl) -replace 'page=1',"page=$incpages"
        $url
        $getresults = Invoke-RestMethod -uri $url -UseDefaultCredentials -Method Get -ContentType "application/json"
        $testarray += $getresults.Models
        $resultpages -= 1
        } while ($resultpages -gt 0)
    

    如果我再过滤结果:

    $testarray | where {$_.os -like '*windows*'} | select hostname,os
    

    我看到了我的期望。

    这就是你说的那种循环吗?

    【讨论】:

      猜你喜欢
      • 2013-10-23
      • 2023-03-26
      • 1970-01-01
      • 2020-05-29
      • 1970-01-01
      • 2018-04-27
      • 1970-01-01
      • 2012-12-02
      相关资源
      最近更新 更多