如何定义用 OpenAPI 编写的登录 API 以将 cookie 从响应返回到其生成的代码

问题描述

我想为登录请求编写 API。 如果登录请求成功,则 API 应从响应标头返回 cookie。否则返回响应错误信息。

请求和响应的内容类型如下:

  • 请求:application/x-www-form-urlencoded

  • 回复

    1. 关于成功: 内容类型:文本/html
      返回:“set-cookie”头

    2. 出错:
      内容类型:应用程序/json
      返回:错误信息属性“code”

这是用于登录后的 OpenAPI 定义

  /api/v1/user/login:
    post:
      tags:
        - login
      summary: Login as a user.
      description: Send login request
      operationId: loginUser
      requestBody:
        description: Send login credentials.
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              properties:               
                username:
                  type: string
                password:
                  type: string                
              required:               
                - username
                - password
              example:                
                username: usr
                password: '123'
      responses:
        '200':
          description: returns cookie from set-cookie header.          
          content:
            text/html:
              schema:
                type: string
        '400':
          description: 400 Bad Request,Missing Parameter.
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: string
                example:
                  code: MISSING_ParaMETER
tags:
  - name: login
    description: login operations

生成命令 我将 openapi-generator-clicpprestsdk 生成器一起用于 msvc C++ 客户端

npx openapi-generator-cli generate -g cpp-restsdk -i test.yaml -o ./output

我想避免手动编辑代码修复。 所以我希望生成器尽可能为 API 生成完整正确的代码

生成代码: 为了定位代码问题,在生成代码添加了以“//ERROR”开头的注释。

pplx::task<utility::string_t> LoginApi::loginUser(utility::string_t username,utility::string_t password) const
{


    std::shared_ptr<const ApiConfiguration> localVarapiConfiguration( m_apiclient->getConfiguration() );
    utility::string_t localVarPath = utility::conversions::to_string_t("/api/v1/user/login");
    
    std::map<utility::string_t,utility::string_t> localVarQueryParams;
    std::map<utility::string_t,utility::string_t> localVarHeaderParams( localVarapiConfiguration->getDefaultHeaders() );
    std::map<utility::string_t,utility::string_t> localVarFormParams;
    std::map<utility::string_t,std::shared_ptr<HttpContent>> localVarFileParams;

    std::unordered_set<utility::string_t> localVarResponseHttpContentTypes;
    localVarResponseHttpContentTypes.insert( utility::conversions::to_string_t("text/html") );
    localVarResponseHttpContentTypes.insert( utility::conversions::to_string_t("application/json") );

    utility::string_t localVarResponseHttpContentType;

    // use JSON if possible
    if ( localVarResponseHttpContentTypes.size() == 0 )
    {
        localVarResponseHttpContentType = utility::conversions::to_string_t("text/plain");
    }
    // JSON
    else if ( localVarResponseHttpContentTypes.find(utility::conversions::to_string_t("application/json")) != localVarResponseHttpContentTypes.end() )
    {
        localVarResponseHttpContentType = utility::conversions::to_string_t("application/json");
    }
    // multipart formdata
    else if( localVarResponseHttpContentTypes.find(utility::conversions::to_string_t("multipart/form-data")) != localVarResponseHttpContentTypes.end() )
    {
        localVarResponseHttpContentType = utility::conversions::to_string_t("multipart/form-data");
    }
    //ERROR: Instead of "text/html",Content-Type checking for "text/plain" generated!
    else if( localVarResponseHttpContentTypes.find(utility::conversions::to_string_t("text/plain")) != localVarResponseHttpContentTypes.end() )
    {
        localVarResponseHttpContentType = utility::conversions::to_string_t("text/plain");
    }
    else
    {
        throw ApiException(400,utility::conversions::to_string_t("LoginApi->loginUser does not produce any supported media type"));
    }

    localVarHeaderParams[utility::conversions::to_string_t("Accept")] = localVarResponseHttpContentType;

    std::unordered_set<utility::string_t> localVarConsumeHttpContentTypes;
    localVarConsumeHttpContentTypes.insert( utility::conversions::to_string_t("application/x-www-form-urlencoded") );

    {
        localVarFormParams[ utility::conversions::to_string_t("username") ] = apiclient::parameterToString(username);
    }
    {
        localVarFormParams[ utility::conversions::to_string_t("password") ] = apiclient::parameterToString(password);
    }

    std::shared_ptr<IHttpBody> localVarHttpBody;
    utility::string_t localVarRequestHttpContentType;

    // use JSON if possible
    if ( localVarConsumeHttpContentTypes.size() == 0 || localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("application/json")) != localVarConsumeHttpContentTypes.end() )
    {
        localVarRequestHttpContentType = utility::conversions::to_string_t("application/json");
    }
    // multipart formdata
    else if( localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("multipart/form-data")) != localVarConsumeHttpContentTypes.end() )
    {
        localVarRequestHttpContentType = utility::conversions::to_string_t("multipart/form-data");
    }
    else if (localVarConsumeHttpContentTypes.find(utility::conversions::to_string_t("application/x-www-form-urlencoded")) != localVarConsumeHttpContentTypes.end())
    {
        localVarRequestHttpContentType = utility::conversions::to_string_t("application/x-www-form-urlencoded");
    }
    else
    {
        throw ApiException(415,utility::conversions::to_string_t("LoginApi->loginUser does not consume any supported media type"));
    }


    return m_apiclient->callApi(localVarPath,utility::conversions::to_string_t("POST"),localVarQueryParams,localVarHttpBody,localVarHeaderParams,localVarFormParams,localVarFileParams,localVarRequestHttpContentType)
    .then([=](web::http::http_response localVarResponse)
    {
        if (m_apiclient->getResponseHandler())
        {
            m_apiclient->getResponseHandler()(localVarResponse.status_code(),localVarResponse.headers());
        }

        if (localVarResponse.status_code() >= 400)
        {
            throw ApiException(localVarResponse.status_code(),utility::conversions::to_string_t("error calling loginUser: ") + localVarResponse.reason_phrase(),std::make_shared<std::stringstream>(localVarResponse.extract_utf8string(true).get()));
        }

        // check response content type
        if(localVarResponse.headers().has(utility::conversions::to_string_t("Content-Type")))
        {
            utility::string_t localVarContentType = localVarResponse.headers()[utility::conversions::to_string_t("Content-Type")];
            if( localVarContentType.find(localVarResponseHttpContentType) == std::string::npos )
            {
                throw ApiException(500,utility::conversions::to_string_t("error calling loginUser: unexpected response type: ") + localVarContentType,std::make_shared<std::stringstream>(localVarResponse.extract_utf8string(true).get()));
            }
        }
        //ERROR: Only Return Response Body. Not "set-cookie" Header
        return localVarResponse.extract_string();
    })
    .then([=](utility::string_t localVarResponse)
    {
        utility::string_t localVarResult(utility::conversions::to_string_t(""));

        if(localVarResponseHttpContentType == utility::conversions::to_string_t("application/json"))
        {
            web::json::value localVarjson = web::json::value::parse(localVarResponse);

            ModelBase::fromJson(localVarjson,localVarResult);
        }
        //ERROR: Instead of "text/html",Content-Type checking for "text/plain" generated!
        else if(localVarResponseHttpContentType == utility::conversions::to_string_t("text/plain"))
        {
            localVarResult = localVarResponse;
        }
        else
        {
            throw ApiException(500,utility::conversions::to_string_t("error calling loginUser: unsupported response type"));
        }

        return localVarResult;
    });
}

API 定义是否需要进一步修改

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)