In my Node.js app I return an error like this:
app.get('/api/login', (req, res, next) => {
//...
return res.status(400).send({
isSuccess: false,
errors: ["error 1", "error 2"]
})
})
In Angular, how can I get the error?
login() {
const headers = new HttpHeaders().set('Accept', 'application/json').set('Content-Type', 'application/json');
this.http.post('http://localhost:3000/api/login', { username: 'arwels', password: '24899632' }, { headers: headers }).subscribe(response => {
// ok
}, (err) => {
console.log(err) // Bad Reqeust
});
}
When I print err in the error section, it prints Bad Reqeust. Where is the object that is sent by the server?
You can use an HttpInterceptor to capture error responses from your API.
Ref: https://angular.io/api/common/http/HttpInterceptor
Here's an Example:
export class MyHttpInterceptor implements HttpInterceptor {
constructor() {
}
intercept( req: HttpRequest<any>, next: HttpHandler ): Observable<HttpEvent<any>> {
return next.handle(request).pipe(
catchError(async (_err: HttpErrorResponse, _caught: any) => {
switch (_err.status) {
case 401:
...
break;
case 500:
...
break;
default:
...
break;
}
return of(_err);
})
) as any;
}
}
Since you have full control over how you are returning your errors in your API, you can tailor the HttpInterceptor to work with any error object you want to create on your backend.
Unfavorable Option
If you just want the entire response so you can sniff out the statusCode, you can also just {observe: 'response'} in the HttpHeaders.
this.http.get<HttpResponse<any>>(<url>, {observe: 'response'}).pipe(
tap(resp => console.log('response', resp))
);
Related
I am using React and Express to create a web application.
However, the response to a request using the ky library will contain a default message.
How do I get a custom message?
By the way, this works on Postman & axios library.
//Custom Error
class HttpException extends Error {
status: number;
message: string;
constructor(status: number, message: string) {
super(message);
this.status = status;
this.message = message;
}
}
export default HttpException;
//Express
import HttpException from '../exceptions/HttpException';
if (!Object.keys(result).length) throw new HttpException(404, "User does not exist")
//Express error handling middleware
export const errorMiddleware = (err: HttpException, req: express.Request, res: express.Response, next: express.NextFunction) =>{
const status = err.status || 500;
const message = err.message || 'Something went wrong';
res
.status(status)
.send({
status,
message,
})
}
//React
import ky from 'ky'
const customKy = ky.create({
prefixUrl: process.env.NEXT_PUBLIC_API_HOST,
credentials: "include",
headers: { 'Content-Type': 'application/json' },
});
try {
const result: any = await customKy.post("path", { json: data }).json()
} catch (err: any) {
console.log(err.response.status)
console.log(err.response.message)
}
//result console
login.tsx:28 404
login.tsx:29 undefined
Im using NodeJS/Angular.
I wanted to render a document using Carbone in NodeJS, and send the result in a http request.
Myfile.js:
router.get('/executeFusion/', async (req, res) => {
try {
// Data to inject
const data = {
firstname: 'BLB',
lastname: 'MAR'
};
carbone.render('./node_modules/carbone/examples/simple.odt', data, async function(err, result) {
if (err) {
return console.log(err);
}
});
const file = './result.odt';
res.download(file);
}
catch (err) {
errorDbHandler.sendErrorHttp(err, res);
}
});
MyComponent.ts:
this.fusionService.executeFusion()
.subscribe(data => {console.log(data)},
(error) => console.log(error));
MyService.ts :
export class FusionService {
constructor(private httpClient: HttpClient, private configService: ConfigService) { }
executeFusion() {
return this.httpClient.get<any>(`${this.configService.getUrlApi()}/api/Fusion/executeFusion/`);
}
}
But the, I got this error:
The main idea here is, generating a document in NodeJS, send it to Angular in order to download it.
The error is related to promise which is mentioned in the question:
this.fusionService.executeFusion().toPromise().then(res => {
console.log(res);
}).catch(e) {
console.log(e);
}
But when you request the Http request in angular, you should use httpClient to make it and it returns the observable like this:
this.fusionService.executeFusion()
.subscribe(data => {console.log(data)},
(error) =>. console.log(error));
And, to make the express server send the file as a downloaded one:
res.download(file);
xport class FusionService {
constructor(private httpClient: HttpClient, private configService: ConfigService) { }
executeFusion() {
return this.httpClient.get<any>(`${this.configService.getUrlApi()}/api/Fusion/executeFusion/`, {response: 'application/txt'}); // type should match the type you are sending from API
}
}
for more details check here.
I am building an app with React and NestJS.
In NestJS, I have an API endpoint to upload a photo like so:
#Controller('api/upload')
export class UploadController {
constructor(private readonly uploadService: UploadService) {}
#Post()
#UseInterceptors(
FileInterceptor('image', {
storage: diskStorage({
destination: './myphoto',
filename: (req, file, cb) => {
if (file.mimetype !== 'image/png')
// how do I return an Http error message here?
return cb(null, 'myphoto.png');
},
}),
}),
)
uploadPhoto(#UploadedFile() image) {
}
}
In React, I am using axios and redux-thunk to hit this endpoint like so:
export const uploadPhotoAsync = (data: FormData) => {
return (dispatch: ThunkDispatch<{}, {}, AnyAction>) => {
return axios.post('http://localhost:8080/api/upload', data)
.then(() => {
dispatch({ type: UPLOAD_PHOTO_COMPLETE, error: null });
})
.catch((e) => {
dispatch({ type: UPLOAD_PHOTO_COMPLETE, error: e.message });
});
};
};
As you can see, if there is an error message, we want to catch it and store it in state to display to the user.
My question is: how do I use NestJS to return an error message so that it can be caught by my front-end error handler? In the if statement in my controller, I tried just doing something like throw new UnsupportedMediaException("My error message here") but all that appears to do is throw the error on the server-side and nothing gets sent to the client.
Any help would be greatly appreciated.
I am very to new nodejs and angular 7 I am using jwt token for authentication, I want to redirect automatically to the login page once token get expire. I know similar question have been asked already but I also tired that way I didn't work out for me.
admin.controller.js
const controller = require("./admin.service");
const jwt = require("jsonwebtoken")
module.exports = {
verifyAdmin: (req, res) => {
const sign = jwt.sign({admin_user: req.body}, "mysecretkey", {
expiresIn: "1h"
})
req.body.admin_token = sign
const body = req.body;
controller.adminLogin(body, (err, result) => {
if(err) {
console.log(err)
res.status(500).json({
success: 0,
message: "Database connection error"
})
} else{
if(result[0].length > 0) {
console.log(result[0][0].admin_user)
res.json({
success: 1,
message: result[0],
token: sign
})
} else {
res.json({
success:0,
message: "We cannot find it"
})
}
}
})
}
So someone suggested the using HttpInterceptor is good idea for this I used that too but not wokring.
auth.service.ts
import { Injectable } from '#angular/core';
import { HttpClient, HttpParams, HttpHeaders, HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpErrorResponse } from '#angular/common/http';
import { Teacher } from '../shared/teacher.model';
import { Subject, Observable } from 'rxjs';
#Injectable()
export class AuthService implements HttpInterceptor {
// private adminValidateUrl = "http://localhost:3000/getData";
private adminValidateUrl = "http://localhost:3000/adminApi/verifyAdmin"
private verifyAdminToken = "http://localhost:3000/adminApi/getAdminUserName"
private getTeacherRecordsUrl = "http://localhost:3000/api/getTeacherRecords"
private removeTeacherUrl = "http://localhost:3000/adminApi/removeTeacherRecord"
subject = new Subject<Teacher[]>();
teachers: Teacher[] = []
constructor(private http: HttpClient) { }
headers = new Headers({
'Content-Type': 'application/json',
'Token': localStorage.getItem("admin_token")
});
adminValidation(adminData: any) {
console.log(adminData)
return this.http.post<any>(this.adminValidateUrl, adminData)
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const authReq = req.clone({ headers: req.headers.set("Token", localStorage.getItem("Token")) });
console.log("Sending request with new header now ...");
//send the newly created request
return next.handle(authReq)
.pipe(err => {
// onError
console.log(err);
if (err instanceof HttpErrorResponse) {
console.log(err.status);
console.log(err.statusText);
if (err.status === 401) {
window.location.href = "/login";
}
}
return Observable.throw(err);
}) as any;
}
getAdminUserName() {
const token = localStorage.getItem('admin_token');
return this.http.get<any>(this.verifyAdminToken, {
observe: "body",
headers: new HttpHeaders().set("Authorization", "Bearer " + token)
});
}
getTeacherRecordsFromDB() {
return this.http.get<any>(this.getTeacherRecordsUrl, {
observe: "body"
})
}
removeTeacher(teacher: Teacher) {
const token = localStorage.getItem('admin_token');
return this.http.post<any>(this.removeTeacherUrl, teacher, {
observe: "body",
headers: new HttpHeaders().set("Authorization", "Bearer " + token)
})
}
}
or may be I am not using it right.
so I want a way I which my angular page automatically redirect to login page when token expires with some message of token expire.
Thanks.
Hey You can use following code inside interceptor to redirect page to login when token expired
return next.handle(request).pipe(
catchError(error => {
if (error instanceof HttpErrorResponse
&& (error.status === 403 || error.status === 401)) {
localStorage.removeItem('accessToken');
window.location.href = '/login';
return throwError(error);
} else {
return throwError(error);
}
})
)
I have a nodeJS express server application in TypeScript. When an error occurs I want to add some text to it and read it in the client Angular application.
NodeJS Server, express code:
import {
Request,
Response
} from 'express';
if (medewerker) {
verifyPassword(medewerker.id, req.body.wachtwoord).then(isVerifiedPassword => {
if (isVerifiedPassword) {
.......
} else {
throw new Error('Wachtwoord niet juist ingevoerd');
}
}).catch(error => {
console.log(error);
res.status(401).json('I want to show this text: ' + error);
})
}
Client code:
this.httpClient.put(this.url + 'medewerker/login', {
'email': authData.userId,
'wachtwoord': authData.password
}, {
headers: this.headertjes,
withCredentials: true,
observe: 'response',
responseType: 'json'
})
.subscribe((data1: HttpResponse < MedewerkerTypeId > ) => {
if (data1 != null) {
.....
}
}, ((error: HttpErrorResponse) => {
console.log(error.statusText) //here I want to grep and show my text.
}));
But I get an error: undefined message.
I tried all the options but only default properties like error.status and error.message works. But no Custom messages like I want.
Maybe somebody can help me ?
The body of the ErrorResponse can be accessed using the error property.
Change your code like this:
this.httpClient.put(this.url + 'medewerker/login', {
'email': authData.userId,
'wachtwoord': authData.password
}, {
headers: this.headertjes,
withCredentials: true,
observe: 'response',
responseType: 'json'
})
.subscribe((data1: HttpResponse < MedewerkerTypeId > ) => {
if (data1 != null) {
.....
}
}, ((error: HttpErrorResponse) => {
console.log(error.error) //here error contains the text
}));