From 673bf4725cee88d268bca513a70a42c9e2bc5d18 Mon Sep 17 00:00:00 2001 From: Tomas Dostal <5617576+DostalTomas@users.noreply.github.com> Date: Wed, 23 Jan 2019 00:58:28 +0100 Subject: [PATCH] fix(ajax): Fix case-insensitive headers in HTTP request (#4453) In RFC 7230 and RFC 7540 is written, that HTTP headers is case-insensitive, so this is fix for correct serializing request body base on HTTP headers. --- spec/observables/dom/ajax-spec.ts | 20 +++++++++++++++++++ src/internal/observable/dom/AjaxObservable.ts | 17 +++++++++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/spec/observables/dom/ajax-spec.ts b/spec/observables/dom/ajax-spec.ts index 510795ac81..17fc8c049f 100644 --- a/spec/observables/dom/ajax-spec.ts +++ b/spec/observables/dom/ajax-spec.ts @@ -600,6 +600,26 @@ describe('ajax', () => { expect(MockXMLHttpRequest.mostRecent.data).to.equal('{"🌟":"🚀"}'); }); + it('should send json body not mattered on case-sensitivity of HTTP headers', () => { + const body = { + hello: 'world' + }; + + const requestObj = { + url: '/flibbertyJibbet', + method: '', + body: body, + headers: { + 'cOnTeNt-TyPe': 'application/json; charset=UTF-8' + } + }; + + ajax(requestObj).subscribe(); + + expect(MockXMLHttpRequest.mostRecent.url).to.equal('/flibbertyJibbet'); + expect(MockXMLHttpRequest.mostRecent.data).to.equal('{"hello":"world"}'); + }); + it('should error if send request throws', (done: MochaDone) => { const expected = new Error('xhr send failure'); diff --git a/src/internal/observable/dom/AjaxObservable.ts b/src/internal/observable/dom/AjaxObservable.ts index e258e6ddc7..1d645cef76 100644 --- a/src/internal/observable/dom/AjaxObservable.ts +++ b/src/internal/observable/dom/AjaxObservable.ts @@ -202,17 +202,18 @@ export class AjaxSubscriber extends Subscriber { const headers = request.headers = request.headers || {}; // force CORS if requested - if (!request.crossDomain && !headers['X-Requested-With']) { + if (!request.crossDomain && !this.getHeader(headers, 'X-Requested-With')) { headers['X-Requested-With'] = 'XMLHttpRequest'; } // ensure content type is set - if (!('Content-Type' in headers) && !(root.FormData && request.body instanceof root.FormData) && typeof request.body !== 'undefined') { + let contentTypeHeader = this.getHeader(headers, 'Content-Type'); + if (!contentTypeHeader && !(root.FormData && request.body instanceof root.FormData) && typeof request.body !== 'undefined') { headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'; } // properly serialize body - request.body = this.serializeBody(request.body, request.headers['Content-Type']); + request.body = this.serializeBody(request.body, this.getHeader(request.headers, 'Content-Type')); this.send(); } @@ -315,6 +316,16 @@ export class AjaxSubscriber extends Subscriber { } } + private getHeader(headers: {}, headerName: string): any { + for (let key in headers) { + if (key.toLowerCase() === headerName.toLowerCase()) { + return headers[key]; + } + } + + return undefined; + } + private setupEvents(xhr: XMLHttpRequest, request: AjaxRequest) { const progressSubscriber = request.progressSubscriber;