Consolidate all REST service requests and match the server's response to my specific object model

My goal was to develop a versatile REST service that could be utilized across all my services. For instance, for handling POST requests, the following code snippet demonstrates how I implemented it:

post<T>(relativeUrl: string, body?: any,  params?: HttpParams, headers?: HttpHeaders): Observable<HttpResponse<T>> {
        return this.executeRequest(this.createRequest(relativeUrl, body, params, headers, 'POST'))
    }

A similar approach was taken for other HTTP request methods as well. These methods make use of the createRequest and executeRequest functions.

// TODO: Finish and check arguments
    private createRequest(relativeUrl: string, body: any, params: HttpParams | null, headers: HttpHeaders | null, method: string ): HttpRequest<any> {

        let url: string;
        if (relativeUrl.startsWith('http') || relativeUrl.startsWith('https')) {
            url = relativeUrl;
        } else {
            url = `${environment.restUrl}/${relativeUrl}`;
        }


        headers = headers || new HttpHeaders()
        //TODO: If user is logged add Authorization bearer in headers

        return new HttpRequest(method, url, body, {
            headers: headers,
            params: params
        })
    }

    private executeRequest(request: HttpRequest<any>): Observable<HttpResponse<any>> {
        return <any> this.http.request(request)
            .pipe(
                catchError(error => {
                    return throwError(error);
                })
            );
    }

I have some queries regarding the implementation of these methods. Are they properly structured? Is the response from the HTTP requests handled correctly? As an example, my login.service utilizes the POST method in the following manner:

login<User>(email: string, password: string): Observable<HttpResponse<User>>{

        const data = {
            email: email,
            password: password
        };

        let headers = new HttpHeaders({
            'Content-Type':  'application/json',
            'Accept-Language': 'it'
        })

        return this.restService.post<User>(this.baseUrl, data, null, headers)
            .pipe(
                catchError(error => {
                    this.notificationService.error(error.error.error.message);
                    return throwError(error);
                })
            );
    }

One concern relates to the conversion of JSON data returned from the server into my User object. Should this conversion take place within the service or should it be handled by the component utilizing the loginService? Additionally, is it appropriate to perform the conversion using Object.assign(new User(), serverResponse.body)?

Answer №1

One effective way to apply the same logic to all your requests is by utilizing Http Interceptors in Angular.

A helpful example of this can be found in Damien Bod's angular-auth-oidc-client library.

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
    private oidcSecurityService: OidcSecurityService;

    constructor(private injector: Injector) {}

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        let requestToForward = req;

        if (this.oidcSecurityService === undefined) {
            this.oidcSecurityService = this.injector.get(OidcSecurityService);
        }
        if (this.oidcSecurityService !== undefined) {
            let token = this.oidcSecurityService.getToken();
            if (token !== '') {
                let tokenValue = 'Bearer ' + token;
                requestToForward = req.clone({ setHeaders: { Authorization: tokenValue } });
            }
        } else {
            console.debug('OidcSecurityService undefined: NO auth header!');
        }

        return next.handle(requestToForward);
    }
}

Reference:https://github.com/damienbod/angular-auth-oidc-client

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is the environment file in Angular adequately protected from potential breaches?

Currently utilizing Angular 15, I have included confidential information such as passwords and secret keys for encryption in the environment file. My concern is not about the security of the environment file in the repository (such as git or etc), but rath ...

Is there a way for me to generate an Nx command that can dynamically create a library with a specified name?

In the world of Nx and Angular, I have a repository named org housing all my projects. To create a special library within this setup, like one called auth, I typically use a command that looks like this: npx nx g @nx/angular:lib auth-data-access --directo ...

Does anyone know of a custom typeguard that enforces the presence of elements in an array?

I need help creating a custom type guard to determine if an array contains nullable or optional elements. I have defined a helper type called RequiredArray: type RequiredArray<A extends readonly any[]> = A extends [infer P, ...infer R] ? [Non ...

Utilizing Hapi js as a proxy server for managing API requests

I am looking for guidance on setting up a proxy server using Hapi js to handle api calls. For example, if I send a request to www.example.com to retrieve data, instead of directly accessing www.example.com from my angular application, I want hapi js to a ...

Adjacent components

I have a query regarding the utilization of Angular. I aim to align the sentences side by side. These are two distinct components that I developed. I wish for recipe-list and recipes-details to function properly, with both statements displayed alongside ...

An endless cascade of dots appears as the list items are being rendered

Struggling to display intricately nested list elements, Take a look at the JSON configuration below: listItems = { "text": "root", "children": [{ "text": "Level 1", "children": [{ "text": "Level 2", "children": [{ "text": ...

Combining angular's CLI project with a groovy Gradle application

I'm in the process of merging the seed project from angular-cli with my Gradle-packaged Java application, deployed on a Tomcat server. How can I successfully combine the Angular build with the Gradle build? Additionally, where is the ideal location t ...

Challenges encountered when unit testing ngx-translate

0 I am encountering issues with unit testing while using the ngx-translate library. Despite adding a provider for TranslateService, the tests keep asking for more providers, creating an endless loop of dependencies. Specifically, I am trying to unit test ...

Include the designated return type within a fat arrow function

No matter how hard I look, I cannot figure out the correct way to combine return type annotation with fat arrow syntax. class BasicCalculator{ value:number; constructor(value:number=0){ this.value=value; } add= (operand:number)=> ...

Efficiently sending data to Service Bus from an HTTP-triggered function

How can I link the output to service bus? I've configured an out binding in my Azure function: { "queueName": "testqueue", "connection": "MyServiceBusConnection", "name": "myQueueItem", "type": "serviceBus", "direction": "out" } I started ...

When inputting data from an Angular 6 form into Mongoose, the stored date appears to be offset by

I am currently working with Angular 6 to store form data, specifically a date. The form is sending the date as (date: "2018-07-02T00:00:00.000Z") and that's what gets saved into mongoose. However, when I retrieve all events to display on the page, the ...

Steps for launching Angular 5 application using Node.js server

I have developed an Angular 5 application that retrieves data from a node.js server. I successfully deployed the application to my web server hosted by FastComet, which supports node.js, but unfortunately, the server does not seem to be functioning properl ...

The ReactJS Material Table Tree mode experiences delays when new row data is introduced

My Reactjs app utilizes the material-table widget within a component: render() { return ( <div> <Row> <MaterialTable title="Mon équipement" style={{ width: "100%", margin: "0%" }} ...

Example of Signature in TypeScript Function Declaration

While going through this documentation, I found myself puzzled by the concept of having a parameter that can be both an object and a function in JavaScript. type DescribableFunction = { description: string; (a: any): boolean; }; function doSomething( ...

Switching from MOCK API to real API in Angular: The step-by-step guide

I am a beginner in Angular and I am currently working on connecting a sample app to my API gateway called ContactApp. Right now, it is functioning with a mock API but I want to switch to using a real API server. I followed all the steps from a tutorial on ...

Typescript not flagging an error for an object being declared without a type

I am encountering an issue with my tsconfig.json file: { "compilerOptions": { "allowJs": true, "allowSyntheticDefaultImports": true, "baseUrl": "src", "isolatedModules": true, "jsx": "preserve", "esModuleInterop": true, "forc ...

Angular parent component struggles to manage control over multiple child components

As a newcomer to Angular, I have a question regarding my Page1 setup. Page1 has two menu options at the top: when the first option is clicked, Page1.html is displayed, and clicking the second menu displays another component (Page2) in the context area. I w ...

Is it possible to execute an npm command within a docker container?

I am facing an issue while attempting to run my Angular application in development mode within a Docker container. When I use docker-compose build, everything works fine, but when I try to start the container, I encounter the following error: ERROR: for ...

Exploring the Magic of Class Variable Destructuring in React

Is there a simpler method to break down a prop object and assign them to variables of the same name in the class? I am familiar with ({ first: this.first, second: this.second, } = props) however, it can get complicated when dealing with numerous variable ...

How can TypeScript allow an argument to only accept keys that match another argument?

I'm currently developing a library that deals with linked lists. The current implementation is hardcoded to work with a list node type containing a "next" field that points to the next node of the same type. However, I am looking to make it more flexi ...