How to send token in cookie, from server request angular universal? - javascript

I need to send from my server side to API in request headers "Cookie: token"
In angular universal, for servers Http request methods I use axios. when I try to change headers using Interceptor I have an error "Refused to set unsafe header 'Cookie'" if I send a static cookie like third arguments of axios post all work fine but I have some troubles to dynamically insert token there.
request.servise.ts
import { RequestBody } from './models/request-body.model';
import axios from 'axios';
import {AxiosInstance} from 'axios';
export class Request {
http: AxiosInstance = axios;
constructor() {}
async test(): Promise<any> {
const params = {
param1: 1,
param2: 2,
param3: 3,
}
try {
return this.basicRequest('https://some-request.url', params);
} catch (e) {
console.error('Unknown exception: ', e);
return null;
}
}
private basicRequest(url, params) {
const request = new RequestBody('2.0', 'someMethod', Math.floor(Math.random() * (9999999 - 1000000)) + 1000000, params);
return this.http.post(url, request);
}
}
projects.ts (sever router controller)
import {Router} from 'express';
import {Request} from '../../shared/request.service';
const router: Router = Router();
router.get('/test', async function(req, res, next){
const request = new Request();
try {
const projects = (await request.test()).data.result.records;
res.json(projects);
} catch (e) {
console.error(e);
}
});
export const ProjectsController: Router = router;

By default, angular universal does not transfert cookieswhen using HttpClient. So, you need to do it manually, but you'll get the error you mentionned.
A possible workaround, suggested in that universal github issue, is to bypass xhr2's default security behaviour for unsafe headers
server.ts
import * as xhr2 from 'xhr2';
xhr2.prototype._restrictedHeaders = {};

Related

Error On Express Router Setup: Router.use() requires middleware function but got a undefined

I will just say first of all that I am aware of almost all the questions asked on this site under this title.
The solutions there were pretty obvious and already done by me (with no success) or only helped for those specific cases and didn’t really work in my case unfortunately.
Now, for the problem:
I'm trying to create a route that will handle a get request and a post request which are sent to the route 'ellipses'.
These requests should receive and send data from and to an SQL database.
The problem is that for some reason the router is not ready to get these functions and gives me the error in the title:
Router.use () requires middleware function but got an undefined
Here is my code:
This code is from the file dat.js. its porpose is just to access the SQL database.
import { Sequelize } from "sequelize";
export const sequelize = new Sequelize('TheDataBaseName', 'TheUser', 'ThePassword', {
host: 'localhost',
dialect: 'mssql'
});
This code is from the file: controller.js. its porpose is to manage the requests and load the data.
import { sequelize } from "../dat";
export const sendEllipses = async (req, res, next) => {
try {
const ellipses = await getEllipsesFromJson();
return res.send(ellipses);
} catch (e) {
console.log(e);
}
};
export const addNewEllipse = async (req, res, next) => {
const { body: obj } = req;
let newEllipse;
try {
if (Object.keys(obj) !== null) {
logger.info(obj);
newEllipse = await sequelize.query(
`INSERT INTO [armageddon].[dbo].[ellipses] (${Object.keys(
obj
).toString()})
values (${Object.values(obj).toString()})`
);
} else {
console.log("the values are null or are empty");
}
return res.send(newEllipse);
} catch (error) {
console.log(error);
}
};
This code is on the file: routers.js.
its porpose is to define the route
import Router from "express";
import { sendEllipses } from "../ellipses.controller";
import { addNewEllipse } from "../ellipses.controller";
const router = Router();
export default router.route("/ellipses").get(sendEllipses).post(addNewEllipse);
This code is from the file: app.js. This is where everything actually happens.
import { router } from "../routers";
import express from "express";
app.use('/api', router);
app.listen(5000, () => {
console.log("server is runing on port 5000")
});
You need to export the router
const router = Router();
router.route("/ellipses").get(sendEllipses).post(addNewEllipse)
export default router
Now import the router:
import routes from "../router.js";
app.use('/api', routes);
Its also mentioned in the docs: https://expressjs.com/de/guide/routing.html#express-router

Cannot set headers after they are sent to the client error when using the routing-controllers package

I want to use routing-controllers package in my app. But when I add a middleware I get an error.
Here is my code:
index.ts:
import "reflect-metadata";
import { createExpressServer } from "routing-controllers";
import { UserController } from "./UserController";
const app = createExpressServer({
defaultErrorHandler: false,
controllers: [UserController],
});
app.use((req, res, next) => {
res.status(404).send("Not Found!");
});
app.listen(3000, () => {
console.log("********listening**********");
});
UserController.ts:
import { Controller, Get } from "routing-controllers";
#Controller("/users")
export class UserController {
#Get("/")
getAll() {
return "This action returns all users";
}
}
I get "cannot set headers after they are sent to the client error" when I send a request to the "/users/" endpoint. Normally the request finish and the last middleware do not run. Am i wrong?

NestJS HTTPS empty #POST() body

Im using NestJS via HTTPS.
import { NestFactory } from '#nestjs/core';
import { fstat } from 'fs';
import { AppModule } from './app.module';
import {readFileSync} from 'fs'
async function bootstrap() {
const httpsOptions = {
key:readFileSync('tsl/private-key.pem'),
cert:readFileSync('tsl/public-cert.pem')
}
const app = await NestFactory.create(AppModule,{httpsOptions});
await app.listen(3000);
}
bootstrap();
I try to get simple POST request:
#Post()
test(#Body() body){
console.log(body);
}
But output is always {}
POSTMAN:
I readed that nestjs cant parse data correctly. How can i fix that?
Your postman request needs to be set to raw and JSON, not raw and Text
Integrate swagger into your application.
It is an open API and supported by nestjs.
https://docs.nestjs.com/openapi/introduction

Pass object to Express export function

I'm working (and learning) on my TypeScript skills, although I ran into a problem: I have a class named Manager which contains and manages multiple 'sub' managers. In the index file, I load the Manager by creating an instance and calling the load function. When loading all 'sub' managers get a reference to the main/only Manager instance, this way they can call/use the other 'sub' managers.
But I would like to be able to get some info from the 'sub' managers at a REST API endpoint. These endpoints are loaded through routes:
index.ts
import "reflect-metadata";
import { createConnection } from "typeorm";
import { Request, Response } from "express";
import * as express from "express";
import * as bodyParser from "body-parser";
import { AppRoutes } from "./routes";
import { Manager } from "./manager";
createConnection().then(async (typeORMConnection) => {
const manager = new Manager();
manager.load().then(() => {
console.log("Manager has loaded all managers");
const expressApp = express();
expressApp.use(bodyParser.json());
expressApp.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "*");
res.header("Access-Control-Allow-Headers", "*");
next();
});
// Loop over every route
AppRoutes.forEach((singleRoute) => {
// Generate Express route
expressApp[singleRoute.method](singleRoute.path, (request: Request, response: Response, next: Function) => {
singleRoute.action(request, response)
.then(() => next())
.catch((error) => next(error));
});
});
// Start Express app
expressApp.listen(3000);
console.log("Express application is up and running on port 3000");
});
}).catch((error) => console.log(`TypeORM connection error: ${error}`));
A route file looks like this:
routes.ts
import { getSpeakerById, getSpeakerAll } from "./controller/get";
import { enableSpeakerById, disableSpeakerById } from "./controller/put";
export const AppRoutes = [
{
path: "/speaker",
method: "get",
action: getSpeakerAll
},
{
path: "/speaker/:id",
method: "get",
action: getSpeakerById
},
{
path: "/speaker/:id/disable",
method: "put",
action: disableSpeakerById
},
{
path: "/speaker/:id/enable",
method: "put",
action: enableSpeakerById
},
];
And last but not least this is an Express endpoint file containing the actual logic:
controller/get.ts
import { Request, Response } from "express";
import { getManager } from "typeorm";
import { Speaker } from "../entity/Speaker";
const ping = require("ping");
export async function getSpeakerById(request: Request, response: Response) {
const speakerRepository = getManager().getRepository(Speaker);
const speakerObject = await speakerRepository.findOne(request.params.id);
// If no post is found return 404
if (!speakerObject) {
response.status(404);
response.send("Speaker doesn't exist");
response.end();
return;
}
// Ping speaker and bind the time once its been resolved
speakerObject.time = await ping.promise.probe(speakerObject.host);
response.send(speakerObject);
}
export async function getSpeakerAll(request: Request, response: Response) {
const speakerRepository = getManager().getRepository(Speaker);
const speakerObjects = await speakerRepository.find();
const speakerPromise = [];
// Create a promise array of pings to all speakers
speakerObjects.forEach((speakerObject) => speakerPromise.push(ping.promise.probe(speakerObject.host)));
const speakerResults = await Promise.all(speakerPromise);
// Since the promise array is based on order we can rebind the property by looping over it in the same order
speakerResults.forEach((speakerResult, speakerIndex) => speakerObjects[speakerIndex].time = speakerResult.time);
response.send(speakerObjects);
}
Now I need to access the main Manager instance in the controller/get.ts, but I can't pass it along as parameter (for as far as I know) since it's an export. I would just import the Manager class and create a new instance but I only want to start the Manager once since it contains logic such as intervals and speaker instances from the Sonos package. I hope I was able to explain the problem but if anyone needs clarification on something I'll update the post.
You actually can pass it along as a parameter. There's nothing stopping you doing something like this in your index.ts:
// Generate Express route
expressApp[singleRoute.method](singleRoute.path, (request: Request, response: Response, next: Function) => {
singleRoute.action(request, response, manager)
.then(() => next())
.catch((error) => next(error));
});
});
And then updating the signature on you exported controller methods to be like
import { Manager } from '../manager';
export async function getSpeakerById(request: Request, response: Response, manager: Manager) {
...
}

express.session undefined in typescript

I am very new to typescript/javascript, I am trying to build backend rest apis with session
following is app.ts file
import express from "express";
import { applyMiddleware, applyRoutes } from "./utils";
import routes from "./services";
const app = express();
var ses= {
secret: "secret_session",
resave: true,
saveUninitialized: true,
cookie: { maxAge: 3600000,secure: false, httpOnly: true
}
if (app.get('env') === 'production') {
app.set('trust proxy', 1)
ses.cookie.secure = true
}
app.use(session(ses));
applyRoutes(routes, app);
I have started the server and applied the middlewares for error handling but those are not related to question in my opinion so I'm not adding code for it. Following is my routes.ts code where I'm trying to set the session.
import { Request, Response } from "express";
import { getAll, getByKeyword, addNewProduct } from "./productControllers";
{
path: "/api/v1/getAllProducts",
method: "get",
handler: [
(req: Request, res: Response) => {
getAll()
.then((row: any) => {
var sess = req.session;
sess.views = 1;
res.status(200).json({ data: row });
})
.catch(err => {
res.json({
message: err
});
});
}
]
}
I'm getting error at sess.views = 1;
I have tried the suggested questions before asking it, none of them were of any help to me.
EDIT:
I have created an index.ts
import searchRoutes from "./products/routes";
export default [...searchRoutes];
I have another util class
export const applyRoutes = (routes: Route[], router: Router) => {
for (const route of routes) {
const { method, path, handler } = route;
(router as any)[method](path, handler);
}
}
You are using an interface which is Request for express.js. But it doesn't have type definition for session. So typescript throws a compile error. To solve it you need to define session type under Request interface.
You could define a session.d.ts file under your project. And create required types & interfaces. Like:
declare global {
namespace Express {
interface Request {
session?: Session;
sessionID?: string;
}
}
}
interface Session{
mySessionVarible:string
}
But the good thing is we have DefinitilyTyped project which you can find many type definitions. This needs to solve your compile problem.
npm install --save-dev #types/express-session
And don't forget to change your import for Request.
import { Request, Response } from "#types/express-session";

Categories

Resources