【问题标题】:Curl/GraphQL command failing with 200Curl/GraphQL 命令以 200 失败
【发布时间】:2022-01-19 15:15:20
【问题描述】:

我正在尝试编写一个针对 GraphQL API 执行 curl 的 shell 脚本,但我之前从未与 GQL 进行过交互。我遇到了一些奇怪的错误,虽然我知道这个社区无法访问 GQL 服务器,但我希望有人可以查看脚本并确保我没有在语法方面做任何明显错误的事情(两者都在shell 脚本层以及 GQL 查询本身)。

我的脚本:

#!/bin/bash

BSEE_WEB_SERVER_DNS=https://mybsee.example.com
BSEE_API_KEY=abc123

siteId=1
scanConfigId=456

runScanQuery='mutation CreateScheduleItem { create_schedule_item(input: {site_id: "$siteId" scan_configuration_ids: "$scanConfigId"}) { schedule_item { id } } }'
runScanVariables='{ "input": "site_id": $scanId }}'
runScanOperationName='CreateScheduleItem'

curl -i --request POST \
    --url $BSEE_WEB_SERVER_DNS/graphql/v1 \
    --header "Authorization: $BSEE_API_KEY" \
    --header 'Content-Type: application/json' \
    --data '{"query":"$runScanQuery","variables":{$runScanVariables},"operationName":"${runScanOperationName}"}'

当我从终端运行脚本时的输出:

HTTP/2 200 

<OMITTED RESPONSE HEADERS>

{"errors":[{"message":"Invalid JSON : Unexpected character (\u0027$\u0027 (code 36)): was expecting double-quote to start field name, Line 1 Col 38","extensions":{"code":3}}]}%

出于安全和简洁的原因,我省略了 HTTP 响应标头。

我想知道我对引号/双引号的使用是否存在某种错误,或者 GQL 查询本身(通过 curl)的性质是否对任何人都不利。

我与管理服务器的团队确认 HTTP 200 OK 响应代码是正确的。 200 表示对 GQL API 的请求成功,但 GQL 正在响应此错误以指示 query 本身不正确。

【问题讨论】:

    标签: shell curl graphql


    【解决方案1】:

    我们需要修改 GraphQL 位并修复 bash 字符串引用。

    runScanQuery GraphQL 操作

    修复 GraphQL 语法。在arguments input: { site_id: $siteId, scan_configuration_ids: $scanConfigId 中使用 GraphQL operation name CreateScheduleItemvariables $site_id

    mutation CreateScheduleItem($site_id: String!, $scanConfigId: String!) {
      create_schedule_item(
        input: { site_id: $siteId, scan_configuration_ids: $scanConfigId }
      ) {
        schedule_item {
          id
        }
      }
    }
    

    runScanVariables: JSON

    我们的突变需要两个变量,GraphQL 会将其替换为CreateScheduleItem($site_id: String!, $scanConfigId: String!)。以 JSON 形式提供 GraphQL 变量。这是 bash 变量替换后的预期输出:

    { "$site_id": "1", "$scanConfigId": "456" }
    

    正确引用 bash

    最后,将输入转换为 bash 友好的语法:

    runScanQuery='mutation CreateScheduleItem($site_id: String!, $scanConfigId: String!) { create_schedule_item(input: {site_id: $siteId scan_configuration_ids: $scanConfigId}) { schedule_item { id } } }'
    runScanVariables='{"$site_id":"'"$siteId"'","$scanConfigId":"'"$scanConfigId"'"}'  # no spaces!
    runScanOperationName='CreateScheduleItem'
    data='{"query":"'"$runScanQuery"'","variables":'$runScanVariables',"operationName":"'"$runScanOperationName"'"}'
    

    检查我们的 bash 格式。将终端输出粘贴到 VSCode 等代码感知编辑器中。期望编辑器正确解析输出。

    echo $runScanQuery              # want string in graphql format
    echo $runScanVariables          # want JSON
    echo $data                      # want JSON
    

    编辑:添加公共 API 示例

    这是一个使用公共星球大战 API 的完整工作示例:

    #!/bin/bash
    filmId=1
    data='{"query":"query Query($filmId: ID) { film(filmID: $filmId) { title }}","variables":{"filmId":"'"$filmId"'"}}'
    
    curl --location --request POST 'https://swapi-graphql.netlify.app/.netlify/functions/index' \
    --header 'Content-Type: application/json' \
    --data "$data"
    

    回复{"data":{"film":{"title":"A New Hope"}}}

    【讨论】:

    • 谢谢@fedonev (+1) - 所以你的data 变量在那里,我可以将它(逐字)用于我原始问题中curl--data 参数吗?跨度>
    • @hotmeatballsoup --data "$data" 如果你想使用数据变量而不是字符串文字。
    • @hotmeatballsoup 我添加了一个星球大战 API 工作示例来演示正确的格式。愿原力与你同在。
    【解决方案2】:

    在 GraphQL 总是有 200 个状态码是正常的;客户端必须检查响应正文以查找失败。

    原因很简单:在 REST 中,http 是协议的一部分,状态码具有语义,但在 GraphQL 中,http 不是协议的一部分,您可以在多个传输协议上使用 GraphQL:

    • http: 典型场景docs
    • WebSocket:不提供任何“类似状态代码”的负载。 sample
    • MQTT:不提供任何“类似状态代码”的负载
    • ...

    服务器告诉你某些事情(甚至是失败)的唯一方式是正文。


    在您的情况下,我建议您 jq 通过 bash 脚本搜索 error 属性来解析 json。

    【讨论】:

      【解决方案3】:

      您的错误与 GraphQL 完全无关。你的 JSON 真的错了。

      错误消息显示意外字符(\u0027$\u0027(代码 36)):原希望用双引号来开始字段名称,第 1 行第 38 行,

      你可以用撇号替换转义的\u0027,你会得到

      意外字符('$'(代码 36)):希望在字段名称开始时使用双引号,第 1 行第 38 行",

      所以它讨厌你作为数据发送到 curl 的第 38 位的美元符号

      data='{"query":"'"$runScanQuery"'","variables":'$runScanVariables'
                                                      ^
                                                     this
      

      首先 - JSON 中的所有字段名称和值都应该用双引号括起来,而不是单引号。

      第二 - 如果你想 curl 扩展环境变量,把它放在双引号,而不是单引号。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-10-06
        • 1970-01-01
        • 1970-01-01
        • 2019-07-06
        • 1970-01-01
        • 2016-10-09
        • 2019-04-22
        相关资源
        最近更新 更多