Angular 6 个 Http 客户端自定义 url 和 header

Angular 6 Http client custom url and header

我在 Angular 6 应用程序中工作,我想知道在向服务器发送请求时自定义 url 时最佳做法应该是什么。

场景如下: - 在我的 Angular 项目中,我有 environment.ts 和 environment.prod.ts,我在其中添加了一个 "host",其中包含 http 服务器的 url:port(带有控制器的项目) . - 我正在创建要注入到我的组件中的服务,这些服务将负责向服务器发送请求(GET 和 POST)以检索数据或发送更新。 - 我想使用 environment.ts 中的 "host" 作为请求 url 的一部分。所以我所有的请求都将以 "host" 作为基础 url 然后我可以连接到所需的路径。

我已经检查了一些解决方案并且我已经实施了其中一个,但我不确定这是正确的做法。我会在下面写下我到目前为止实现的内容,然后我会写一些想法,请帮助我了解什么是最好的解决方案(我是 angular 的新手)

目前实施:

-> 在我的功能服务中,例如 LoginService,我注入了 angular HttpClient。然后我简单地调用:

return this.httpService.post("/login/", creds).pipe(
      map((data: any) => {
        this.manager = data;
        return this.manager;
      }));

我创建了一个拦截器来更改 url:InterceptService implements HttpInterceptor 我在其中创建了一个新的 HttpRequest 实例并自定义了 request.url使用 environment.host。我还需要拦截器添加一个 Header 用于身份验证(仍未完全实现)

const httpRequest = new HttpRequest(<any>request.method, environment.host + request.url, request.body);
    request = Object.assign(request, httpRequest);

    const headers = new HttpHeaders({
      'Authorization': 'Bearer token 123',
      'Content-Type': 'application/json'
    });

问题:

1) This works, all my requests are changed in the interceptor as I wanted, but it doesn't look like the best practice in my first look. I don't like to create a new HeepRequest to be able to do this (i did it to keep it immutable, I guess that's the correct way). Do you think this looks good?

2) What about the Authentication being added to the Header in the interceptor? Is it ok? Most of the references I checked did this

其他解决方案:

1) 我看到了一些示例,其中 HttpClientService 扩展了 Http,并且 get 和 post 等每个方法在调用超级方法之前编辑了 url 和 headers。但我相信这不是 Angular 6 并且可能不是更可取的

2) 我还可以创建一个通过注入接收 angular HttpClient (angular 6 HttpClientModule) 实例的服务,并且我可以实现像 get 或 post 这样的方法。

好吧,因为我没有得到任何答案,所以我将添加我的解决方案。根据我的研究,我相信这是最好的解决方案。

I used an interceptor for adding information to the header such as the token bearer authentication.

import { Injectable } from '@angular/core';
import {
  HttpEvent,
  HttpInterceptor,
  HttpHandler,
  HttpRequest,
  HttpResponse,
  HttpHeaders,
  HttpErrorResponse
} from '@angular/common/http'
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import { environment } from "../../../environments/environment";
import { Router } from "@angular/router";

export class HttpClientInterceptor implements HttpInterceptor {

  constructor(private router: Router) { }

  // intercept request to add information to the headers such as the token
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    //I decided to remove this logic from the interceptor to add the host url on the HttpClientService I created
    //const httpRequest = new HttpRequest(<any>request.method, environment.host + request.url, request.body);
    //request = Object.assign(request, httpRequest);

    var token = localStorage.getItem("bearerToken");

    if (token) {
      const newReq = request.clone(
        {
          headers: request.headers.set('Authorization',
            'Bearer ' + token)
        });

      return next.handle(newReq).pipe(
        tap(event => {
          if (event instanceof HttpResponse) {
            console.log("Interceptor - HttpResponse = " + event.status); // http response status code
          }
        }, error => {
          // http response status code
          if (error instanceof HttpErrorResponse) {
            console.log("----response----");
            console.error("status code:");
            console.error(error.status);
            console.error(error.message);
            console.log("--- end of response---");

            if (error.status === 401 || error.status === 403) //check if the token expired and redirect to login
              this.router.navigate(['login']);
          }
        })
      )
    }
    else {
      return next.handle(request);
    }
  };

For changing the url, I created a service on file http-client.service.ts and got the host url from environment.ts

import { Injectable } from "@angular/core";
import { HttpClient } from '@angular/common/http';
import { Observable } from "rxjs";
import { environment } from "../../../environments/environment";

@Injectable({ providedIn:'root' })
export class HttpClientService {
  constructor(private http: HttpClient) { }

  get(url: string, options?: any): Observable<ArrayBuffer> {
    url = this.updateUrl(url);
    return this.http.get(url, options);
  }

  post(url: string, body: string, options?: any): Observable<ArrayBuffer> {
    url = this.updateUrl(url);
    return this.http.post(url, body, options);
  }

  put(url: string, body: string, options?: any): Observable<ArrayBuffer> {
    url = this.updateUrl(url);
    return this.http.put(url, body, options);
  }

  delete(url: string, options?: any): Observable<ArrayBuffer> {
    url = this.updateUrl(url);
    return this.http.delete(url,options);
  }

  private updateUrl(req: string) {
    return environment.host + req;
  }
}

正如我所说,我相信这是最好的方法,但请随时向我的 question/answer 添加信息。