web-dev-qa-db-fra.com

Définir l'URL de base pour les requêtes angulaires 2 http

J'essaie de définir l'URL de base pour toutes mes requêtes angulaires 2 http. Voici la configuration de base pour mon 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());
  }
}

La demande n'est pas envoyée à http://10.7.18.21:8080/api/users comme je m'y attendais de ma configuration. Au lieu de cela, la demande est envoyée à http: // localhost: 8000/users .

Comment définir l'URL de base de la requête http dans l'application angulaire 2?

J'utilise Angular 2.0.0-beta.0.

41
TheKojuEffect

Pour les versions angulaires 4.3+ et @ angular/common/http

C'est simple avec les intercepteurs

@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 et HttpInterceptor sont introduits dans Angular 4.3

42
vegazz

UPDATE: Voir la réponse @vegazz pour Angular 4.

Pour Angular 2.2.1, les éléments suivants doivent précéder l’URL de base de l’API web et représentent une empreinte au sol réduite:

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);
    }
}

Injecter dans les fournisseurs dans app.module.ts:

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

Exemple d'utilisation:

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

Il semble couvrir toutes les méthodes (GET, PUT, POST, ...)

17
corolla

Pour Angular2 Version 2.2 (Comme pour décembre 2016)

Angular de RC5 marque HTTP_PROVIDERS comme obsolète et tente de déplacer des éléments dans @NgModule, la solution ci-dessus n’est pas vraiment applicable, de même que leur documentation. Je croisai plusieurs autres réponses et trouvai mon moyen d'implémenter l'URL de base, en espérant que cela pourrait être utile à quelqu'un d'autre.

L'idée de base est qu'au lieu de faire les choses en bootstrap, on déplace les choses en 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 ]
})

Et déplacez CustomRequestOptions dans un service injectable séparé

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);
  }
}

Modifiez la méthode de requête autre que GET.

Si vous essayez d'envoyer un type de requête autre que GET, la méthode précédente ne parvient pas à injecter le baseurl dans la requête. En effet, Angular2 génère une nouvelle variable RequestOptions autre que this._defaultOptions dont la méthode de fusion n'est pas remplacée par nos options CustomRequestOptions. (Voir le code source ici).

Ainsi, au lieu de renvoyer super.merge(...) à la dernière étape de la méthode de fusion CustomRequestOptions, j'ai généré une nouvelle instance de CustomRequestOptions afin de m'assurer que l'opération suivante fonctionnera toujours.

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
    });
  }
}

Et cela fonctionne aussi pour les méthodes POST, PUT, DELETE. J'espère que c'est utile.

11
yeelan

In Angular 2.0.0-beta.6 Vous pouvez y parvenir en remplaçant le paramètre "fusion"

import {BaseRequestOptions, RequestOptions, RequestOptionsArgs} from 'angular2/http';

export class ApRequestOptions extends BaseRequestOptions {

  merge(options?:RequestOptionsArgs):RequestOptions {
    options.url = 'http://10.7.18.21:8080/api' + options.url;
    return super.merge(options);
  }

}
6
Adrian Sobiczewski

Après avoir examiné les sources de code pour les classes BaseRequestOptions, RequestOptions et Http:

Il semble que la propriété url correspond à l'URL par défaut mais pas à un préfixe pour les URL.

Pour implémenter votre cas d'utilisation, je suggérerais de placer un service devant l'objet http et d'injecter ensuite le service. Quelque chose comme ca:

import {Injectable} from '@angular/core';
import {Http} from '@angular/http';

@Injectable()
export class HttpClient {
  http: Http;
  urlPrefix: string;

  constructor(http: Http) {
    this.http = http;
    this.urlPrefix = 'http://...';
  }

  get(url) {
    return this.http.get(this.urlPrefix + url);
  }

  post(url, data) {
    return this.http.post(this.urlPrefix + url, data);
  }
}

Et

import {HttpClient} from './http-client';

export classMyComponent {
  constructor(httpClient: HttpClient) {
    this.httpClient = httpClient;
  }

  handleSomething() {
    this.httpClient.post(url, data)
    ).subscribe(...);
  }
}

Cela dit, une telle contribution pourrait peut-être être apportée à Angular2 lui-même ;-)

J'espère que ça vous aide, Thierry

5
Thierry Templier

Approche différente: lors du développement de votre application dans localhost, envisagez plutôt de configurer un proxy

proxy.conf.json

{
   "/api/**": {
      "target": "http://10.7.18.21:8080/",
      "secure": false,
      "logLevel": "debug"
   }
}

Plus: link

3
istibekesi
import {LocationStrategy} from 'angular2/router';

constructor(private locationStrategy:LocationStrategy) {
  console.log(locationStrategy.prepareExternalUrl('xxx'));
}

Voir aussi https://github.com/angular/angular/blob/1bec4f6c6135d7aaccec7492d70c36e1eeaeefa/modules/angular2/test/router/path_location_strategy_spec.ts#L88

1
Günter Zöchbauer

Pour les utilisateurs actuels, voici un exemple réellement fonctionnel dans angulaire 2.4.8

here est le code qui explique pourquoi divisé et chaîné BaseCommonRequestOptions et CommonRequestOptions 

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

@Injectable()
export class BaseCommonRequestOptions extends BaseRequestOptions {

  merge(options?: RequestOptionsArgs): RequestOptions {
    return new CommonRequestOptions(super.merge(extracted(options)));
  }
}

/**
 * for inner merge when using post put patch delete...others method
 */
export class CommonRequestOptions extends RequestOptions {
  merge(options?: RequestOptionsArgs): RequestOptions {
    return new RequestOptions(super.merge(extracted(options)));
  }
}

/**
 * inject default values
 *
 * @param options
 * @returns {RequestOptionsArgs}
 */
export function extracted(options: RequestOptionsArgs) {
  console.log(options);
  if (!validUrl(options.url)) {
    options.url = 'http://localhost:3000' + (options.url ? options.url : "");
  }
  // use default header application/json, if content-type header was empty.
  if (options.headers != null) {
    let contentType = options.headers.get('content-type');
    if (contentType == null || contentType == '') {
      options.headers.append('content-type', 'application/json');
    }
  } else {
    options.headers = new Headers({ 'content-type': 'application/json' });
  }

  return options;
}

/**
 * validate url
 *
 * @param url
 * @returns {boolean}
 */
export function validUrl(url: string) {
  return /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/.test(url);
}

0
Jinseoung Lee

créer un fichier .ts

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


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

}

Puis dans app.module.ts

import { ApiXHRBackend } from './guard/httpintercepter';
import {Request, XHRBackend, XHRConnection} from '@angular/http';

Ajouter un fournisseur dans la section des fournisseurs

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

alors dans votre appel http service.ts doit être comme ci-dessous exemple

return this._http.post("/api/customerservice/loginvalidation",data)
.map((response: Response) => {
return response;
});

Ici/api sera remplacé par votre URL de base http: // localhost: 8080

plus de détails http://shabeen.fr/webschool/how-to-set-angular-2-service-http-base-url/

0
codelover