Improve Http validation error message in middy validator of lambda - javascript

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!

Related

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,
...

Flush and send response object periodically in Node.js

I am new to Node.js and i am trying to refresh the data periodically using the below code:
router.post('/getMessage',function(req,res){
setInterval(findMessage,5000);
function findMessage() {
Message.find(
{
$or: [
{sender: req.body.sender, receiver: req.body.receiver},
{sender: req.body.receiver, receiver: req.body.sender}
]
},
(err, data) => {
res.send({success: true, data: data});
}
);
}
});
But this gives an error: "Cannot set headers after they are sent". I understand that res.send calls res.end() implicitly and therefore this error is occuring. And have tried res.write() also. But i am returning an object and not a String or buffer, hence it also failed to work.
It would be great if someone could give an example of how to achieve this exactly.
response.send() method does two task
1. write content on the response and send.
2. End connection with res.end().
So, when you did response.send(), then it sends your message and closes the connection. For that reason, you getting the error "Cannot set headers after they are sent".
So, the conclusion is that you can't send multiple responses using response.send().
You can achieve this by the socket.io or you can make the request from frontend after an interval.

How do I get the post json when there is a 404 error?

I have a service call that when it returns a 404 error, I want to display the message that comes from the server when the status is 404. So, in event of an error or success, I get a post json that gives me a status code and message that indicates if it was successful or not.
Currrently, I have this service call:
this._transactionService.findExistingTransaction(user, searchNumber)
.subscribe(data => {
this.transactionResponse = data;
console.log(JSON.stringify(this.transactionResponse));
this.router.navigate(['/edit-transaction-portal'], {queryParams: {bill: searchNumber}});
this.onDismiss();
}, (err) => { this.displayErrors = true;});
on error, it will set the bool displayErrors = true and then I can show the error message in my UI.
In html code:
<input #inputtedNumber class="transactionInput" placeholder="{{numberPlaceholder | translate }}"/>
<div class="error-msg1" *ngIf="displayErrors" style="margin-left:90px;" name="errorMsg">
{{transactionResponse._errorDetails._message}} </div>
This is the json that gets posted back when I directly try to access api endpoint:
{
"_transactionNumber":null,
"_order":null,
"_errorDetails":{
"_status":"404",
"_message":"Number is not available"
}
}
I bind to the transactionResponse object that I get back from my service call. Unfortunately, although I believe this should work, I get the issue that _errorDetails is undefined and so nothing shows up.
I wonder if this is the right setup for something like this? If now, how can I fix it?
Thanks!
EDIT: Duplicate SO post with no answer: How to read Custom error message from backend in Angular 4/2
The response body from the server should be in the error property of the error response that comes back in the error callback.
Regarding HttpErrorResponse, the documentation states:
A response that represents an error or failure, either from a non-successful HTTP status, an error while executing the request, or some other failure which occurred during the parsing of the response.
Any error returned on the Observable response stream will be wrapped in an HttpErrorResponse to provide additional context about the state of the HTTP layer when the error occurred. The error property will contain either a wrapped Error object or the error response returned from the server.
If you want to use the same transactionResponse to display the errors, then assign the error property of the err that comes back to this.transactionResponse.
Service Call
this._transactionService.findExistingTransaction(user, searchNumber).subscribe(
(data) => {
this.transactionResponse = data;
console.log(JSON.stringify(this.transactionResponse));
this.router.navigate(['/edit-transaction-portal'], {queryParams: {bill: searchNumber}});
this.onDismiss();
},
(err: HttpErrorResponse) => {
this.displayErrors = true;
// assign the error property of the err that comes back to the transactionResponse
this.transactionResponse = err.error;
});
HTML
Then this will work.
<input #inputtedNumber class="transactionInput" placeholder="{{ numberPlaceholder | translate }}"/>
<div class="error-msg1" *ngIf="displayErrors" style="margin-left:90px;" name="errorMsg">
{{transactionResponse._errorDetails._message}}
</div>
There was some work done to this part of Angular in September 2017. parse error response body for responseType "json" So you may need to update Angular depending on your version.
This solution was tested on the following:
Node v8.2.1
NPM v5.3.0
Angular CLI: 1.7.2
Angular: 5.0.0
Edit: StackBlitz example
HttpErrorResponse StackBlitz example
This example makes some assumptions about what the service looks like and what endpoint it is calling. The service makes a POST call to www.google.com. This fails and returns an HttpErrorResponse.
{
"isTrusted": true
}
The error property of the HttpErrorResponse is assigned to this._transactionResponse. This can then be accessed in the template and displayed in the browser.
Your problem is that in the event of an error, your
data => {
this.transactionResponse = data;
code does not get called - you got an error response, not a normal response afterall.
Try to get the information from the
}, (err) => { this.transactionResponse = err
part.
I think you can use a typed response:
On your error notification type you could have something like:
err => {
this.localErrorResponse = err as ErrorResponse;
this._order= this.localErrorResponse._order;
}
inside your class, also, you could have:
import { ErrorResponse } from './error-response';
localErrorResponse: ErrorResponse;
_order: string;
and then, you could have your ErrorResponse class like:
import { ErrorDetail } from './error-detail';
export class ErrorResponse{
_transactionNumber: number;
_order: string;
_errorDetails: ErrorDetail;
}
and class ErrorDetail
export class ErrorDetail {
_status: number;
_message: string
}
then you can map some other variables, as _order (this._order), or get them from your localErrorResponse (this.localErrorResponse) variable
I have a service call that when it returns a 404 error, I want to
display the message that comes from the server when the status is 404
...
I bind to the transactionResponse object that I get back from my
service call. Unfortunately, although I believe this should work, I
get the issue that _errorDetails is undefined and so nothing shows up.
Try this:
StackBlitz EXAMPLE

How to handle backend errors from Node/Koa on frontend apollo-client

My frontend, using apollo-client, throws an exception when the backend returns an error after a request.
When the node server receives a request, I check the validity of the request's token using koa middleware. If the token is valid, the request is forwarded to the next middleware. If the token is invalid, I want to return a 401 access denied error to the client. To do this, I followed Koa's error documentation located here.
The code for the error handling middleware I wrote:
function userIdentifier() {
return async (ctx, next) => {
const token = ctx.request.headers.authorization
try {
const payload = checkToken(token)
ctx.user = {
id: payload.userId,
exp: payload.exp,
iat: payload.iat,
}
} catch (error) {
ctx.user = undefined
ctx.throw(401, "access_denied")
// throw new Error("access_denied")
}
await next()
}
}
This seemingly works on the backend, but not on the frontend. When the frontend receives this error, a JavaScript runtime error occurs. I am not sure what causes this.
Note, the unexpected "a" is the same "a" found in ctx.throw(401, "access_denied"). If it were instead ctx.throw(401, "x") the frontend shows "unexpected token x" instead.
The frontend code where the errors happens:
In an attempt to fix this, I followed Apollo's error handling documentation and used apollo-link-error.
const errorLink = onError(props => {
const { graphQLErrors, networkError } = props
console.log("ON ERROR", props)
if (graphQLErrors)
graphQLErrors.map(({ message, locations, path }) =>
console.log(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
)
)
if (networkError) console.log(`[Network error]: ${networkError}`)
})
Then I combine all links and create the Apollo client like this:
const link = ApolloLink.from([errorLink, authLink, httpLink])
export const client = new ApolloClient({
link,
cache: new InMemoryCache(),
})
The output of the debugging log in apollo-link-error is as follows:
Related Documents
Someone seems to be having an identical error, but a solution was not listed.
I found that the errors were handled correctly on the frontend when I began using this library on the backend: https://github.com/jeffijoe/koa-respond
Using just ctx.unauthenticated()
But I would still like to know more about how to return json/object-based errors with koa without a plugin helping

Swagger Nodejs - Response Validation Failed

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

Categories