Задайте базовый url для angular 2 http-запросов
Я пытаюсь установить базовый url для всех моих angular 2 http-запросов. Ниже приведена базовая настройка для моего приложения.
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());
}
}
Запрос не отправляется http://10.7.18.21:8080/api/users, как я ожидал от своей конфигурации. Вместо этого запрос отправляется http://localhost:8000/users.
Как установить базовый url для HTTP-запроса в приложении angular 2?
Я использую Angular 2.0.0-beta.0.
Ответы
Ответ 1
ОБНОВЛЕНИЕ: см. ответ @vegazz для Angular 4.
Для Angular 2.2.1 следующее должно содержать префикс web api base url и представляет меньший размер:
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);
}
}
Ввод в провайдеры в app.module.ts:
providers: [
{ provide: XHRBackend, useClass: ApiXHRBackend }
]
Пример использования:
this._http.post('/api/my-route', {foo: 'bar'})
.map<MyResponse>(res => res.json())
Кажется, что он охватывает все методы (GET, PUT, POST,...)
Ответ 2
Для angular 4.3+ и @angular/common/http
Это просто с перехватчиками
@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 и HttpInterceptor представлены в angular 4.3
Ответ 3
Для Angular2 Версия 2.2 (по состоянию на декабрь 2016 года)
Angular от метки RC5 HTTP_PROVIDERS
как устаревшего и пытающегося переместить вещи в @NgModule
, вышеупомянутое решение на самом деле не применимо, так как их документация. Я перекрестился с несколькими другими ответами и нашел способ реализовать базовый url, надеюсь, что это может быть полезно кому-то другому.
Основная идея заключается в том, что вместо того, чтобы делать что-то в бутстрапе, мы перемещаем вещи на 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 ]
})
И переместите CustomRequestOptions в отдельную инъекционную службу
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);
}
}
Изменить метод запроса, кроме GET.
Если вы пытаетесь отправить тип запроса, отличный от GET, предыдущий метод не может ввести baseurl в запрос. Это связано с тем, что Angular2 генерирует новый RequestOptions
, отличный от this._defaultOptions
, метод слияния которого не переопределяется нашими CustomRequestOptions. (Смотрите здесь исходный код).
Поэтому вместо возврата super.merge(...)
на последнем этапе метода слияния CustomRequestOptions я сгенерировал новый экземпляр CustomRequestOptions
, чтобы гарантировать, что следующая операция все равно будет работать.
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
});
}
}
И это работает также для метода POST, PUT, DELETE. Надеюсь, что это будет полезно.
Ответ 4
В Angular 2.0.0-beta.6 Вы можете добиться этого, переопределив 'merge'
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);
}
}
Ответ 5
После просмотра источников кода для BaseRequestOptions
, RequestOptions
и Http
классов:
Похоже, что свойство url
соответствует URL-адресу по умолчанию, но не является префиксом для URL-адресов.
Чтобы реализовать ваш прецедент, я бы предложил поставить службу перед объектом http и затем ввести службу. Что-то вроде этого:
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);
}
}
и
import {HttpClient} from './http-client';
export classMyComponent {
constructor(httpClient: HttpClient) {
this.httpClient = httpClient;
}
handleSomething() {
this.httpClient.post(url, data)
).subscribe(...);
}
}
Тем не менее, возможно, это может быть связано с самим Angular2; -)
Надеюсь, это поможет вам,
Thierry
Ответ 6
import {LocationStrategy} from 'angular2/router';
constructor(private locationStrategy:LocationStrategy) {
console.log(locationStrategy.prepareExternalUrl('xxx'));
}
См. также https://github.com/angular/angular/blob/1bec4f6c6135d7aaccec7492d70c36e1ceeaeefa/modules/angular2/test/router/path_location_strategy_spec.ts#L88
Ответ 7
Разный подход: во время разработки вашего приложения в локальном хосте подумайте о настройке прокси-сервера.
proxy.conf.json
{
"/api/**": {
"target": "http://10.7.18.21:8080/",
"secure": false,
"logLevel": "debug"
}
}
Подробнее: ссылка
Ответ 8
Для текущего пользователя здесь действительно работает пример в angular 2.4.8
здесь - это код для того, чтобы скомпилировать и привязать BaseCommonRequestOptions и 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);
}