首页 > 解决方案 > 插入页面参数的 API 循环

问题描述

我正在尝试使用应用程序的 API 文档。

为了调用它,我正在使用代码:

curl -X GET \
  'https://api.program.com/v1/notes?page=1&pageSize=1000&sort=desc' \
  -H 'Authorization: Bearer xxx123xxx456xxx789xxx0001' \
  -H 'cache-control: no-cache'

出于显而易见的原因,此处更改了令牌。但是,我真正想要设置的是page=1参数。

我的问题有两个:

  1. 如何编写一个命令来捕获当前命令结构中的所有页面?所以基本上,在page=1它运行page=2之后page=3,......
  2. 我怎样才能以一种同时识别何时没有更多页面的方式来执行此操作,从而知道何时结束运行?

我目前的设置看起来像这样,但它给了我我需要的东西(我不太清楚)加上我不知道如何跳出循环:

for ((i=1;i<=5;i++)); do
  curl -X GET \
  'https://api.program.com/v1/notes?page=1&pageSize=1000&sort=desc' \
  -H 'Authorization: Bearer xxx123xxx456xxx789xxx0001' \
  -H 'cache-control: no-cache'
done

没有更多记录时的结果如下所示:

{
    "meta": {
        "pageSize": 1000,
        "page": 65
    },
    "links": {
        "self": "/v1/conversations?page=65&pageSize=1000&sort=desc",
        "first": "/v1/conversations?page=1&pageSize=1000&sort=desc",
        "prev": "/v1/conversations?page=64&pageSize=1000&sort=desc",
        "next": null
    },
    "data": []
}

根据查尔斯达菲的回应,我正在运行的内容 - 保存为test_run.sh

getPage () {
  curl -X GET 'https://api.test.com/v1/test?page="$1"&pageSize=1000&sort=desc' \
    -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9Cim97g123NXpMkS_Jc9xggCYlMQVvKsAeBCw' \
    -H 'cache-control: no-cache'
}

但这会返回错误:

MacBook-Pro-8:~ admin$ ./test_run.sh
-bash: ./json_blob.sh: Permission denied

然而,当我运行时,只需在命令行中直接运行以下命令,它就会很好地返回结果:

curl -X GET 'https://api.test.com/v1/test?page="$1"&pageSize=1000&sort=desc' \
        -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9Cim97g123NXpMkS_Jc9xggCYlMQVvKsAeBCw' \
        -H 'cache-control: no-cache' > test_run.json

标签: bashcurl

解决方案


在实践中,我可能会写这个更类似于以下内容:

#!/usr/bin/env bash
case $BASH_VERSION in ''|[12].*) echo "Bash 3.0+ required" >&2; exit 1;; esac

# Given a page number, return text of that page.
# Note that we switch from single to double quotes before expanding $1
getPage() {
  curl --fail -X GET 'https://api.program.com/v1/notes?page='"$1"'&pageSize=1000&sort=desc' \
    -H 'Authorization: Bearer xxx123xxx456xxx789xxx0001' \
    -H 'cache-control: no-cache'
}

# return a stream with *all* page text, from page 1 until
# the first one with no .link.next.
getAllPages() {
  local page i=1
  while page=$(getPage "$i"); do
    printf '%s\n' "$page"
    if [[ $(jq '.links.next' <<<"$page") = null ]]; then
      break
    fi
    (( ++i ))
  done
}

getAllPages \
  | jq -c '.data[] | .attributes | {text: .preview, from: .meta.from}' \
  > data_json_blob.jsonl

此处命名输出文件是.jsonl因为它采用 JSONLines 格式,而不是标准 JSON。(您不能将多个对象放在一个 JSON 文件中而不将它们封装在一个列表或其他容器中并使其有效;因此,当您jq在输入中提供多个对象的 1:1 转换时,通常会得到 JSONL,不是 JSON,作为输出)。


推荐阅读