I am using NextJs and it's serverless functions.
I have a api route /api/blog/write, it is a protected route. Only authorize users can access it. For this i defined a middleware which check if request is comeing from a authorize user then processed other wise redirect request to login page.
api/blog/write.js
import requiredLogin from "#middleware/required-login";
const index= (req, res) => {
const cookies = parseCookies({req}).ts
res.statusCode = 200
return res.json({ status: 'Your first blog' })
}
export default requiredLogin(index);
#middleware/required-login.js
import { parseCookies } from 'nookies';
import jwt from "jsonwebtoken";
const JWT_KEY = process.env.JWT_KEY;
const requiredLogin = (handler) => (req,res)=>{
const token = parseCookies({req}).ts;
jwt.verify(token,JWT_KEY,(err,dev)=>{
if(err) return res.status(401).redirect("/auth?auth=signin")();
return handler(req,res);
})
}
module.exports = requiredLogin;
Using the above code for required-login.js gives me
status code : 500 and error is ReferenceError: parseCookies is not defined.
When i just replace return handler(req,res); in required-login.js with return res.status(200).send(dev) then i am getting expected result.
error consoled by node is
ReferenceError: parseCookies is not defined
at index (C:\Users\Rahul kumar\desktop\Projects\dev\bdevg\.next\server\pages\api.js:110:19)
at C:\Users\Rahul kumar\desktop\Projects\dev\bdevg\.next\server\pages\api.js:151:12
at C:\Users\Rahul kumar\desktop\Projects\dev\bdevg\node_modules\jsonwebtoken\verify.js:223:12
at getSecret (C:\Users\Rahul kumar\desktop\Projects\dev\bdevg\node_modules\jsonwebtoken\verify.js:90:14)
at Object.module.exports [as verify] (C:\Users\Rahul kumar\desktop\Projects\dev\bdevg\node_modules\jsonwebtoken\verify.js:94:10)
at C:\Users\Rahul kumar\desktop\Projects\dev\bdevg\.next\server\pages\api.js:148:25
at apiResolver (C:\Users\Rahul kumar\desktop\Projects\dev\bdevg\node_modules\next\dist\next-server\server\api-utils.js:8:7)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at async DevServer.handleApiRequest (C:\Users\Rahul kumar\desktop\Projects\dev\bdevg\node_modules\next\dist\next-server\server\next-server.js:45:397)
at async Object.fn (C:\Users\Rahul kumar\desktop\Projects\dev\bdevg\node_modules\next\dist\next-server\server\next-server.js:37:176)
parseCookies is not defined in api/blog/write.js, and you use it there.
Since Node.JS (and JavaScript itself) doesn't expose variables defined in one file to another file that has be "required" by that file, you cannot access parseCookies in api/blog/write.js.
You must import it there as well.
// You must import `parseCookies`!
import { parseCookies } from 'nookies';
import requiredLogin from "#middleware/required-login";
const index= (req, res) => {
// You use parseCookies on the following line,
// so you have to import it.
const cookies = parseCookies({req}).ts
res.statusCode = 200
return res.json({ status: 'Your first blog' })
}
export default requiredLogin(index);
Related
I've been using MSW since v0.35.0. Recently I updated it to v0.40.1 and now it seems like MSW is not intercepting the request to the servers and I'm getting the following error.
Here is my test code.
import axios from 'axios';
import { rest } from 'msw';
import { setupServer } from 'msw/node';
const path = 'login/';
const accessToken = 'AccessTokenValue';
const correctCredential = { email: 'test#email.com', password: 'password' };
const server = setupServer(
rest.post(path, (req, res, ctx) => {
return res(ctx.status(200), ctx.json({ data: { access: accessToken } }));
}),
);
beforeAll(() => server.listen());
afterAll(() => server.close());
afterEach(() => server.resetHandlers());
describe('Login', () => {
test('Case: Success', async () => {
let token = '';
await axios
.post('https://test.com' + path, correctCredential)
.then((response) => (token = response.data.data.access));
expect(token).toBe(accessToken);
});
});
And this is the error I get.
Error: Request failed with status code 400
at createError (<my_local_path>)
at settle (<my_local_path>)
at IncomingMessage.handleStreamEnd (<my_local_path>)
at IncomingMessage.emit (node:events:402:35)
at endReadableNT (node:internal/streams/readable:1343:12)
at processTicksAndRejections (node:internal/process/task_queues:83:21)
Here are the versions of the other packages I use.
jest: 27.0.6
axios: 0.25.0
I read Examples from MSW and I don't see any problem with my implementation.
Perhaps this issue is relevant.
https://github.com/mswjs/msw/issues/1125
This issues was fixed 5 days ago, so I believe a corrected version will be released in the near future.
btw, downgrading to 0.36.8 is temporary solution.
**I am getting "TypeError: Cannot read properties of undefined (reading 'address')" continuously
Code of test file is
import server from '../app';
import chai from 'chai';
import chaiHttp from 'chai-http';
//Assertion Style
var should=chai.should();
chai.use(chaiHttp);
let chaiServer;
let projectCount;
const HypersignAuthToken = 'token_value'
const projectData=
{"projectName":"demo-test-26",
"logoUrl":"http://localhost:3000",
"fromDate":"2021-12-15",
"toDate":"2021-12-18",
"actions":[],
"refereePoint":5,
"referralPoint":10,
"projectStatus":1}
describe('API testing /api/v1/project', () => {
beforeEach(() => {
chaiServer=chai.request('http://localhost:6006')
// chaiServer = chai.request(server);
});
it('should be able to GET projectCount', (done)=>{
chaiServer
.get('/api/v1/project')
.auth(HypersignAuthToken,{type:'bearer'})
.end((err, response)=>{
response.should.have.status(200);
response.body.should.be.a('array');
projectCount= response.body.length;
done();
})
})
it('should add (POST) new project', (done)=>{
chaiServer
.post('/api/v1/project')
.auth(HypersignAuthToken,{type:'bearer'})
.send(projectData)
.end((err, response) => {
response.should.have.status(200);
response.body.should.be.a('object');
response.body.should.have.property('_id');
projectData['_id'] = response.body['_id'];
});
});
})
In my package.json i have
I am getting error:-
API testing for /api/v1/project
should be able to GET projectCount:
TypeError: Cannot read properties of undefined (reading 'address')
at serverAddress (node_modules/chai-http/lib/request.js:282:18)
at new Test (node_modules/chai-http/lib/request.js:271:53)
at Object.obj. [as get] (node_modules/chai-http/lib/request.js:239:14)
at Context. (src/tests/investor.ts:70:8)
at processImmediate (node:internal/timers:464:21)
We had the same issue in our project. Make sure to export the express app in your app.js, for example like this:
export const app = express()
Then in your test, import it properly and adjust your definition of chaiServer:
import { app } from '../app'
// in your `beforeEach` handler
chaiServer = chai.request(app)
I'm using nestjs and I was trying to create a custom decorator:
import { createParamDecorator, ExecutionContext } from '#nestjs/common';
import { User } from './user.entity';
export const GetUser = createParamDecorator(
(data, ctx: ExecutionContext): User => {
const req = ctx.switchToHttp().getRequest();
return req.user;
},
);
The decorator is used here:
#Post('/test')
#UseGuards(AuthGuard())
test(#GetUser() user: User) {
console.log(user);
}
But I get the following error:
[Nest] 15053 - 26/03/2020, 13:28:19 [ExceptionsHandler] ctx.switchToHttp is not a function +61625ms
TypeError: ctx.switchToHttp is not a function
at /Users/nelson.larios/Documents/nestjs/nestjs-task-management/dist/auth/get-user.decorator.js:5:21
at /Users/nelson.larios/Documents/nestjs/nestjs-task-management/node_modules/#nestjs/core/router/router-execution-context.js:115:35
at resolveParamValue (/Users/nelson.larios/Documents/nestjs/nestjs-task-management/node_modules/#nestjs/core/router/router-execution-context.js:143:31)
at Array.map (<anonymous>)
at pipesFn (/Users/nelson.larios/Documents/nestjs/nestjs-task-management/node_modules/#nestjs/core/router/router-execution-context.js:148:45)
at /Users/nelson.larios/Documents/nestjs/nestjs-task-management/node_modules/#nestjs/core/router/router-execution-context.js:36:36
at InterceptorsConsumer.intercept (/Users/nelson.larios/Documents/nestjs/nestjs-task-management/node_modules/#nestjs/core/interceptors/interceptors-consumer.js:10:20)
at /Users/nelson.larios/Documents/nestjs/nestjs-task-management/node_modules/#nestjs/core/router/router-execution-context.js:45:60
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at async /Users/nelson.larios/Documents/nestjs/nestjs-task-management/node_modules/#nestjs/core/router/router-proxy.js:8:17
Any thoughts?
Thanks
Prior to version 7.x, Custom Decorators were static, and thus did not get the ExecutionContext passed to them. In v7.x release, this has been added.
As mentioned in comments on the OP's question, you need to upgrade to this version to get the example in the documentation working.
I am making an app with reactjs frontend and nodejs backend api for that at someplace i getting error something like this.
But here i want to get only this message email: {message: "This email is already taken", I tried to parse this error using some online turorial but when i try them i get error from backend.
This is the error after using errorparser
(node:14208) UnhandledPromiseRejectionWarning: ReferenceError: errors is not defined
at exports.default (C:/projects/bookworm-practice/bookworm-api/src/utils/parseErrors.js:5:15)
at C:/projects/bookworm-practice/bookworm-api/src/routes/users.js:14:54
at process._tickCallback (internal/process/next_tick.js:68:7)
(node:14208) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:14208) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
this is my parseError function
import _ from 'lodash';
export default function () {
const result = {};
_.forEach(errors, (val, key) => {
result[key] = val.message;
});
return result;
}
this is my user function where i am using parseError
import express from 'express';
import User from '../models/User';
import parseErrors from '../utils/parseErrors';
const router = express.Router();
router.post('/', (req, res) => {
const { email, password } = req.body.user;
const user = new User({ email });
user.setPassword(password);
user.save()
.then(user => res.json({ user: user.toAuthJSON() }))
//.catch(err => res.json({ err })); // this is the default one
.catch(err => res.status(400).json({ errors: parseErrors(err.errors)
//this is after adding parseErrors funtion
}))
})
export default router;
Your parseErrors function did not includes errors as argument
import _ from 'lodash';
export default function (errors) {
const result = {};
_.forEach(errors, (val, key) => {
result[key] = val.message;
});
return result;
}
UPDATED QUESTION
The problem is ApiError: Error during request.
Code:
import * as functions from 'firebase-functions';
const cors = require('cors')({ origin: true });
import * as admin from 'firebase-admin';
const gcs = admin.storage();
export const deleteImage = functions.https.onRequest((req, res) => {
return cors(req, res, async () => {
res.set('Content-Type', 'application/json');
const id = req.body.id;
const name = req.body.name;
const imageRef = gcs.bucket(`images/${name}`);
if (!name || !id) {
return res.status(400).send({message: 'Missing parameters :/'});
}
try {
await imageRef.delete();
console.log('Image deleted from Storage');
return res.status(200).send({status: 200, message: `Thank you for id ${id}`});
}
catch (error) {
console.log('error: ', error);
return res.status(500).send({message: `Image deletion failed: ${error}`});
}
});
});
And the problem is here: await imageRef.delete();, I get the following error:
ApiError: Error during request.
I do, indeed, have admin.initializeApp(); in one of my other functions, so that can't be the issue, unless GCF have a bug.
More In-Depth Error:
{ ApiError: Error during request.
at Object.parseHttpRespBody (/user_code/node_modules/firebase-admin/node_modules/#google-cloud/common/src/util.js:187:32)
at Object.handleResp (/user_code/node_modules/firebase-admin/node_modules/#google-cloud/common/src/util.js:131:18)
at /user_code/node_modules/firebase-admin/node_modules/#google-cloud/common/src/util.js:496:12
at Request.onResponse [as _callback] (/user_code/node_modules/firebase-admin/node_modules/#google-cloud/common/node_modules/retry-request/index.js:198:7)
at Request.self.callback (/user_code/node_modules/firebase-admin/node_modules/request/request.js:185:22)
at emitTwo (events.js:106:13)
at Request.emit (events.js:191:7)
at Request.<anonymous> (/user_code/node_modules/firebase-admin/node_modules/request/request.js:1161:10)
at emitOne (events.js:96:13)
at Request.emit (events.js:188:7)
code: undefined,
errors: undefined,
response: undefined,
message: 'Error during request.' }
(old question removed)
"Error: Can't set headers after they are sent" means that you tried to send two responses to the client. This isn't valid - you can send only one response.
Your code is clearly sending two 200 type responses to the client in the event that imageRef.delete() fails and the catch callback on it is triggered.
Also, you're mixing up await with then/catch. They're not meant to be used together. You choose one or the other. Typically, if you're using await for async programming, you don't also use then/catch with the same promise. This is more idiomatic use of await with error handling:
try {
await imageRef.delete()
res.status(200).send({status: 200, message: `Thank you for id ${id}`});
} catch (error) {
res.status(500).send({message: `Image deletion failed: ${err}`});
}
Note also that you typically send a 500 response to the client on failure, not 200, which indicates success.