WSO2 APIM 4.1.0 (Linux) : REST API testing fails in Publisher : Invalid URL., RESOURCE = /xxxx HEALTH CHECK URL = xxxx - wso2-api-manager

I'm trying to create a simple REST API with a mock back-end in the publisher and test it in the publisher itself, before publishing it to the Dev portal.
Swagger definition
openapi: 3.0.1
info:
title: TestAPI
version: '1.0'
servers:
- url: /
security:
- default: []
paths:
/getMessage:
get:
parameters: []
responses:
'200':
description: ok
security:
- default: []
x-auth-type: Application & Application User
x-throttling-tier: Unlimited
x-wso2-application-security:
security-types:
- oauth2
optional: false
components:
securitySchemes:
default:
type: oauth2
flows:
implicit:
authorizationUrl: 'https://test.com'
scopes: {}
x-wso2-auth-header: Authorization
x-wso2-cors:
corsConfigurationEnabled: false
accessControlAllowOrigins:
- '*'
accessControlAllowCredentials: false
accessControlAllowHeaders:
- authorization
- Access-Control-Allow-Origin
- Content-Type
- SOAPAction
- apikey
- Internal-Key
accessControlAllowMethods:
- GET
- PUT
- POST
- DELETE
- PATCH
- OPTIONS
x-wso2-production-endpoints:
urls:
- 'https://run.mocky.io/v3/64df2918-ea8d-4fc9-8e6e-1f57d8b07070'
type: http
x-wso2-sandbox-endpoints:
urls:
- 'https://run.mocky.io/v3/64df2918-ea8d-4fc9-8e6e-1f57d8b07070'
type: http
x-wso2-basePath: /test/1.0
x-wso2-transports:
- http
- https
x-wso2-response-cache:
enabled: false
cacheTimeoutInSeconds: 300
Request (generated from the "Test -> Try it out" section )
curl -X 'GET' \
'https://localhost:8243/test/1.0/getMessage' \
-H 'accept: */*' \
-H 'Internal-Key: [key]'
Response (from postman)
{
"code": "404",
"type": "Status report",
"message": "Not Found",
"description": "The requested resource is not available."
}
APIM Log
[2022-06-07 12:02:06,610] INFO - LogMediator STATUS = Message dispatched to the main sequence. Invalid URL., RESOURCE = /test/1.0/getMessage, HEALTH CHECK URL = /test/1.0/getMessage
NOTE: The sample "PizzaShack" API gets deployed correctly and works fine but when I try to create one from scratch it always gives the Invalid URL error. The request URL seems fine to me, what am I doing wrong ?

Related

Nelmio 4 security definitions index not found

I try to configure nelmio/api-doc-bundle to use Authorization header for my Bearer token.
I configure it in nelmio_api_doc.yaml like this
nelmio_api_doc:
documentation:
info:
title: title
version: 1.0.0
securityDefinitions:
Bearer:
type: apiKey
description: 'jwt from oauth prefixed by `Bearer`'
name: Authorization
in: header
security:
- Bearer: []
areas: # to filter documented areas
path_patterns:
- ^/api(?!/doc$|/doc.json$) # Accepts routes under /api except /api/doc and /api/doc.json
But when i got to the ui doc page I got :
Notice: Undefined index: securityDefinitions
Did someone know how to fix it ?
It was changed in version 4, check this docs https://symfony.com/doc/4.x/bundles/NelmioApiDocBundle/index.html#using-the-bundle

Enable CORS for Cloud Run with Cloud Endpoints v1

I have been following an article on Medium to deploy Cloud Endpoints v1 in front of a Cloud Run service hosting a REST API and everything works well.
I now have a requirement to enable CORS support and I've added the below configuration to my endpoints YAML file but get an error saying "This service does not allow CORS traffic" when my browser tries to make a pre-flight request (I've tested this with Postman too with the same error). I know there's a flag to enable CORS --cors_preset=basic using environment variables but I'm not sure what key to set with. Any ideas or help is appreciated.
Endpoints YAML snipper:
swagger: '2.0'
info:
title: Cloud Endpoints with Cloud Run
description: Testing Cloud Endpoints with Cloud Run
version: 1.0.0
host: endpoint-<hash>-uc.a.run.app
x-google-endpoints:
- name: endpoint-<hash>-uc.a.run.app
allowCors: true
schemes:
- https
produces:
- application/json
Error:
{
"code": 7,
"message": "The service does not allow CORS traffic.",
"details": [
{
"#type": "type.googleapis.com/google.rpc.DebugInfo",
"stackEntries": [],
"detail": "service_control"
}
]
}
PS: Thanks Guillaum Blaquiere for the awesome article.
UPDATE:
I ended up testing with an incomplete URL and hence received the above error as my backend service wasn't configured to respond to all pre-flight request URLs. Having fixed this, I now get the below error only on the CORS pre-flight configured URL.
{
"code": 13,
"message": "INTERNAL_SERVER_ERROR",
"details": [
{
"#type": "type.googleapis.com/google.rpc.DebugInfo",
"stackEntries": [
],
"detail": "application"
}
]
}
and logs:
invalid URL prefix in "", client: <CLIENT_IP>, server: , request: "OPTIONS /api/v1/<REMAINING_URL> HTTP/1.1", host: "endpoint-<HASH>-uc.a.run.app"
I would say it's necesary to add ESPv2 Config, I've noticed that the note regarding the ESPv2 config was added since last april, and the Medium document was published on 2019, so I think such required step was not mentioned before.
Later in the same section it's mentioned that the flags for cors are passed by the "--set-env-vars" flag of the deploy command.
You can find more about the ESPv2 Beta startup options in here.
I managed to resolve the issue by defining OPTIONS operations in my YAML file with no security, for each path that I had already defined. See below example YAML file for an endpoint path '/api/v1/hello' with GET and OPTIONS operations defined.
swagger: '2.0'
info:
title: Cloud Endpoints with Cloud Run
description: Testing Cloud Endpoints with Cloud Run
version: 1.0.0
host: endpoint-randomhash-uc.a.run.app
x-google-endpoints:
- name: endpoint-randomhash-uc.a.run.app
allowCors: true
schemes:
- https
produces:
- application/json
x-google-backend:
address: https://backend-randomhash-uc.a.run.app
path_translation: APPEND_PATH_TO_ADDRESS
security:
- auth0_jwk: []
paths:
/api/v1/hello:
get:
summary: Say hello
operationId: helloName
parameters:
- name: "name"
in: "query"
description: "Your name"
type: "string"
responses:
'200':
description: Successful operation
schema:
type: string
options:
summary: CORS pre-flight for say hello
operationId: helloNameOptions
parameters:
- name: "name"
in: "query"
description: "Your name"
type: "string"
responses:
'200':
description: Successful operation
schema:
type: string
security: []
securityDefinitions:
auth0_jwk:
authorizationUrl: ""
flow: "implicit"
type: "oauth2"
x-google-issuer: "https://project.auth0.com/"
x-google-jwks_uri: "https://project.auth0.com/.well-known/jwks.json"
x-google-audiences: "firebase-application-host"
As Sergio pointed out in his comment to a SO question, the other option in my case is to use Firebase Hosting proxy to use the same domain and avoid CORS.

There seems to be a mismatch between last deployed API and actually in-use API

According to Google Cloud Console > Endpoints > Services > Deployment History this is the currently deployed API spec:
swagger: "2.0"
info:
title: "JSON Ingester"
description: "Receive JSON files, transform and load them."
version: "1.0.0"
host: "project-id-123.appspot.com"
schemes:
- "https"
paths:
"/upload":
post:
summary: "ETL JSON file."
security:
- api_key: []
operationId: "upload"
consumes:
- multipart/form-data
parameters:
- in: formData
name: file
type: string
responses:
200:
description: "File uploaded."
schema:
type: string
400:
description: "Error during file upload."
securityDefinitions:
api_key:
type: "apiKey"
name: "apikey"
in: "query"
But the key "apikey" is not accepted - instead it requires "key" which was specified in an openapi.yaml that I deployed few hours ago.
This works while it shouldn't:
$ curl -X POST -F "file=#data/file_6.json" https://project-id-123.appspot.com/upload\?key\=AIzaS...Eaoog
And this doesn't work while it should:
$ curl -X POST -F "file=#data/file_6.json" https://project-id-123.appspot.com/upload\?apikey\=AIzaS...Eaoog
{
"code": 16,
"message": "Method doesn't allow unregistered callers (callers without established identity). Please use API Key or other form of API consumer identity to call this API.",
"details": [
{
"#type": "type.googleapis.com/google.rpc.DebugInfo",
"stackEntries": [],
"detail": "service_control"
}
]
}
Do I have to clear a cache or something?
For deploying the API I use:
gcloud endpoints services deploy "./openapi.yaml"
Any ideas?
What rollout_strategy did you use when you deploy ESP? If not specified, default is "fixed". You should use "managed"
Please also check the generated service config by CLI "gcloud endpoints configs describe". Check its system_parameters filed to see if your new "apikey" is created properly.

Swagger doesn't recognize x-www-urleconded parameters

I had a swagger documentation on version 2.0
where i put the path consumes as application/x-www-urlencoded but when i try to request i receive the following error.
{
"message": "Request validation failed: Parameter (username) is required",
"code": "REQUIRED",
"failedValidation": true,
"path": [
"paths",
"/auth/login",
"post",
"parameters",
"0"
],
"paramName": "username"
}
But i already passed the parameter as we can see on this curl
curl -X POST \
http://localhost:10010/v1/auth/login \
-H 'Cache-Control: no-cache' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'username=LOGIN&password=MYPASS&userType=employee'
I've used the following Swagger.yaml
Here you are the definition of.
definitions:
UserType: &UserType
type: string
enum: [customer, employee, supplier]
description: >
User Type:
* customer.
* employee.
* supplier.
and here the path which is utilized.
paths:
/auth/login:
# binds a127 app logic to a route
x-swagger-router-controller: "authentication"
x-a127-apply: {}
post:
summary: Try to login
description: Try to login with credencials based on username/password. This API will return all "habitant" information if login were successful.
# used as the method name of the controller
operationId: login
consumes:
- application/x-www-form-urlencoded
tags:
- Auth
parameters:
- name: username
in: formData
description: Username to login.
required: true
type: string
- name: password
in: formData
description: Password to login.
required: true
type: string
format: password
- name: userType
in: formData
required: true
default: customer
<<: *UserType
responses:
"200":
description: Success. If there are attributes with empty values they won´t be returned
schema:
# a pointer to a definition
$ref: "#/definitions/AuthResponse"
"401":
description: Unauthorized
schema:
$ref: "#/definitions/ErrorResponse"
"500":
description: Internal Server Error
schema:
$ref: "#/definitions/ErrorResponse"
"501":
description: Not Implemented
schema:
$ref: "#/definitions/ErrorResponse"
Thanks for any help.
I think it could be related to your middleware. Are you using express?
If so you may add something like this "app.use(express.urlencoded());"
You should take a look in this link:
https://www.npmjs.com/package/express-xml-bodyparser

How to send a JSON object as part of a multipart request in Swagger Editor?

I'm writing API documentation using Swagger Editor, but having a problem with a multipart POST request containing a JSON object. Here is my Swagger YAML file:
swagger: '2.0'
info:
version: 1.0.0
title: Documentation API
paths:
/agent:
post:
consumes:
- multipart/form-data
produces:
- text/html
parameters:
- in: query
name: method
description: name of method to access
required: true
type: string
- in: body
name: param
description: parameter to send
required: true
schema:
$ref: "#/definitions/Param"
responses:
201:
description: item created
400:
description: invalid input, object invalid
409:
description: an existing item already exists
definitions:
Param: # <----------
type: object
required:
- username
- password
- imsi
- imei
- deviceId
properties:
username:
type: string
password:
type: string
imsi:
type: string
imei:
type: string
deviceId:
type: string
host: 'localhost'
basePath: /v1/api
schemes:
- https
When I execute the request, I get the curl command like this:
curl -X POST "https://localhost/v1/api/agent?method=login" -H "accept: text/html" -H "content-type: multipart/form-data" -F {"username":"1234567890","password":"1234567890","imsi":"310260000000000","imei":"000000000000000","deviceId":"9ca9b02b237a6dae"}
but I expect to get this:
curl -X POST "https://localhost/v1/api/agent?method=login" -H "accept: text/html" -H "content-type: multipart/form-data" -F 'param={"username":"1234567890","password":"1234567890","imsi":"310260000000000","imei":"000000000000000","deviceId":"9ca9b02b237a6dae"}'
That is, the body parameter should be sent with the key name param.
multipart/* requests containing JSON objects can be described using OpenAPI 3.0 but not OpenAPI/Swagger 2.0.
OpenAPI 3.0
OpenAPI 3.0 natively supports JSON objects in multipart/form-data requests:
paths:
/agent:
post:
parameters:
- in: query
name: method
description: name of method to access
required: true
schema:
type: string
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
properties:
# Here, "param" is part/parameter name in a multipart payload.
# Parameter value is an object defined by the "Param" schema.
# Default Content-Type for objects is application/json.
param:
$ref: "#/components/schemas/Param"
responses:
...
OpenAPI 2.0
In OpenAPI/Swagger 2.0, when consuming form data (application/x-www-form-urlencoded or multipart/form-data), form parameters whose value is a JSON string are described as just type: string, and you cannot define the structure of the JSON string.
paths:
/agent:
post:
consumes:
- multipart/form-data
produces:
- text/html
parameters:
- ...
- in: formData # <-------
name: param
description: parameter to send
required: true
type: string # <-------
To pass in a JSON object, the operation needs to consume application/json instead:
paths:
/agent:
post:
consumes:
- application/json # <-----
produces:
- text/html
parameters:
- ...
- in: body
name: param
description: parameter to send
required: true
schema:
$ref: "#/definitions/Param"

Resources