Подтвердить что ты не робот

Задайте базовый 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.

4b9b3361

Ответ 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

Ответ 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);
}