Angular 2 делает за вас много отличной работы. Но он не делает всего, что вы могли бы ожидать. Чего он не делает, так это не устанавливает много заголовков HTTP-запросов.
Теперь это имеет смысл, поскольку Angular не знает, что вы делаете с запросом, поэтому вам действительно нужно это сделать. Но большинство запросов Http, сделанных с помощью службы Http, будут для сериализованных данных JSON. Однако запрос по умолчанию не добавляет заголовков, чтобы сервер знал об этом. В результате разные браузеры будут выполнять очень разные запросы.
Это пример запроса Http, сделанного Chrome:
GET http://localhost:4200/movies.json HTTP/1.1Host: localhost:4200Connection: keep-aliveUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36Accept: */* Referer: http://localhost:4200/ Accept-Encoding: gzip, deflate, sdch, brAccept-Language: en-US,en;q=0.8,nl;q=0.6 If-None-Match: W/"3a4c7-1590757b458" If-Modified-Since: Fri, 16 Dec 2016 11:15:05 GMT
И это тот же запрос, сделанный с FireFox:
GET http://localhost:4200/movies.json HTTP/1.1Host: localhost:4200User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-US,en;q=0.5Accept-Encoding: gzip, deflate Referer: http://localhost:4200/ Connection: keep-aliveIf-Modified-Since: Fri, 16 Dec 2016 11:15:05 GMT If-None-Match: W/"3a4c7-1590757b458" Cache-Control: max-age=0
Заметили разницу между двумя запросами? И особенно заголовок Accept, где Chrome утверждает, что принимает что-либо, а FireFox указывает предпочтение HTML или XML.
Добавление заголовков HTTP
Установить заголовки HTTP для запроса несложно. При вызове функции Http.get() вы можете указать заголовки, и все в порядке.
@Injectable() export class MoviesService { constructor(private http: Http) { } getMovies(): Observable<Movie[]> { var options = new RequestOptions({ headers: new Headers({ 'Accept': 'application/json' }) }); return this.http .get('/movies.json', options) .map(resp => resp.json()); } }
Однако делать это в каждой службе, которая выполняет HTTP-запрос, довольно утомительно и легко забыть, поэтому должен быть более простой способ.
BaseRequestOptions и внедрение зависимостей спешат на помощь
Как это бывает, Angular использует тип BaseRequestOptions по умолчанию для всех параметров. Так что, если мы можем просто изменить это значение по умолчанию, мы готовы к работе. И это именно то, что позволит нам сделать внедрение зависимостей.
Сначала нам нужно определить наш собственный класс параметров запроса по умолчанию с любыми настройками, которые вы хотели бы. В этом случае я просто добавляю два заголовка.
@Injectable() export class DefaultRequestOptions extends BaseRequestOptions { headers = new Headers({ 'Accept': 'application/json', 'X-Requested-By':'Angular 2', }); }
Затем мы настраиваем провайдера DI для использования класса out вместо класса по умолчанию.
@NgModule({ // Other settings providers: [ MoviesService, { provide: RequestOptions, useClass: DefaultRequestOptions } ], }) export class AppModule { }
И мы готовы работать с каждым Http-запросом, используя наши два заголовка по умолчанию. Вот пример из Chrome.
GET http://localhost:4200/movies.json HTTP/1.1Host: localhost:4200Connection: keep-aliveCache-Control: max-age=0Accept: application/jsonX-Requested-By: Angular 2User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36 Referer: http://localhost:4200/ Accept-Encoding: gzip, deflate, sdch, brAccept-Language: en-US,en;q=0.8,nl;q=0.6 If-None-Match: W/"3a4c7-1590757b458" If-Modified-Since: Fri, 16 Dec 2016 11:15:05 GMT
Добавление динамических заголовков Http
Эти заголовки великолепны, но есть одно ограничение. Эти заголовки всегда одинаковы. А с некоторыми заголовками, например аутентификацией, вы можете захотеть контролировать фактические значения во время запроса. Оказывается, он тоже не очень сложный. Каждый запрос объединяет параметры и, следовательно, заголовки из текущего запроса с параметрами запроса по умолчанию, используя функцию слияния. Поскольку мы можем переопределить это, мы можем добавить любой динамический заголовок, который захотим.
@Injectable() export class DefaultRequestOptions extends BaseRequestOptions { headers = new Headers({ 'Accept': 'application/json', 'X-Requested-By':'Angular 2', }); merge(options?: RequestOptionsArgs): RequestOptions { var newOptions = super.merge(options); newOptions.headers.set('X-Requested-At', new Date().toISOString()); return newOptions; } }
Сладкий :-)
Первоначально опубликовано на сайте blogs.msmvps.com 16 декабря 2016 г.