handle HTTP status codes in Angular 5 - angular5

I'm trying to capture http status codes in angular in service which calls a backend service, i'm facing issues as i see status 204 , but when logging angular show status null, here is what i'm doing in my service:
return this.http.get<JSON>(mybackendsserviceurl)
.do(res => {
})
.catch(res => {
return this.handleError(res);
});
}
private handleError(err: HttpErrorResponse) {
console.log(err.message);
return Observable.throw(err.message);
}
How to catch different errors from backend service, like 204,403,404,500...etc and display a user friendly message for each error?
my frontend is calling the service from API gateway and i'm setting the errors in Response Integrations.

To handle different status codes just check them:
this.http.get<JSON>(<URL>)
.subscribe(
res => console.log(res),
err => {
console.error(err);
this.handleError(err);
});
private handleError(err: HttpErrorResponse) {
if( err.status == 500 ) {
return Observable.throw(new Error(<YOUR USERFRIENDLY MESSAGE>));
} else if( err.status == 400 ) {
return Observable.throw(new Error(<YOUR MESSAGE>));
}
// you can also catch all errors of a group like this
else if( err.status < 500 && err.status >= 400 ) {
return Observable.throw(new Error(<CLIENT ERROR MESSAGE>));
}
}
In your UI you can handle the Observable and of course, show a nice dialog with the error message.

Related

Flutter:400 Bad request when i make a request to gmail of googleapis

I want to get a respond from Gmail of googleapis so I use a package:googleapis/gmail/v1.dart and make a code service.users.messages.list(_currentUser.email, q:'from:$searchingWord'); get list of email filtered by q:.
But there is a 400 Bad request, So, after debugging I found this url https://www.googleapis.com/gmail/v1/users/(myEmail)/messages?q=from%3Anoreply%40github.com&alt=json.
It's a bad request, so it's a url problem, but I'm not sure what's wrong.
I need your help.
The code where the problem occurred
Future<gMail.GmailApi> getGMailApi() async {
return gMail.GmailApi(await getGoogleClient());
}
Future<AuthClient> getGoogleClient() async {
return await clientViaServiceAccount(await getCredentials(), [
'email',
'https://mail.google.com/',
'https://www.googleapis.com/auth/gmail.modify',
'https://www.googleapis.com/auth/gmail.readonly'
]);
}
Future<ServiceAccountCredentials> getCredentials() async {
if (credentials == null) {
credentials = ServiceAccountCredentials.fromJson(await rootBundle
.loadString('android/app/todoapp-270005-c7e7aeec11f7.json'));
}
print(credentials);
return credentials;
}
Future<void> handleGetMail(String searchingWord) async {
gMail.GmailApi service = (await getGMailApi());
gMail.ListMessagesResponse response =
await service.users.messages.list(_currentUser.email, q:'from:$searchingWord');
List<gMail.Message> messages;
while (response.messages != null) {
messages.addAll(response.messages);
if (response.nextPageToken != null) {
String pageToken = response.nextPageToken;
response = await service.users.messages
.list(_currentUser.email, q:'from:$searchingWord', pageToken: pageToken);
} else {
break;
}
}
for (gMail.Message message in messages) {
print(message.toString());
}
}

How do I return an error from a Controller in Loopback 4?

I have a controller method
// ... inside a controller class
#get('/error', {})
async error() {
throw new Error("This is the error text");
}
The response I'm getting from this error front-end is:
{
"error": {
"statusCode": 500,
"message": "Internal Server Error"
}
}
What I would like the error to be is:
{
"error": {
"statusCode": 500,
"message": "This is the error text"
}
}
How do I return an error from a controller in Loopback 4?
Hello from the LoopBack team 👋
In your controller or repository, you should throw the Error exactly as shown in your question.
Now when LoopBack catches an error, it invokes reject action to handle it. The built-in implementation of reject logs a message via console.error and returns an HTTP response with 4xx/5xx error code and response body describing the error.
By default, LoopBack hides the actual error messages in HTTP responses. This is a security measure preventing the server from leaking potentially sensitive data (paths to files that could not be opened, IP addresses of backend service that could not be reached).
Under the hood, we use strong-error-handler to convert Error objects to HTTP responses. This module offers two modes:
Production mode (the default): 5xx errors don't include any additional information, 4xx errors include partial information.
Debug mode (debug: true): all error details are included on the response, including a full stack trace.
The debug mode can be enabled by adding the following line to your Application constructor:
this.bind(RestBindings.ERROR_WRITER_OPTIONS).to({debug: true});
Learn more in our docs: Sequence >> Handling errors
Alternatively, you can implement your own error handler and bind it as the sequence action reject. See Customizing sequence actions in our docs.
export class MyRejectProvider implements Provider<Reject> {
constructor(
#inject(RestBindings.SequenceActions.LOG_ERROR)
protected logError: LogError,
#inject(RestBindings.ERROR_WRITER_OPTIONS, {optional: true})
protected errorWriterOptions?: ErrorWriterOptions,
) {}
value(): Reject {
return (context, error) => this.action(context, error);
}
action({request, response}: HandlerContext, error: Error) {
const err = <HttpError>error;
const statusCode = err.statusCode || err.status || 500;
const body = // convert err to plain data object
res.statusCode = statusCode;
res.setHeader('Content-Type', 'application/json; charset=utf-8');
res.end(JSON.stringify(body), 'utf-8');
this.logError(error, statusCode, request);
}
}
If you just want to show error message, you just extend Error object and throw it like below. (Loopback documentation didn't mention this anyway)
Avoid using 5xx error and use 4xx error to show some important thing to user is best practice and so that Loopback4 was implemented like this.
class NotFound extends Error {
statusCode: number
constructor(message: string) {
super(message)
this.statusCode = 404
}
}
...
if (!await this.userRepository.exists(id)) {
throw new NotFound('user not found')
}
For my situation, I found a catch in my sequence.ts file. Inside the catch, it checked if the error had a status code of 4xx, and if not, it just returned a anonymous 500.
Here's the code I was looking for to do the logic:
// sequence.ts
...
} catch (err) {
console.log(err);
let code: string = (err.code || 500).toString();
if (code.length && code[0] === '4') {
response.status(Number(code) || 500);
return this.send(response, {
error: {
message: err.message,
name: err.name || 'UnknownError',
statusCode: code
}
});
}
return this.reject(context, err);
}
...
Here's how you tell it what to do:
// ... inside a controller class
#get('/error', {})
async error() {
throw {
code: 400,
message: "This is the error text",
name: "IntentionalError"
}
}
To throw custom validation error I use this method:
private static createError(msg: string, name?: string): HttpErrors.HttpError {
const error = new HttpErrors['422'](msg);
error.name = name ?? this.name;
return error;
}
Catch error examples here are for defaultSequence, overriding the handle method.
But nowdays app template uses MiddlewareSequence.
So here is the example, how tomodify the response in middleware sequence, you can use this example:
import { Middleware, MiddlewareContext } from '#loopback/rest';
export const ErrorMiddleware: Middleware = async (middlewareCtx: MiddlewareContext, next) => {
// const {response} = middlewareCtx;
try {
// Proceed with next middleware
return await next();
} catch (err) {
// Catch errors from downstream middleware
// How to catch specific error and how to send custom error response:
if (HttpErrors.isHttpError(err) || (err as HttpErrors.HttpError).statusCode) {
const code: string = (err.statusCode || 500).toString();
if (code.length && code[0] === '4') {
response.status(Number(code) || 500);
return response.send({
error: {
message: err.message,
name: err.name || 'UnknownError',
statusCode: code
}
});
}
}
throw err;
}
};
And register the middleware in application.ts
this.middleware(ErrorMiddleware);

Unable to get error message from API Angular 6

I use the following function to Post a object of a given class.
public Post<T>(object: T, url: string, httpOptions: {}): Observable<T> {
return this.httpClient.post<T>(`${environment.apiEndpoint}` + url, object, httpOptions)
.pipe(
catchError(this.handleError)
);
}
This function is called in all the service that wants to post something. Like this.
public addEquipment(equipment: Equipment): Observable<Equipment> {
return this.shared.Post<Equipment>(equipment, this.url, this.header);
}
addEquipment is then executed within the component that uses that service. Like this.
this.equipmentService.addEquipment(result)
.subscribe((data: any) => { this.alertService.success(data) }, (error: any) => this.alertService.error(error));
The problem is when the API returns a error (that I can see includes a error message, in the network tab) it tells me that there is no body in the response. The API returns a HttpResult where the error message is added to the response field.
return new HttpResult { StatusCode = HttpStatusCode.Conflict, Response = "Error message"}
I use the following function to handle the errors.
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', error.error.message);
}
else {
console.log(error);
console.error(
`Backend returned code ${error.status}, ` +
`body was: ${error.error}`);
}
console.log(error);
return throwError(
error.error)
};
It is Angular 6 and a ServiceStack API.
All suggestions would be appreciated.
FYI it's preferable to return structured error responses in ServiceStack which you can do with:
HttpError.Conflict("Error message");
Which will let you catch it when using ServiceStack's TypeScript ServiceClient with:
try {
var response = await client.post(request);
} catch (e) {
console.log(e.responseStatus.message);
}
But from this answer for handling errors with Angular HTTP Client it suggests the error body should be accessible with:
this.httpClient
.get("data-url")
.catch((err: HttpErrorResponse) => {
// simple logging, but you can do a lot more, see below
console.error('An error occurred:', err.error);
});

react native fetch request to localhost server, even after change to IPV4

I'm trying to make http request in my react native app(in android in real device) with the localhost url.
after it failed in localhost url with the error
Network request Failed
I changed it to my ipv4 but it still not works.
but when I'm using in POSTMAN to check with my ipv4 it looks it works fine.
try {
let response = await fetch("http://myIPV4address:3008", {
method: method,
headers: headers,
body: body != null ? JSON.stringify(body) : null,
})
console.log('response:',response)
const endTime = (new Date()).getTime();
if( response.status == 401 ) {
return Promise.reject(response);
}
if( response.status == 400 ) {
return Promise.reject(response);
}
if( response.status == 404 ) {
return Promise.reject(response);
}
if( response.status == 500 ) {
return Promise.reject(response);
}
if( response.status == 502 ) {
return Promise.reject(response);
}
let responseJson = response.headers.map['content-type'][0].includes('application/json') ? await response.json() : response.statusText;
return responseJson;
} catch(error) {
console.error(error);
}
maybe it is settings in react native app I need to change?
Solution:
I connected to the wifi where the pc is connect because before it doesn't know what is localhost is
look for dns server the solution is to configure your emulator

Return false from Promise: should it resolve(false) or reject()?

I am making a request to a server via HTTP, to see if a user with a specific email exists.
function userExists(id) {
return makeHttpRequestToServer(id)
.then((response) => {
if (response === 200) {
// User exists in the database
} else if (response === 404) {
// User does not exist in the database
}
});
}
I am unsure how I should handle the resolve/reject calls:
Should I resolve() when the user is found in the database, and reject() when the user is not found in the database?
Should I resolve(true) when the user is found in the database, and accept(false) when the user is not found in the database?
You should use resolve to return any non-error response, and reject only for errors and exceptions.
Searching for a specific entry in a database that does not contain the entry is not necessarily an error, so you should resolve(false).
function userExists(id) {
return makeHttpRequestToServer(id)
.then((response) => {
if (response === 200) {
// User exists in the database
resolve(true);
} else if (response === 404) {
// User does not exist in the database
resolve(false);
} else {
// Something bad happened
reject(new Error("An error occurred"));
}
});
}
This makes it easier to differentiate between returning false, and having an error occur.
When handling callbacks, it is conventional to preserve the first returned argument for error responses, and the remaining arguments for returned values.
function userExists(id, callback) {
makeHttpRequestToServer(id)
.then((response) => {
if (response === 200) {
// User exists in the database
callback(undefined, true);
} else if (response === 404) {
// User does not exist in the database
callback(undefined, false);
} else {
// Something bad happened
callback(new Error(response));
}
}
}