简体   繁体   中英

Generic POST, GET in typescript - headers, response type optional

im writing simple application in angular and have created some services, which are calling api.

Before changes in every service i had methods like this:

 let addHeaders = new HttpHeaders();
 addHeaders = addHeaders.append('Authorization', apiKey);
 const endpoint = this.BuildAddress(this.MessagesEndp);
 return this.httpClient.post<Array<MessageDto>>(endpoint, dto, {headers: addHeaders});

but coding with DRY rule i want to create some common methods for my all services which are deriving from my 'restApiSetvice'.

So i have started writing like this:

 Get<T>(endpoint: string, authorization: boolean = true): Observable<T> {
    const apiKey = this.GetApiKey();
    if (authorization) {
      const addHeaders = new HttpHeaders().set('Authorization', apiKey);
      return this.client.get<T>(endpoint, {headers: addHeaders}).pipe(map(result => {
        return result;
      }));
    } else {
      return this.client.get<T>(endpoint).pipe(map(result => {
        return result;
      }));
    }
  }

so i can simplify my code in all services to this:

GetFriendshipRequests(id: number) {
    const endpoint = this.BuildAddress(this.GetFriendshipisRequestsEnd, id);
    return this.Get<Array<number>>(endpoint);
  }

but there are some problems some of calls doesn't need to authorize, so in example i have some if statement

 if (authorization) {

but some of services needs to also send this:

 responseType: 'text' as 'json'

on request

and also some of them need to send this:

observe: 'response'});

(actually this is smalles problem coz i can always observe all requests)

but how can i write method parametyers to retrieve observe, options, response type, etc?

how to do it smoothly

please dont forget that i actually learning typescript and angular, so please write answer as simple as you can:)

what i want:

I just don't want to put multiple if statesment in my common restapiQuery class

Sounds like an opt-in/out kind of issue. In your case, in most situations you want to set the authorization header, and in some exceptional ones you want to opt-out of this step.

So I would suggest you to move the authorization header login into an interceptor , which would handle this logic. Furthermore, instead of wrapping the HTTP logic in your own custom methods in order to handle the opt-out logic, you could simply move this into an utility method as follows:

// authorization-utils.ts
const OPT_OUT_AUTH_HEADER = "X-Opt-Out-Auth";

export function addNoAuthRequired(headers?: HttpHeaders): HttpHeaders{
  headers = headers || new HttpHeaders;
  return headers.set(OPT_OUT_AUTH_HEADER, 'true')
}

export function noAuthRequired(req: HttpRequest<any>): boolean {
  return req.headers.has(OPT_OUT_AUTH_HEADER);
}

// authorization-interceptor.ts
import { noAuthRequired } from './authorization-utils';

@Injectable()
export class AuthorizationInterceptor implementes HttpInterceptor {
  ctor(private readonly authService: AuthorizationService){}
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>{
    return of(req).pipe(
      map(request => noAuthRequired(request)
         ? request
         : request.clone({setHeaders: this.AuthHeaders})
      ),
      mergeMap(request => next.handle(request))
    );
  }

  private get AuthHeaders(){
    return {Authorization: this.authService.GetApiKey()}
  }
}

Once you register this interceptor in your appplication, the authorization header will be added to all requests that dont opt-out from this step.

To opt-out from it, you will need to do the following:

import { addNoAuthRequired } from './authorization-utils';

foo(url:string): Observable<Foo>{
   const headers = addNoAuthRequired();
   return this.http.get<Foo>(url,{headers});
}

This will keep the duplicated code to the minimum without limiting the flexibility of your HTTP operations.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM