Google API Gateway OpenApi Swaagger 2.0 to CloudRun Parameter configured for Path turns out in query instead of path - openapi

I'm testing an API Gateway setup on Google Cloud to access specific endpoints on a service deployed on Cloud Run. I'm following the steps shown here. We need to authenticate using an API Key, so the API Key specific configuration that went into the API Gateway config was picked from this documentation.
The API Gateway config is as shown below:
# api_gateway_config.yaml
swagger: '2.0'
info:
title: myappapi
description: API with Cloudrun Backend
version: 1.0.0
schemes:
- https
produces:
- application/json
paths:
/:
get:
summary: Greet a User from service
operationId: hello
x-google-backend:
address: https://myappapi-asldfjoiewjfv-uc.a.run.app/
security:
- api_key: []
responses:
'200':
description: A successful response
schema:
type: string
/reports/results/{id}:
get:
summary: Get Report Results for specified report id
operationId: GetReportResults
x-google-backend:
address: https://myappapi-asldfjoiewjfv-uc.a.run.app/v1/reports/results/{id}
parameters:
- in: path
name: id
required: true
type: integer
security:
- api_key: []
responses:
'200':
description: A successful response
schema:
type: string
securityDefinitions:
# This section configures basic authentication with an API Key.
api_key:
type: "apiKey"
name: "key"
in: "query"
For a sample call to the /reports/results endpoint as http://myappapi/reports/results/1,
the expectation is for calls to get converted to https://myappapi-asldfjoiewjfv-uc.a.run.app/v1/reports/results/1?key=MyAPIKeyHere. But instead they turn out as https://myappapi-asldfjoiewjfv-uc.a.run.app/v1/reports/results?key=MyAPIKeyHere&id=1
Is there a way to get the API calls go as https://myappapi-asldfjoiewjfv-uc.a.run.app/v1/reports/results/1?key=MyAPIKeyHere ?
Thanks in Advance!

As mentioned in this documentation
Set path_translation as part of setting x-google-backend:
x-google-backend:
address: https://GCP_REGION-PROJECT_ID.cloudfunctions.net/hello
path_translation: [ APPEND_PATH_TO_ADDRESS | CONSTANT_ADDRESS ]
The default value of path_translation depends on where you set x-google->backend in your OpenAPI spec:
When x-google-backend is used at the top level of the OpenAPI specification, path_translation defaults to APPEND_PATH_TO_ADDRESS.
When x-google-backend is used at the operation level of the OpenAPI specification, path_translation defaults to CONSTANT_ADDRESS.
For more details on path translation, please see the Understanding path translation section. You can also check this stackoverflow thread.

Related

Why does SwaggerHub return error 403 when I test my OpenAPI definition?

I have the following OpenAPI definition hosted on SwaggerHub:
https://app.swaggerhub.com/apis/MyFirstAPI/1.0.1-oas3
openapi: 3.0.0
servers:
- url: http://api.myfirstapi.com/
info:
version: 1.0.1-oas3
title: Equ API
paths:
/query:
get:
tags:
- developers
parameters:
- in: query
name: searchString
schema:
type: string
responses:
'200':
description: search results matching criteria
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Equity'
'400':
description: There is 400
components:
schemas:
Equity:
...
When I test the GET /query request, it returns a 403 error:
content-length: 0
date: Fri,10 Sep 2021 14:32:54 GMT
server: nginx/1.18.0 + Phusion Passenger(R) 6.0.8
status: 403 Forbidden
via: 1.1 b5d86079363e9709b4c4051d3c94ac3d.cloudfront.net (CloudFront)
x-amz-cf-id: pYbLwlrEHg5DXkGe5FkysAjSjbSDqUg7Rrhbv-Dt8Xwt8JuPRMAW3Q==
x-amz-cf-pop: DEL54-C1
x-cache: Error from cloudfront
x-powered-by: Express,Phusion Passenger(R) 6.0.8
Why does this error happen and how to fix it?
This 403 error is somewhat misleading. The actual problem here is that the target server for requests - api.myfirstapi.com - does not actually exist. The servers list is supposed to specify your real server(s).
If you are designing a new API and don't have a live server yet, you can use SwaggerHub's mock server to similate responses and test API calls.
To add a mock to your API definition:
Click the API name on the editor toolbar.
Switch to the Integrations tab and click Add New Integrations.
Select API Auto Mocking from the list and click Add.
Enter any value for Name (e.g. mock), leave other options as is, and click Create and Execute.
Close the remaining dialogs.
This creates a mock server for your API and adds it to the servers list in your API definition:
servers:
- description: SwaggerHub API Auto Mocking
url: https://virtserver.swaggerhub.com/OWNER_NAME/API_NAME/VERSION
Make sure to select this server in the API docs before you test API calls.

How does one setup OpenAPI redirect response with parameters?

I have an HTTP 302 (Redirect) that I implemented a new status parameter, that will append to the RedirectURL, so one can show a message something like
if the call URL is passed as
GET http://localhost:8080/info/status?redirectUrl=http://localhost:8080/redirect
then it will redirect as
http://localhost:8080/redirect?status=success
and it's counterpart
http://localhost:8080/redirect?status=error
but how does one describe this in OpenAPI specification? I can't seem to make use of parameters in the response and found some code that uses responseParameters but I had no luck to make it work... don't even know if it's something that is supported, at least, I get no errors compiling with both commands
/info/setup:
get:
summary: Setup Url
description: Setup Url to create new setup. Should be retrieved from api
apps endpoint and redirect to, not called directly by the url defined
here
parameters:
- in: query
name: installationId
description: The installation id
required: true
schema:
type: string
- in: query
name: redirectUrl
description: Url to redirect back to upon finished installation
required: true
schema:
type: string
responses:
"302":
description: Redirect
responseParameters:
- in: query
name: status
description: the status of the instalation
schema:
oneOf:
- type: string
example: success
description: When the installation was successful
- type: string
example: error
description: When the installation was erroneous
headers:
location:
description: Setup state based redirect
schema:
oneOf:
- type: string
description: If setup is done and valid for installation id, will
redirect to given redirect url
- type: string
description: If no setup exist for installation id, will redirect to
SumUp oauth page
- type: string
description: If error during authorization with SumUpl, e.g. non
matching editions, will redirect to a setup page for
further user action
what is the common way of having such a scenario?
should we have 2 redirect URLs like
GET http://localhost:8080/info/status
?redirectUrl=http://localhost:8080/redirect
&errorUrl=http://localhost:8080/redirect_error
I'm a bit of a loss on this simple predicament, maybe someone can help 😊
Yes, this is an annoying issue with OpenAPI. You cannot really specify a redirect explicitly.
The best you can do is specify a response with a status code in the 3xx redirect range (301, 302, 303, 307, 308) that has a "location" header parameter of type "string".
You should then add a description and summary - pretty much what you have already done.
There is this issue in the OpenAPI specification github: https://github.com/OAI/OpenAPI-Specification/issues/2512
Hopefully something will be done soonish.

How to make tokenUrl configurable

Is there anyway to make the token url in OpenAPI spec configurable.
For instance the I want to make the realm {{REALM_NAME_HERE}} below configurable from swagger UI.
securitySchemes:
oauth:
type: oauth2
description: This API uses OAuth 2
flows:
clientCredentials:
tokenUrl: http://localhost:32777/auth/realms/{{REALM_NAME}}/protocol/openid-connect/token
scopes: {}
tokenUrl does not support variables. There's a corresponding feature request in the OpenAPI Specification repository:
https://github.com/OAI/OpenAPI-Specification/issues/551
However, if the parameterized part of the tokenUrl (in your example - http://localhost:32777/auth/realms/{{REALM_NAME}}) also happens to be the API server URL, you can define tokenUrl relative to the server URL:
openapi: 3.0.0
servers:
- url: 'http://localhost:32777/auth/realms/{REALM_NAME}'
variables:
REALM_NAME:
default: some_default_realm # default value is required
paths:
...
components:
securitySchemes:
oauth:
type: oauth2
description: This API uses OAuth 2
flows:
clientCredentials:
tokenUrl: './protocol/openid-connect/token'
scopes: {}

Rest API Token Based Authentication Mechanism with Swagger Not Working

I am trying to make an API call with rest token based authentication from swagger. But at server side, I don't find token in the request. I tried the same API call with poster and swagger. In Poster it works fine but in swagger it doesn't.
Below is my JSON file which I am using to make API call with token:
swagger: '2.0'
info:
title: City
description: City Information
version: 1.0.0
host: '127.0.0.1:8090'
schemes:
- http
basePath: /App
produces:
- application/json
paths:
/city/list:
get:
summary: city
description:
Show cities name and its attributes.
security:
- APIAuthKey: []
responses:
'200':
description: An array of city
default:
description: Unexpected error
securityDefinitions:
APIAuthKey:
type: apiKey
in: header
name: X-AUTH-TOKEN
And this is how swagger sends request with X-AUTH-TOKEN:
But, when I use the same API call wit same parameters and X-AUTH-TOKEN in Poster, It works fine. Below, I have highlighted that how I send request with Poster:
Can anyone please suggest if I'm doing anything wrong or missing something? Why am I unable to send token with request correctly to fetch at server side in request header?

Open API POST with Path Parameter

I am trying to write a Open API specification with Swagger-ui (swagger version 2.0) and I am not sure how to represent a POST parameter with a path parameter
POST /ping/{text}
My specification is as follows,
# this is an example of the Uber API
# as a demonstration of an API spec in YAML
swagger: '2.0'
info:
title: Mock API
description: Mock API
version: "1.0.0"
# the domain of the service
host: api.mock.com
# array of all schemes that your API supports
schemes:
- https
# will be prefixed to all paths
basePath: /v1
produces:
- application/json
paths:
/ping:
get:
summary: Ping
description: |
Respond to PING requests, similar to heart beat
parameters:
- name: path
in: path
description: String input for echo service
required: false
type: string
tags:
- ping
responses:
200:
description: The text passed in the request
schema:
type: string
default:
description: Empty response for request passed
schema:
type: string
And the swagger ui shows an error as follows -
code: "ONE_OF_MISSING"
message: "Not a valid parameter definition"
but if I change it to in: query the error vanishes. What am I doing wrong? or what is the right way to specify a path parameter in open API specification?
There are a few changes you need to make to your document to conform to the Open API specification.
1- The name field should match the path segment (ie text
If in is "path", the name field MUST correspond to the associated path segment from the path field in the Paths Object. See Path Templating for further information.
2- required: true should be added.
If the parameter is in "path", this property is required and its value MUST be true.
3- If you want to document POST /ping/{text}, get needs to be changed to post. Also the path segment (ie. /{text) should be added to the path.
Here is the final Swagger doc after the changes described above:
# this is an example of the Uber API
# as a demonstration of an API spec in YAML
swagger: '2.0'
info:
title: Mock API
description: Mock API
version: "1.0.0"
# the domain of the service
host: api.mock.com
# array of all schemes that your API supports
schemes:
- https
# will be prefixed to all paths
basePath: /v1
produces:
- application/json
paths:
/ping/{text}:
post:
summary: Ping
description: |
Respond to PING requests, similar to heart beat
parameters:
- name: text
in: path
description: String input for echo service
required: true
type: string
tags:
- ping
responses:
200:
description: The text passed in the request
schema:
type: string
default:
description: Empty response for request passed
schema:
type: string
According to the specification it seems that "required" has to be true if you set "in: path".
Details can be found here: http://swagger.io/specification/#parameterObject