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.
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
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, ...)
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);
}
}
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.
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);
}
}
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
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
import {LocationStrategy} from 'angular2/router';
constructor(private locationStrategy:LocationStrategy) {
console.log(locationStrategy.prepareExternalUrl('xxx'));
}
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);
}
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/