Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set base url for angular 2 http requests

I am trying to set base url for all my angular 2 http requests. Following is the basic set up for my application.

class HttpOptions extends BaseRequestOptions {
  url:string = "http://10.7.18.21:8080/api/";
}


bootstrap(AppComponent, [
  HTTP_PROVIDERS,
  provide(RequestOptions, {useClass: HttpOptions})
]);


export class AppComponent {
  users:Array<User>
  constructor(private http: Http) {
    http.get("/users")
      .subscribe(res => this.users = res.json());
  }
}

The request is not sent to http://10.7.18.21:8080/api/users as I expected from my configuration. Instead the request is sent to http://localhost:8000/users.

How do I set base url for http request in angular 2 application?

I am using Angular 2.0.0-beta.0.

like image 850
TheKojuEffect Avatar asked Dec 29 '15 18:12

TheKojuEffect


3 Answers

For angular 4.3+ and @angular/common/http

It's can be done with interceptors

@Injectable()
export class ExampleInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const url = 'http://myurl.com';
    req = req.clone({
      url: url + req.url
    });
    return next.handle(req);
  }
}

app.module.ts

import { NgModule } from '@angular/core';
import { Injectable } from '@angular/core';
import { HttpClientModule, HttpRequest, HTTP_INTERCEPTORS } from '@angular/common/http';

@NgModule({
  declarations: [
    AppComponent,
    ...
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    ...
  ],
  providers: [
    AppComponent,
    { provide: HTTP_INTERCEPTORS, useClass: ExampleInterceptor, multi: true }
  ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }

EDIT: HttpClient and HttpInterceptor are introduced in Angular 4.3

like image 167
vegazz Avatar answered Sep 27 '22 06:09

vegazz


UPDATE: See @vegazz answer for Angular 4.

For Angular 2.2.1, the following should prefix web api base url and represents a smaller footprint:

import {Request, XHRBackend, XHRConnection} from '@angular/http';

@Injectable()
export class ApiXHRBackend extends XHRBackend {
    createConnection(request: Request): XHRConnection {
        if (request.url.startsWith('/')){
            request.url = 'http://localhost:3000' + request.url;     // prefix base url
        }
        return super.createConnection(request);
    }
}

Inject into providers in app.module.ts:

providers: [
    { provide: XHRBackend, useClass: ApiXHRBackend }
  ]

Usage example:

this._http.post('/api/my-route', {foo: 'bar'})
            .map<MyResponse>(res => res.json())

It seems to cover all methods (GET, PUT, POST, ...)

like image 18
corolla Avatar answered Sep 27 '22 06:09

corolla


For Angular2 Version 2.2 (As for Dec 2016)

Angular from RC5 mark HTTP_PROVIDERS as deprecated and trying to move things into @NgModule, the above solution is not really applicable, so as their documentation. I cross referred several other answers and found my way to implement base url, hope this might be helpful to someone else.

The basic idea is, instead of doing things in bootstrap, we move things to AppModule.

app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpModule, RequestOptions } from '@angular/http';


import { CustomRequestOptions } from './customrequest.options';

@NgModule({
  declarations: [
    AppComponent,
    ...
  ],
  imports: [
    BrowserModule,
    HttpModule,
    ...
  ],
  providers: [
    { provide: RequestOptions, useClass: CustomRequestOptions }
  ],
  bootstrap: [ AppComponent ]
})

And move CustomRequestOptions into a separate injectable service

import { Injectable } from '@angular/core';
import { BaseRequestOptions, RequestOptions, RequestOptionsArgs } from '@angular/http';

@Injectable()
export class CustomRequestOptions extends BaseRequestOptions {
  merge(options?:RequestOptionsArgs):RequestOptions {
    options.url = 'http://localhost:9080' + options.url;
    return super.merge(options);
  }
}

Edit for request method other than GET.

If you are trying to send request type other than GET, the previous method fails to inject the baseurl into the request. This is because Angular2 generate new RequestOptions other than this._defaultOptions whose merge method isn't being override by our CustomRequestOptions. (See the source code here).

So instead of returning super.merge(...) in the last step of CustomRequestOptions merge method, I generated a new instance of CustomRequestOptions to ensure the following operation will still work.

import { Injectable } from '@angular/core';
import { RequestOptions, RequestOptionsArgs } from '@angular/http';

@Injectable()
export class CustomRequestOptions extends RequestOptions {
  merge(options?: RequestOptionsArgs): RequestOptions {
    if (options !== null && options.url !== null) {
      options.url = 'http://localhost:9080' + options.url;
    }
    let requestOptions = super.merge(options)
    return new CustomRequestOptions({
      method: requestOptions.method,
      url: requestOptions.url,
      search: requestOptions.search,
      headers: requestOptions.headers,
      body: requestOptions.body,
      withCredentials: requestOptions.withCredentials,
      responseType: requestOptions.responseType
    });
  }
}

And this works for POST, PUT, DELETE method as well. Hope this is helpful.

like image 11
yeelan Avatar answered Sep 27 '22 06:09

yeelan