Swagger Nodejs - Response Validation Failed - javascript

I am building the API with Swagger and NodeJS, the annoying problem I have faced so far is Swagger validates the response, and it's not always smooth.
My case:
In file .yaml: I checked the yaml syntax with Swagger Editor => File Yaml is correct.
/user/createNew:
x-swagger-router-controller: xxxxxxx
post:
tags:
- User
summary: Create New User
# used as the method name of the controller
operationId: createNewUser
parameters:
- name: NewUserReq
in: body
required: true
description: Email register
schema:
$ref: "#/definitions/NewUserReq"
responses:
"201":
description: Successful
schema:
# a pointer to a definition
$ref: "#/definitions/CreateUserResp"
# responses may fall through to errors
default:
description: Error
schema:
$ref: "#/definitions/ErrorResponse"
CreateUserResp:
properties:
status:
type: integer
description: Response status
response:
$ref: "#/definitions/MsgResponse"
MsgResponse:
required:
- resp_msg
properties:
resp_msg:
type: string
To check the response format, I generated the NodeJs file from Swagger Editor
examples['application/json'] = {
"response" : {
"resp_msg" : "aeiou"
},
"status" : 123
};
In controller file .js:
function createNewUser(req,res){
....
var resp = new Object();
resp.resp_msg=data.email;
final_response.status = 200;
final_response.response = resp;
console.log("createNewUser::Query succeffully", JSON.stringify(final_response));
//{"status":200,"response":{"resp_msg":"test#gmail.com"}}
res.set('Content-Type', 'application/json');
res.json(final_response);
}
Try to run API with Postman, the error happens with log below:
Error: Response validation failed: failed schema validation
at throwErrorWithCode (/var/app/current/node_modules/swagger-express-mw/node_modules/swagger-node-runner/node_modules/swagger-tools/lib/validators.js:121:13)
at Object.module.exports.validateAgainstSchema (/var/app/current/node_modules/swagger-express-mw/node_modules/swagger-node-runner/node_modules/swagger-tools/lib/validators.js:176:7)
at /var/app/current/node_modules/swagger-express-mw/node_modules/swagger-node-runner/node_modules/swagger-tools/middleware/swagger-validator.js:141:22
at /var/app/current/node_modules/swagger-express-mw/node_modules/swagger-node-runner/node_modules/swagger-tools/node_modules/async/lib/async.js:356:13
at async.forEachOf.async.eachOf (/var/app/current/node_modules/swagger-express-mw/node_modules/swagger-node-runner/node_modules/swagger-tools/node_modules/async/lib/async.js:233:13)
at _asyncMap (/var/app/current/node_modules/swagger-express-mw/node_modules/swagger-node-runner/node_modules/swagger-tools/node_modules/async/lib/async.js:355:9)
at Object.map (/var/app/current/node_modules/swagger-express-mw/node_modules/swagger-node-runner/node_modules/swagger-tools/node_modules/async/lib/async.js:337:20)
at validateValue (/var/app/current/node_modules/swagger-express-mw/node_modules/swagger-node-runner/node_modules/swagger-tools/middleware/swagger-validator.js:134:11)
at ServerResponse.res.end (/var/app/current/node_modules/swagger-express-mw/node_modules/swagger-node-runner/node_modules/swagger-tools/middleware/swagger-validator.js:252:9)
at ServerResponse.send (/var/app/current/node_modules/express/lib/response.js:205:10)
I cannot figure out what caused the error, I double checked the structure of JSON response.
Very appreciate for any suggestion.

You have put required: true which means you have to pass that parameter otherwise Response Validation Failed will appear.

I tried to reproduce but it gives me some errors. However, I tried removing MsgResponse and defining CreateUserResp as a single definition, and it worked:
CreateUserResp:
type: object
properties:
response:
type: object
properties:
resp_msg:
type: string
description: The response object
status:
type: number
description: The status code
It seems like you're not defining response as an object, and just adding some properties to it.

After trying some experiments, I made it work. My solution simply is changing response code "201" to "200" in yaml file, and it worked. I don't know why I left the response code "201". Anyway, I am still new with this, and don't know if it's a best practice or not. I am open to receive any better suggestion.

You can get this error if you don't specify in the header the data type sent within the request body
Content-Type : application/json

Related

Improve Http validation error message in middy validator of lambda

When I develop sample apps by serverless-framework, I use middy validator,I expect that when validation error occured, detailed information will be returned.
const transactions: ValidatedEventAPIGatewayProxyEvent<typeof schema> = async (event) => { logic
};
export const handler = middy(transactions)
.use(httpHeaderNormalizer()) // normalize http header to canonical format eg Content-type to Content-Type
.use(httpJsonBodyParser())
.use(validator({ inputSchema:
{type:'object',
required:['body'],
properties: { body:schema }}}))
.use(httpErrorHandler())
After setting above lambda function,I tried this function by throwing event parameter.
it returned following details in my console. must NOT be shorter than 28 characters is easy to understand root cause.
POST /development/transactions (λ: transactions)
HttpError [BadRequestError]: Event object failed validation
at createError (/Users/h/pricing/node_modules/#middy/validator/node_modules/#middy/util/index.js:193:12)
{
cause: [
{
instancePath: '/body/OtherCustomerFeePattern',
schemaPath: '#/properties/body/properties/OtherCustomerFeePattern/minLength',
keyword: 'minLength',
params: [Object],
message: 'must NOT be shorter than 28 characters'
}
],
statusCode: 400,
status: 400,
expose: true
}
But when I put event from client(postman) to my localhost, it returned like
Event object failed validation
It is not understandable of root cause . why detailed error didn't respond ?
My parameter and response is like follows in postman.
If somene has opinion or experienced similar issues. will you please let me know . Thanks!

Cast to ObjectID failed for value (Front end side problem)

So I have been given an API to which I need to send a post request to create a task within a list, but when I try to send the request, I get the following error (I am trying it in postman).
The following is the schema of a post request body I need to send to the API, and the image is the request I am sending with the postman (I need to use the x-www-form-urlencoded because otherwise, it is not working)
{
title: { type: String,required:true},
description: String,
done:Boolean,
date: { type: Date, default: Date.now },
list:{
type: Schema.ObjectId,
ref: 'List'
}
So can you please help me with this?
I get the following error.
Cast to ObjectID failed for value \"Daily Tasks\" at path \"list\"
The API is expecting you to pass the id of a List, not its name.
It's probably expecting you to do an other API call before to get that id.
It should look like this: "507f1f77bcf86cd799439011"
Additionally, you can look at the documentation of MongoDB for information about the ObjectId format: https://docs.mongodb.com/manual/reference/method/ObjectId/

Can't understand WebAuthn API error from JavaScript

I am currently building out an AJAX registration endpoint for Django to allow for FIDO2 authentication (physical hardware key login). This is from following the example/documentation from Yubico's official fido2 python library.
The only dependencies are cbor.js and js-cookie. Everything server-side is working for now, however, I keep getting this JavaScript error while invoking the navigator.credentials.create method
TypeError: Failed to execute 'create' on
'CredentialsContainer': The provided value is not of
type '(ArrayBuffer or ArrayBufferView)'
The code:
var csrftoken = Cookies.get('csrftoken');
fetch('/register/begin', {
method: 'POST',
headers: {
'X-CSRFToken': csrftoken
}
}).then(function(response) {
if(response.ok) {
return response.arrayBuffer();
}
throw new Error('Error getting registration data!');
}).then(CBOR.decode).then(function(options) {
console.log(options)
//This line is not working
return navigator.credentials.create(options);
//More code... complete registration...
I can't figure this out. Do you know whats wrong? Thanks!
I had the same problem, and the cause was that some of the pieces of data sent from the server in the response from /register/begin must be formatted as byte strings rather than unicode strings. In particular, I've found that the user_id and the credential ids have to be byte strings - assuming that you are also following Yubico's example in the server, implemented in python 3.
Also of note is that in this case I've found Firefox's error messages much more helpful than chome's.
I was having this issue as well. I ended up using the TextEncoder class to encode the challenge and the user id...
const enc = new TextEncoder();
const createCredentialOptions: CredentialCreationOptions = {
publicKey: {
rp: rp,
challenge: enc.encode(challenge),
user: {
id: enc.encode(user.id),
name: user.name,
displayName: user.displayName
},
pubKeyCredParams: pubKeyCredParams,
...

How to create a new contact with Google contacts api v3 - using javascript

Even if this issue has been raised many times over the past year, it's not yet correctly solved ... especially when using the latest googleapis lib ! Google doc is not useful as many deprecated methods are still mentioned and no javascript examples are given...
using people.get() ( after a list() ) I can get a view on how it should be ( I guess)
{
"resourceName":"people/c3451490284670017263",
"etag":"%EgcBAggJNyUuGgwBAgMEBQYHCAkKCwwiDHVtR0Y5OHZVMnhJPQ==",
"locales":[{"metadata":{"primary":true,"source":{"type":"CONTACT","id":"2fe628208b77deef"}},"value":"en"}],
"emailAddresses":[{"metadata":{"primary":true,"source":{"type":"CONTACT","id":"2fe628208b77deef"}},"value":"john.doe#example.com"]
}
so I tried to create a new People this way :
return google.people('v1').people.createContact({
auth: jwtClient,
resourceName: 'people/me',
locales: ['en'],
genders: ['female'],
names: [{givenName: 'Jenny', familyName: 'Doe'}],
emailAddresses: ['jenny.doe#example.com']
})
but NO WAY... I am always getting errors :
Invalid JSON payload received. Unknown name \"genders\": Cannot bind query parameter. Field 'genders' could not be found in request message.
Invalid JSON payload received. Unknown name \"locales\": Cannot bind query parameter. Field 'locales' could not be found in request message.
Invalid JSON payload received. Unknown name \"names[familyName]\": Cannot bind query parameter. Field 'names[familyName]' could not be found in request message.
Invalid JSON payload received. Unknown name \"emailAddresses\": Cannot bind query parameter. Field 'emailAddresses' could not be found in request message.
Invalid JSON payload received. Unknown name \"names[givenName]\": Cannot bind query parameter. Field 'names[givenName]' could not be found in request message.
Invalid JSON payload received. Unknown name \"resourceName\":Cannot bind query parameter. Field 'resourceName' could not be found in request message.
Is any example existing on the web ?
feedback welcome ... ( even from a Google man... LOL )
After double-checking (maybe triple...) the documentation , I read the following statement
Usage
Specifying request body
The body of the request is specified in the requestBody parameter object of the request. The body is specified as a JavaScript object with key/value pairs. For example, this sample creates a watcher that posts notifications to a Google Cloud Pub/Sub topic when emails are sent to a gmail account:
const res = await gmail.users.watch({
userId: 'me',
requestBody: {
// Replace with `projects/${PROJECT_ID}/topics/${TOPIC_NAME}`
topicName: `projects/el-gato/topics/gmail`
}
});
console.log(res.data);
so I wrote :
return google.people('v1').people.createContact({
auth: jwtClient,
parent: 'people/me',
requestBody: {
locales: [{ value: 'en' }],
genders: [{ value: 'female' }],
names: [{ givenName: 'Jenny', familyName: 'Doe' }],
emailAddresses: [{ value: 'jenny.doe#example.com' }]
}
})
And the request is executed without any error ... I can see the new contact in mt Google account app Contacts..

How to check if there is any payload (POST) data in a request with hapijs?

This is what I have:
server.route({
method: 'POST',
path: '/somePath/',
config: {
payload:{
output: 'stream'
}
});
I expect a short XML and that is why I using 'stream' instead of 'data'. I am using FakeToe as the XML parser as it is stream based and in my handler function I call request.payload.pipe(parser). All I want to check is if there is any POST data in the request and if not send a bad request back to the user.
I have thought about getting the size of data in the request.payload stream but there does not seem to be straightforward of doing that without pulling first and then pushing back data into the stream, which I don't like.
Everything works perfectly when the data is there, but if not FakeToe does not call the callback function with an error saying that the stream is empty. Also, I do not want to call request.payload.read method myself just to check if there is any data.
Any way to do that in hapijs?
You can use Joi to validate the presence of a payload. It is a schema and validation module provided by Hapi. It will automatically validate any requests received at an endpoint and reply with an appropriate badRequest message if the validation fails.
var Joi = require('Joi');
server.route({
method: 'POST',
path: '/somePath/',
config: {
payload:{
output: 'stream'
}
validate: {
payload: Joi.any().required()
}
});
More about this here and here.
EDIT:
As per the discussion in this GitHub Issue, a validation object like
Joi.object({
pipe: Joi.func().required()
}).unknown();
Can be used to test whether the payload is actually a stream.
I suppose that you have content-length header ? You could check that from request.headers instead of reading the payload.

Categories