使用Swagger Codegen客户端在Python中添加API调用标头的细节不清楚。

7

请指出正确的文档、教程、示例,或提供一个,展示如何将特定认证令牌添加到Python中Swagger生成的API客户端的特定标头?

这是我尝试过的:
我的API调用使用正确的curl命令完美运行:

curl -v -H 'X-CAG-Authorization: AG_CONSUMER_TOKEN access-key=31337-70k3n' \
     'https://api.company.net/api/v1/user/detail?user=1'

*   Trying 10.10.1.10...
* Connected to api.company.net (10.10.1.10) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate: *.company.net
* Server certificate: COMODO RSA Organization Validation Secure Server CA
* Server certificate: COMODO RSA Certification Authority
> GET /api/v1/user/detail?user=1 HTTP/1.1
> Host: api.company.net
> User-Agent: curl/7.49.1
> Accept: */*
> X-CAG-Authorization: AG_CONSUMER_TOKEN access-key=31337-70k3n
> 
< HTTP/1.1 200 OK
< Server: openresty
< Date: Thu, 22 Dec 2016 19:46:05 GMT
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Connection: close
< Vary: Accept-Encoding
< Vary: Accept-Encoding
< X-UA-Compatible: IE=edge
< 
{"successful":true,"message":"SUCCESS","body":{"…

然而,当我在Python(2.7.12)客户端尝试相同的基本请求时,尽管确认令牌已被放置在即将使用的标头中,但我收到了授权失败的消息。希望能提供有关正确使用客户端的更多详细信息,或有关如何获取确切请求和响应详细信息的说明。
/Users/me/VEnvs/sku-grade/bin/python /Users/me/prj/code/python_client/api_example.py
HEADERS:
{'X-CAG-Authorization': 'AG_CONSUMER_TOKEN access-key=31337-70k3n', 'User-Agent': 'Swagger-Codegen/1.0.0/python'}
Exception when calling SupplierApi->get_api_v1_user_details: (401)
Reason: Unauthorized
HTTP response headers: HTTPHeaderDict({'Date': 'Thu, 22 Dec 2016 21:09:30 GMT', 'Content-Length': '636', 'Content-Type': 'application/json; charset=UTF-8', 'Connection': 'keep-alive', 'Server': 'nginx'})
HTTP response body: {
  "code" : "PRECONDITION_FAILED",
  "type" : "UnauthorizedApiDeniedException",
  "message" : "Target API(/api/v1/user/details) is not available, you have to get a grant in advance.",
  "messages" : {

这是一个Swagger API规范:swagger.yaml
---
swagger: "2.0"
info:
  description: "API"
  version: "TEMPORARY"
  title: "User Details"
  termsOfService: "http://wiki.company.net/tos"
  contact:
    name: "…"
  license:
    name: "…"
host: "api.company.net"
basePath: "/api/v1"
tags:
- name: "supplier"
  description: "Supplier"
schemes:
- "https"
produces:
- "application/json"
paths:
  /user/details:
    get:
      tags:
      - "supplier"
      summary: "userDetails"
      operationId: "getApiV1UserDetails"
      consumes:
      - "application/json"
      produces:
      - "application/json;charset=utf-8"
      parameters:
      - name: "user"
        in: "query"
        description: "user id"
        required: true
        type: "integer"
        format: "Long"
      responses:
        200:
          description: "OK"
          schema:
            $ref: "#/definitions/SupplierResponseOfUserDetailsDto"
        401:
          description: "Unauthorized"
        403:
          description: "Forbidden"
        404:
          description: "Not Found"
definitions:
  SupplierResponseOfUserDetailsDto:
    type: "object"
    properties:
      body:
        $ref: "#/definitions/UserDetailsDto"
      message:
        type: "string"
      successful:
        type: "boolean"
  UserDetailsDto:
    type: "object"
    properties:
      name:
        type: "string"

我从http://editor.swagger.io/运行了swagger-codegen,并按照API示例尝试添加额外的标题:api_example.py

from __future__ import print_function
import time
import swagger_client
from swagger_client import ApiClient
from swagger_client import Configuration
from swagger_client.rest import ApiException
from pprint import pprint

# Setup the authentication token header
conf = Configuration()
conf.api_key_prefix = {"teamname": "AG_CONSUMER_TOKEN"}
conf.api_key = {
    "teamname": "access-key=31337-70k3n"
}
conf.api_client = ApiClient(None, "X-CAG-Authorization",
                            conf.get_api_key_with_prefix("teamname"))

# create an instance of the API class
api_instance = swagger_client.SupplierApi()
user = 1
try:
    api_response = api_instance.get_api_v1_user_details(user)
    pprint(api_response)
except ApiException as e:
    print("Exception when calling "
          "SupplierApi->get_api_v1_user_details: %s\n" % e)

通过在supplier_api.py中加入print(self.api_client.default_headers),我可以看到头部似乎已经被设置了。
{'X-CAG-Authorization': 'AG_CONSUMER_TOKEN access-key=31337-70k3n', 'User-Agent': 'Swagger-Codegen/1.0.0/python'}

那么,为了让我的示例通过头部并像简单的curl调用一样得到授权,我应该做出什么改变呢?

更新:我也尝试过定义它:

      security:
      - api_key: []
securityDefinitions:
  api_key:
    type: "apiKey"
    name: "X-CAG-Authorization"
    in: "header"

然后只需使用以下命令设置密钥:

swagger_client.configuration.api_key['X-CAG-Authorization'] = \
    'access-key=31337-70k3n'
swagger_client.configuration.api_key_prefix['X-CAG-Authorization'] = \
    'AG_CONSUMER_TOKEN'

但那并没有改变很多,除了默认头部中我正在打印的标题消失了。


我还尝试通过 swagger_client.configuration.… 引用配置来设置 api_key_prefixapi_keyapi_client,这与上述方法的效果相同;后来我更改了我的规范以包括 securityDefinitionssecurity 的提及,然后删除了这些配置设置,并仅按名称设置了 api_key。这不会影响标头,也不会改变行为。 - dlamblin
我也在Swagger Codegen项目中打开了这个问题:https://github.com/swagger-api/swagger-codegen/issues/4456 - dlamblin
2个回答

3
我尝试了您的代码示例,看起来您的标头实际上已经传递到服务器。
您可以通过在swagger_client/rest.py文件中添加print headers来确认这一点,就在此之前:
r = self.pool_manager.request(method, url,
                              fields=query_params,
                              preload_content=_preload_content,
                              timeout=timeout,
                              headers=headers)

您确定服务器没有问题吗?也许有一些标题破坏了身份验证?

以下curl命令是否有效?

curl -v \
 -H 'X-CAG-Authorization: AG_CONSUMER_TOKEN access-key=31337-70k3n' \
 -H 'Content-Type: application/json' \
 -H 'Accept: application/json;charset=utf-8' \
 -H 'User-Agent: Swagger-Codegen/1.0.0/python' \
 'https://api.company.net/api/v1/user/detail?user=1'

这应该会给你一个与Swagger返回相同的答案,即401错误。如果确实有错误,你可以从服务器端进行调试。如果没有错误,我就不知道了。


谢谢,使用所有四个标头的curl语句继续通过,所以我将再次检查Python中的https部分是否正常工作,并且它不是路径(似乎相同)。然后尝试使用swagger-codegen的最新版本生成。 - dlamblin
感谢你找到了正确的位置来打印出所有的方法、URL、字段和头部信息。在这样做之后,我发现 API 有两个公共端点,但只有一个能正常工作,所以现在我得到了完全相同且正确的行为。拥有更多的文档会很好,但在这种情况下,问题是正确调试的问题。 - dlamblin

2
在规范中,您需要描述与此示例类似的安全设置(在您的情况下为API密钥),该示例定义在OpenAPI / Swagger规范的securityDefinitions部分中。
然后,在端点中,您需要类似于此示例“应用”安全定义。
之后,您可以在自动生成的Python API客户端的configuration.py中设置API密钥,HTTP请求将相应地包括API密钥(根据规范中定义的安全设置,可能在标题或URL查询字符串中)。
自Swagger Codegen的上一个稳定版本以来,自动生成的Python API客户端已经有了很多增强功能,因此建议您拉取最新的主分支并在本地构建JAR以生成API客户端。

这是有用的额外细节。我在更新中指出,我根据两个示例更新了规范。我没有修改configuration.py,因为我不想在代码中提交密钥;相关的操作员从airflow中的连接获取它。但是在测试中,我直接使用了API,所以我也会尝试一下。我还可以尝试最新的主分支(我期望editor.swagger.io是最新的)。 - dlamblin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接