How do I set the baseUrl for Angular HttpClient?

AngularAngular Httpclient

Angular Problem Overview


I did not find a way in the documentation to set the base API URL for HTTP requests. Is it possible to do this with the Angular HttpClient?

Angular Solutions


Solution 1 - Angular

Use the new HttpClient Interceptor.

Create a proper injectable that implements HttpInterceptor:

import {Injectable} from '@angular/core';
import {HttpEvent, HttpInterceptor, HttpHandler, HttpRequest} from '@angular/common/http';
import {Observable} from 'rxjs/Observable';

@Injectable()
export class APIInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    const apiReq = req.clone({ url: `your-api-url/${req.url}` });
    return next.handle(apiReq);
  }
}

The HttpInterceptor can clone the request and change it as you wish, in this case I defined a default path for all of the http requests.

Provide the HttpClientModule with the following configurations:

providers: [{
      provide: HTTP_INTERCEPTORS,
      useClass: APIInterceptor,
      multi: true,
    }
  ]

Now all your requests will start with your-api-url/

Solution 2 - Angular

Based on TheUnreal's very useful answer, the interceptor can be written to get the base url through DI:

@Injectable()
export class BaseUrlInterceptor implements HttpInterceptor {

    constructor(
        @Inject('BASE_API_URL') private baseUrl: string) {
    }

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

        const apiReq = request.clone({ url: `${this.baseUrl}/${request.url}` });
        return next.handle(apiReq);
    }
}


BASE_API_URL can be provided by the application module:

providers: [
    { provide: "BASE_API_URL", useValue: environment.apiUrl }
]

where environment is the object automatically created by the CLI when generating the project:

export const environment = {
  production: false,
  apiUrl: "..."
}; 

Solution 3 - Angular

Everybody who followed Alexei answer and couldn't make it work like me - it's because you also have to add to providers array this element

{
  provide: HTTP_INTERCEPTORS,
  useClass: BaseUrlInterceptor,
  multi: true
}

Unfortunately I have too low reputation to add a comment to his answer.

Solution 4 - Angular

Why not create an HttpClient subclass that has a configurable baseUrl? That way if your application needs to communicate with multiple services you can either use a different subclass for each, or create multiple instances of a single subclass each with a different configuration.

@Injectable()
export class ApiHttpClient extends HttpClient {
  public baseUrl: string;

  public constructor(handler: HttpHandler) {
    super(handler);

    // Get base url from wherever you like, or provision ApiHttpClient in your AppComponent or some other high level
    // component and set the baseUrl there.
    this.baseUrl = '/api/';
  }

  public get(url: string, options?: Object): Observable<any> {
    url = this.baseUrl + url;
    return super.get(url, options);
  }
}

Solution 5 - Angular

Excerpts from Visual studio 2017 asp.net core webapi angular sample application.

include below lines in Main.ts

export function getBaseUrl() {
  return document.getElementsByTagName('base')[0].href;
}

const providers = [
  { provide: 'BASE_URL', useFactory: getBaseUrl, deps: [] }
];

in your component

  constructor(http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
    http.get<WeatherForecast[]>(baseUrl + 'api/SampleData/WeatherForecasts').subscribe(result => {
      this.forecasts = result;
    }, error => console.error(error));
  }

my complete main.ts code looks like below

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

export function getBaseUrl() {
  return document.getElementsByTagName('base')[0].href;
}

const providers = [
  { provide: 'BASE_URL', useFactory: getBaseUrl, deps: [] }
];

if (environment.production) {
  enableProdMode();
}

platformBrowserDynamic()
  .bootstrapModule(AppModule)
  .catch(err => console.error(err));

my component code looks like below

import { Component, Inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'fetch-weather',
  templateUrl: './weather.component.html',
  styleUrls: ['./weather.component.scss']
})

export class WeatherComponent {
  public forecasts: WeatherForecast[];

  constructor(http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
    http.get<WeatherForecast[]>(baseUrl + 'api/SampleData/WeatherForecasts').subscribe(result => {
      this.forecasts = result;
    }, error => console.error(error));
  }
}

interface WeatherForecast {
  dateFormatted: string;
  temperatureC: number;
  temperatureF: number;
  summary: string;
}

Solution 6 - Angular

you don't necessarily need a base URL with HttpClient, the docs says you just have to specify the api part of the request, if you are making calls to the same server it is straightforward like this:

this.http.get('/api/items').subscribe(data => {...

However, you can if you need or want to, specify a base URL.

I have 2 suggestions for doing that:

1. A helper class with a static class property.

export class HttpClientHelper {

    static baseURL: string = 'http://localhost:8080/myApp';
}


this.http.get(`${HttpClientHelper.baseURL}/api/items`); //in your service class

2. A base class with a class property so any new service should extend it:

export class BackendBaseService {

  baseURL: string = 'http://localhost:8080/myApp';

  constructor(){}
}

@Injectable()
export class ItemsService extends BackendBaseService {

  constructor(private http: HttpClient){  
    super();
  }
      
  public listAll(): Observable<any>{    
    return this.http.get(`${this.baseURL}/api/items`);
  }

}

Solution 7 - Angular

I think there is no default way to do this. Do the HttpService and inside you can define property of your default URL, and make methods to call http.get and others with your property URL. Then inject HttpService instead of HttpClient

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionStepan SuvorovView Question on Stackoverflow
Solution 1 - AngularTheUnrealView Answer on Stackoverflow
Solution 2 - AngularAlexei - check CodidactView Answer on Stackoverflow
Solution 3 - AngularHakejView Answer on Stackoverflow
Solution 4 - AngularNeutrinoView Answer on Stackoverflow
Solution 5 - AngularMoorthi DanielView Answer on Stackoverflow
Solution 6 - Angularskinny_jonesView Answer on Stackoverflow
Solution 7 - AngularAnton LeeView Answer on Stackoverflow