Neoheurist
Neoheurist

Reputation: 3474

Handling Angular HTTP 404 error from server actually which represents a valid response with no records

I have a situation where the web services that I am using are inconsistently coded and I have no way to change their behavior. My main issue is that the web service returns an HTTP 404 error on a valid GET method in cases where there are no records within the backend database corresponding to the conditions of the query. The correct behavior should be a 200 HTTP response with an empty array of elements (e.g. list of companies).

I have an Angular interceptor with a catchError function that I've coded to recognize cases where the 404 really isn't an error. Within this logic I want to suppress the error and return a response that contains body: {companies: []}.

Is there a way to do this?

@Injectable()
export class TokenInterceptor implements HttpInterceptor {
    public intercept(request: { clone: (arg0: { headers: any; }) => any; headers: { set: (arg0: string, arg1: string) => any; }; }, next: { handle: (arg0: any) => any; }) {

...

        return next.handle(request.clone({headers})).pipe(
            // retry(1),
            catchError((error: HttpErrorResponse) => {
                let message;

                if (error.error instanceof ErrorEvent) {
                    message = `Client error: ${error.error.message}`;
                }
                else {
                    message = `Server code: ${error.status}\nMessage: ${error.message}`;

                    // detect 404 error that aren't really errors

                    if (404 === error.status && [Webservices.GET_MEMBER_COMPANIES, Webservices.GET_MEMBER_PERSONS, Webservices.GET_MEMBER_PERSON_COMPANY_LINKS, Webservices.GET_MEMBER_VISUALIZATION_STATES].some((path: string) => {
                        return (new RegExp(path.replace(Webservices.MEMBER_ID, '\\d+').replace(Webservices.COMPANY_ID, '\\d+').replace(Webservices.PERSON_ID, '\\d+').replace(Webservices.VISUALIZATION_STATE_ID, '\\d+'))).test(error.url);
                    })) {
                        console.debug(error);
                    }
                }

                console.debug(headers);
                console.debug(message);

                // window.alert(message);

                return throwError(message);
            })
        );
    }
}

Note: the above is a work in progress provided solely to illustrate the state of the error handler

Thanks!

Upvotes: 0

Views: 3221

Answers (1)

andellapie
andellapie

Reputation: 176

Inside your catchError you need to return an Observable<HttpResponse>. Try this:

import {of} from 'rxjs'; //Add this

catchError((error: HttpErrorResponse) => {
    if (404 === error.status){
        var response = new HttpResponse({
             body: {companies: []} //your body object
        });
        return of(response);
    }
    return throwError(message);
}

Explanation: if you look at interceptor signature (HttpEvent) intercept(req:HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> the return type is Observable<HttpEvent<any>> which is an Angular type defined as:

type HttpEvent<T> = HttpSentEvent | HttpHeaderResponse | HttpResponse<T> | HttpProgressEvent | HttpUserEvent<T>;

So build your HttpResponse variable and use of operator to return it as Observable.

That's all.

Upvotes: 4

Related Questions