how I can write headers using way nest.js?
I'm currently using this:
import { Controller, Body, Get, Post, HttpCode, HttpStatus, Req, Res } from '#nestjs/common';
import { Request, Response } from 'express';
import { AuthService } from './auth.service';
import { Usuario } from '../usuario/usuario.entity';
import { JsonWebTokenError } from 'jsonwebtoken';
import { request } from 'http';
#Controller('auth')
export class AuthController {
constructor(private readonly authService: AuthService) { }
#Post('login')
#HttpCode(HttpStatus.OK)
async login(#Body('username') username: string, #Body('password') password: string, #Res() response: Response) {
this.authService
.validateUser(username, password)
.then((token) => {
response.setHeader('Authorization', 'Bearer ' + token);
let respuesta: any = {};
respuesta.success = true;
respuesta.token = token;
return response.send(respuesta);
});
}
}
I do not want to use response.setHeader('Authorization', 'Bearer ' + token); and return response.send(respuesta);
Thanks for your answers!
NestJS is build on top of express, so do it like in express:
async login(#Body('username') username: string, #Body('password') password: string, #Res() res: Response) {
const token = await this.authService.validateUser(username, password);
res.set('Authorization', 'Bearer ' + token);
res.send({
success: true,
token,
})
});
In latest versions you could use the #Header decorator within NestJS Core.
import { Controller, Get, Req, Header, Res } from '#nestjs/common';
import { Request, Response } from 'express';
#Controller('cookies')
export class CookiesController {
#Get('set')
// #Header('Set-Cookie', 'cookieName = 12345') // "Usin header decorator"
setCookie(#Res() response: Response): Response {
/*
* If using express approach, pass #Res as param decorator
*/
response.cookie('rememberme', '1') // Using express res object.
return response.send('Cookie has been set! :)')
}
#Get()
checkCookie(#Req() request: Request ): string {
console.log(Object.keys(request.cookies))
if(Object.keys(request.cookies).length > 0){
console.log('cookies =>', request.cookies)
return 'Cookies are set :)'
} else {
return 'Uh, oh! Cookie hasn\'t been set :\'('
}
}
}
Related
I am quite new with typescript/express and I have a problem with importing a middleware.
Indeed, I have a module auth.ts which will contain in a near future several middlewares. Here is its current implementation (with only one middleware for keeping simple).
import { Request, Response } from "express";
import jwt, { JwtPayload } from "jsonwebtoken";
export function getConnectedPerson(req: Request, res: Response, next) {
try {
const token = req.headers.authorization.split(' ')[1];
const { personId } = jwt.verify(token, process.env.TOKEN_SEED) as JwtPayload;
res.locals.personId = personId;
next();
} catch {
res.status(401).send("Invalid request");
}
}
and here is my controller implementation:
import { Request, Response, Router } from "express";
import { autoInjectable } from "tsyringe";
const authMiddleware = require("auth")
#autoInjectable()
export class ActivityController {
constructor() {
}
initRoutes(router: Router) {
router.get('/activities', [
authMiddleware.getConnectedPerson
],async (req: Request, res: Response) => {});
}
}
when starting my app, I get the following error:
Error: Route.get() requires a callback function but got a [object Object]
I am a bit lost with all the possible import/export/require variants. Would you know what is wrong with my implementation ?
In auth.ts, export is going wrong i feel. Please do the following changes and try
import { Request, Response } from "express";
import jwt, { JwtPayload } from "jsonwebtoken";
function getConnectedPerson(req: Request, res: Response, next) {
try {
const token = req.headers.authorization.split(' ')[1];
const { personId } = jwt.verify(token, process.env.TOKEN_SEED) as JwtPayload;
res.locals.personId = personId;
next();
} catch {
res.status(401).send("Invalid request");
}
}
function getConnectedPerson_1(req: Request, res: Response, next) {
// some operation
console.log("second function export");
next();
}
exports.getConnectedPerson = getConnectedPerson;
exports.getConnectedPerson_1 = getConnectedPerson_1;
in controller :-
import { Request, Response, Router } from "express";
import { autoInjectable } from "tsyringe";
//const authMiddleware = require("auth")
const { getConnectedPerson, getConnectedPerson_1 } =require("./auth")
#autoInjectable()
export class ActivityController {
constructor() {
}
initRoutes(router: Router) {
router.get('/activities', [ getConnectedPerson, getConnectedPerson_1 ],async (req: Request, res: Response) => {});
}
}
I'm currently rewriting old request service to use HttpClient instead of Http. My app makes use of ngrx store and after I rewrote request service, it stopped working.
here's my request service:
import { Injectable } from '#angular/core';
import {HttpClient, HttpHeaders} from '#angular/common/http';
import { ToastController } from 'ionic-angular';
import { ReplaySubject } from 'rxjs/ReplaySubject';
import { Config } from '../app/app.config';
import {Observable} from 'rxjs/Rx';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import { Version } from '#angular/compiler';
export enum HttpStatus {
UNAUTHORIZED,
WRONGVERSION,
UNVERIFIED,
NONETWORK,
}
export interface HttpNotifierData {
status: HttpStatus
}
#Injectable()
export class HttpClientService {
private httpNotifier: ReplaySubject<HttpNotifierData>;
constructor(
public toastCtrl: ToastController,
private _http: HttpClient,
) {
this.httpNotifier = new ReplaySubject();
}
createHeaders(contentType?: string) {
var headers = new HttpHeaders();
let token = localStorage.getItem('auth_token');
let expires = localStorage.getItem('auth_expires');
let appVersion = Config.version+'';
if(token)
headers = headers.set( 'Authorization', 'Bearer ' + token);
if(expires)
headers = headers.set( 'TokenExpiration', expires);
if(appVersion)
headers = headers.set( 'App-Version', appVersion);
if(contentType === 'form')
headers = headers.set('Content-Type','application/x-www-form-urlencoded');
return headers;
}
createAppVersionHeader(headers: Headers) {
let appVersion = Config.version+'';
headers.append('App-Version', appVersion);
}
getHttpNotifier(): ReplaySubject<HttpNotifierData> {
return this.httpNotifier;
}
request(verb: string, url: string, data?: any, contentType?: string) {
let headers = this.createHeaders(contentType);
return this._http.request(verb, url, {
body: data,
headers: headers
}).catch(err => {
if (err.status == 0) {
this.httpNotifier.next({status: HttpStatus.NONETWORK});
err._body = 'Kunne ikke kontakte baksystem';
} else if (err.status == 401) {
this.httpNotifier.next({status: HttpStatus.UNAUTHORIZED});
} else if (err.status == 403) {
this.httpNotifier.next({status: HttpStatus.UNVERIFIED});
} else if (err.status == 412) {
this.httpNotifier.next({status: HttpStatus.WRONGVERSION});
} else {
// TODO: Convert API error to user friendly error
this.toastCtrl.create({
message: err._body,
duration: 3000,
showCloseButton: true,
closeButtonText: "Lukk",
cssClass: 'error',
}).present();
}
throw err;
});
}
get(url) {
let cache = '?cache=' + Math.ceil(Math.random() * 100000);
return this.request('GET', url + cache);
}
post(url, data, contentType = 'json') {
return this.request('POST', url, data, contentType);
}
put(url, data) {
return this.request('PUT', url, data);
}
delete(url) {
return this.request('DELETE', url);
}
}
my user auth service:
import { Injectable } from '#angular/core';
import { Config } from '../app/app.config';
import { HttpClientService } from "./http.service";
#Injectable()
export class UserService {
constructor(
private _http: HttpClientService
) { }
login(username: string, password: string) {
var data = "grant_type=password&username=" + username + "&password=" + password + "&deviceId=test";
return this._http.post(Config.apiUrl + 'Token', data, 'form');
}
getPin(phone: string) {
return this._http.post(Config.apiUrl + 'api/account/forgotPassword', {phoneNumber: phone})
}
}
my ngrx effect for authenticating user:
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/observable/of';
import { Injectable } from '#angular/core';
import { Effect, Actions } from '#ngrx/effects';
import { Observable } from 'rxjs/Observable';
import { UserService } from '../services/user.service';
import * as UserActions from '../actions/user.actions';
#Injectable()
export class UserEffects {
constructor(
private actions: Actions,
private userService: UserService
) {}
#Effect()
login:Observable<any> = this.actions
.ofType(UserActions.LOGIN)
.map((action: UserActions.Login) => action.payload)
.switchMap(payload => {
return this.userService.login(payload.username, payload.password)
.map((response:any) => new UserActions.LoginSuccess(JSON.parse(response._body)))
.catch((error) => Observable.of(new UserActions.LoginFailed(error._body)))
});
#Effect()
getPin:Observable<any> = this.actions
.ofType(UserActions.GET_PIN)
.map((action: UserActions.GetPin) => action.payload)
.switchMap(payload => {
return this.userService.getPin(payload)
.map((response: any) => new UserActions.GetPinSuccess())
.catch((error) => Observable.of(new UserActions.GetPinFailed(error._body)))
});
}
when debugging, I have this error appearing in effect module:
however, in network section I can see that request is completed successfully:
what can be wrong with my service?
ok, so I figured out the solution.
effects for login should have pipe and no json parsing:
#Effect()
login:Observable<any> = this.actions
.ofType(UserActions.LOGIN)
.map((action: UserActions.Login) => action.payload)
.switchMap(payload => {
return this.userService.login(payload.username, payload.password).pipe()
.map((response:any) => new UserActions.LoginSuccess(response))
.catch((error) => Observable.of(new UserActions.LoginFailed(error._body)))
});
I am getting the error message in cli like :
Type 'Headers' has no properties in common with type 'RequestOptionsArgs'
. However, the code executes. The version I am using is 5, as it shows in package.json. I am unable to find a good http example, which suit my need. I want to send some parameters in headers section, and authorize it in php. Here is the service code:
user.service.ts
import { Observable } from 'rxjs/Observable';
import { Customer } from './../models/customer';
import { Injectable } from "#angular/core";
import { Http, Response, Headers, RequestOptions } from "#angular/http";
import "rxjs/add/operator/map";
import { apiServicesURL,appServicesURL } from "../constants/globals";
import { HttpClient, HttpHeaders } from "#angular/common/http";
#Injectable()
export class UserService {
//headers : Headers ;
constructor(private http: Http) {
}
getCustomerInfoo(custId): Observable<Customer> {
//cust.push({token : localStorage.getItem('token')});
console.log(apiServicesURL + 'getCustomers');
let token = localStorage.getItem('token');
let api_token = localStorage.getItem('api_token');
let email = localStorage.getItem('email');
let headers = new Headers({ 'Content-Type': 'application/json' });
// let options: RequestOptions = new RequestOptions({ headers: headers });
return this.http.post(apiServicesURL + 'getCustomers', JSON.stringify({ customer_id: custId, token: api_token, email: email }), headers ).map((response: Response) => {
// login successful if there's a jwt token in the response
return <Customer>response.json();
});
}
}
Any help, appreciated!!!
If you are using angular 5 then try it this below code and write RequestOptionsProvider to module.ts file
import { Injectable } from '#angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HTTP_INTERCEPTORS } from '#angular/common/http';
import { AuthService } from '#app/core/services/auth.service';
import { Observable } from 'rxjs/Observable';
#Injectable()
export class DefaultRequestOptionsService implements HttpInterceptor {
constructor(private auth: AuthService) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// Get the auth header from the service.
// const authHeader = this.auth.getAuthorizationHeader();
// Clone the request to add the new header.
// const authReq = req.clone({headers: req.headers.set('Authorization', authHeader)});
const authReq = req.clone({ headers: req.headers.set('Content-Type', 'application/json') });
// Pass on the cloned request instead of the original request.
return next.handle(authReq);
}
}
export const RequestOptionsProvider = { provide: HTTP_INTERCEPTORS, useClass: DefaultRequestOptionsService, multi: true };
I am trying to intercept a 401 response, send a refresh token request before trying request again (but with a different header). I have it working except retryWhen does not give me to modify the original request header. So I've been trying to use catchError instead but I cannot seem to execute the request again.
Here is my current retryWhen:
import {Injectable} from '#angular/core';
import {
HttpInterceptor, HttpHandler, HttpRequest, HttpEvent, HttpErrorResponse
}
from '#angular/common/http';
import {Observable} from 'rxjs/Observable';
import {CustomerService} from "../customer/customer.service";
import * as ApplicationSettings from "application-settings";
import {retryWhen, map} from "rxjs/operators";
import {LoginResponse} from "./LoginResponse";
/**
* This takes a request that requires an access_token and refreshes it on 401 errors.
*/
#Injectable()
export class RefreshTokenInterceptor implements HttpInterceptor {
public constructor(private customer: CustomerService) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).pipe(
retryWhen(errors => {
return Observable.create(observer => {
errors.forEach((error: HttpErrorResponse) => {
if (error.status === 401) {
let refresh_token = ApplicationSettings.getString('refresh_token');
return this.customer.refreshToken(refresh_token).subscribe(
(response: LoginResponse) => {
this.customer.setToken(response);
let headers = req.headers.set('Authorization', `Bearer ${response.access_token}`);
console.log(`Bearer ${response.access_token}`);
let newReq = req.clone({headers: headers});
observer.next(next.handle(newReq));
observer.complete();
},
error2 => {
observer.error();
}
);
} else {
observer.error();
}
});
});
})
);
}
}
If I swap out retryWhen with catchError:
catchError((err, caught) => {
console.log('err: ' + JSON.stringify(err));
if (err.status === 401) {
console.log('401 !!!! REFRESH MEH!');
let newReqOb: Observable<HttpEvent<any>> = Observable.create(observer => {
console.log('going to refresh token');
let refresh_token = ApplicationSettings.getString('refresh_token');
let refresh = this.customer.refreshToken(refresh_token);
refresh.subscribe((response: LoginResponse) => {
console.log('token refreshed!');
this.customer.setToken(response);
let access_token = ApplicationSettings.getString('access_token');
let headers = req.headers.set('Authorization', `Bearer ${access_token}`);
console.log(`Bearer ${access_token}`);
let newReq = req.clone({headers: headers});
observer.next(next.handle(newReq)); // <-- HERE IT WONT FIRE
observer.complete();
});
});
return newReqOb;
}
return caught;
})
The important part is I am returning next.handle(newReq) and it doesn't seem to fire the request. If I switch it to next.handle(newReq).subscribe(), the request will fire but no callbacks are triggered.
Here is the full example with retryWhen:
import {Inject, Injectable} from '#angular/core';
import {
HttpInterceptor, HttpHandler, HttpRequest, HttpEvent, HttpErrorResponse, HttpClient
}
from '#angular/common/http';
import {Observable, ObservableInput} from 'rxjs/Observable';
import {CustomerService} from "../customer/customer.service";
import * as ApplicationSettings from "application-settings";
import {retryWhen, map, catchError} from "rxjs/operators";
import {LoginResponse} from "./LoginResponse";
import {APP_CONFIG, AppConfig} from "../../app.config";
/**
* This takes a request that requires an access_token and refreshes it on 401 errors.
*/
#Injectable()
export class RefreshTokenInterceptor implements HttpInterceptor {
public constructor(private customer: CustomerService, private http: HttpClient, #Inject(APP_CONFIG) private config: AppConfig) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).pipe(
catchError((err, caught) => {
console.log('err: ' + JSON.stringify(err));
if (err.status === 401) {
console.log('401 !!!! REFRESH MEH!');
let newReqOb: Observable<HttpEvent<any>> = Observable.create(observer => {
console.log('going to refresh token');
let refresh_token = ApplicationSettings.getString('refresh_token');
let refresh = this.customer.refreshToken(refresh_token);
refresh.subscribe((response: LoginResponse) => {
console.log('token refreshed!');
this.customer.setToken(response);
let access_token = ApplicationSettings.getString('access_token');
let headers = req.headers.set('Authorization', `Bearer ${access_token}`);
console.log(`Bearer ${access_token}`);
let newReq = req.clone({headers: headers});
observer.next(next.handle(newReq));
observer.complete();
});
});
return newReqOb;
}
return caught;
})
);
}
}
I did find out the issue, here is the resulting code:
import {Inject, Injectable} from '#angular/core';
import {
HttpInterceptor, HttpHandler, HttpRequest, HttpEvent, HttpErrorResponse, HttpClient
}
from '#angular/common/http';
import {Observable, ObservableInput} from 'rxjs/Observable';
import {CustomerService} from "../customer/customer.service";
import * as ApplicationSettings from "application-settings";
import {catchError, switchMap, finalize} from "rxjs/operators";
import {LoginResponse} from "./LoginResponse";
import {APP_CONFIG, AppConfig} from "../../app.config";
import {RouterExtensions} from "nativescript-angular/router";
/**
* This takes a request that requires an access_token and refreshes it on 401 errors.
* #TODO What happens on 400 errors?
*/
#Injectable()
export class RefreshTokenInterceptor implements HttpInterceptor {
isRefreshingToken: boolean = false;
public constructor(private customer: CustomerService,
private http: HttpClient,
private router: RouterExtensions,
#Inject(APP_CONFIG) private config: AppConfig) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
let validate = {
is_api_v1: req.url.indexOf('api/v1') > -1,
is_not_register_end_point: !(req.url.indexOf('api/v1/customers') > -1 && req.method === 'POST')
};
if (validate.is_api_v1 && validate.is_not_register_end_point) {
return next.handle(req).pipe(
catchError((err, caught) => {
if (err instanceof HttpErrorResponse && err.status === 401) {
console.log(req.url);
console.log('Injecting Refresh Token');
return this.handle401Error(req, next);
}
// return caught;
})
);
} else {
return next.handle(req);
}
}
handle401Error(req: HttpRequest<any>, next: HttpHandler) {
//-- Test if we are refreshing so we are not stuck in an infinite loop
if (!this.isRefreshingToken) {
this.isRefreshingToken = true;
let refresh_token = ApplicationSettings.getString('refresh_token');
let refresh = this.customer.refreshToken(refresh_token);
return refresh.pipe(
switchMap((tokenResp: LoginResponse) => {
this.customer.setToken(tokenResp);
let access_token = ApplicationSettings.getString('access_token');
let headers = req.headers.set('Authorization', `Bearer ${access_token}`);
return next.handle(req.clone({headers: headers}));
}),
catchError(error => {
ApplicationSettings.setBoolean("authenticated", false);
this.router.navigate(["/login"], { clearHistory: true, queryParams: {
error: 'Your session is no longer valid, please log in again',
}});
return Observable.throw("");
}),
finalize(() => {
this.isRefreshingToken = false;
})
)
}
}
}
First I'm new new to angular 2. I'm trying to call two difference API in single service. But it wont return any value second API 'getCityById' but the API 'getCities' return the value.
Here my code:
import { Injectable } from '#angular/core';
import { Http, Headers,Response} from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/Rx';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/toPromise';
import { Cities } from './cities';
#Injectable()
export class CitiesService {
private CityListUrl = "APIurl";
private CityUrl = "APIurl2";
constructor(private http: Http) {}
getCities(): Observable<Cities[]> {
const headers = new Headers();
headers.append('Access-Control-Allow-Headers', 'Content-Type');
headers.append('Access-Control-Allow-Methods', 'GET,PUT,POST,OPTIONS');
headers.append('Access-Control-Allow-Origin', '*');
return this.http.get(this.CityListUrl,{headers: headers})
.map(this.extractData)
.catch(this.handleError);
}
getCityById(CityId:Number): Observable<any> {
const headers = new Headers();
headers.append('Access-Control-Allow-Headers', 'Content-Type');
headers.append('Access-Control-Allow-Methods', 'GET,PUT,POST,OPTIONS');
headers.append('Access-Control-Allow-Origin', '*');
var params = 'cityid='+CityId;
console.log("____________"+this.CityUrl);
console.log(this.http.post(this.CityUrl,params,{headers: headers})
.map(this.extractData));
return this.http.post(this.CityUrl,params,{headers: headers})
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
console.log(res);
let Cities = res.json();
return Cities || { };
}
private handleError(error: Response) {
console.log(error);
return Observable.throw(error.json().error || "500 internal server error");
}
}
I'm not sure what I'm wrong. Please help with this.