Skip to content

Commit 2c4f372

Browse files
committed
fixup! feat(platform-server): use absolute URLs from Location for HTTP
1 parent fb6293f commit 2c4f372

2 files changed

Lines changed: 58 additions & 18 deletions

File tree

packages/platform-server/src/http.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ import {DOCUMENT} from '@angular/common';
1414
import {HttpEvent, HttpRequest, HttpHandler, HttpBackend, XhrFactory, ɵHttpInterceptingHandler as HttpInterceptingHandler} from '@angular/common/http';
1515
import {Observable, Observer, Subscription} from 'rxjs';
1616

17+
// @see https://www.w3.org/Protocols/HTTP/1.1/draft-ietf-http-v11-spec-01#URI-syntax
1718
const isAbsoluteUrl = /^[a-zA-Z\-\+.]+:\/\//;
19+
const FORWARD_SLASH = '/';
1820

1921
@Injectable()
2022
export class ServerXhr implements XhrFactory {
@@ -108,8 +110,15 @@ export class ZoneClientBackend extends
108110
}
109111

110112
handle(request: HttpRequest<any>): Observable<HttpEvent<any>> {
111-
if (!isAbsoluteUrl.test(request.url) && this.doc.location.href) {
112-
return this.wrap(request.clone({url: this.doc.location.href + request.url}));
113+
const href = this.doc.location.href;
114+
if (!isAbsoluteUrl.test(request.url) && href) {
115+
const urlParts = Array.from(request.url);
116+
if (request.url[0] === FORWARD_SLASH && href[href.length - 1] === FORWARD_SLASH) {
117+
urlParts.shift();
118+
} else if (request.url[0] !== FORWARD_SLASH && href[href.length - 1] !== FORWARD_SLASH) {
119+
urlParts.splice(0, 0, FORWARD_SLASH);
120+
}
121+
return this.wrap(request.clone({url: href + urlParts.join('')}));
113122
}
114123
return this.wrap(request);
115124
}

packages/platform-server/test/integration_spec.ts

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -793,22 +793,53 @@ describe('platform-server integration', () => {
793793
});
794794
}));
795795

796-
it('can make relative HttpClient requests', async(() => {
797-
const platform = platformDynamicServer([
798-
{provide: INITIAL_CONFIG, useValue: {document: '<app></app>', url: 'http://localhost'}}
799-
]);
800-
platform.bootstrapModule(HttpClientExampleModule).then(ref => {
801-
const mock = ref.injector.get(HttpTestingController) as HttpTestingController;
802-
const http = ref.injector.get(HttpClient);
803-
ref.injector.get<NgZone>(NgZone).run(() => {
804-
http.get<string>('/testing').subscribe((body: string) => {
805-
NgZone.assertInAngularZone();
806-
expect(body).toEqual('success!');
807-
});
808-
mock.expectOne('http://localhost/testing').flush('success!');
809-
});
810-
});
811-
}));
796+
it('can make relative HttpClient requests', async () => {
797+
const platform = platformDynamicServer([
798+
{provide: INITIAL_CONFIG, useValue: {document: '<app></app>', url: 'http://localhost'}}
799+
]);
800+
const ref = await platform.bootstrapModule(HttpClientExampleModule);
801+
const mock = ref.injector.get(HttpTestingController) as HttpTestingController;
802+
const http = ref.injector.get(HttpClient);
803+
ref.injector.get(NgZone).run(() => {
804+
http.get<string>('/testing').subscribe((body: string) => {
805+
NgZone.assertInAngularZone();
806+
expect(body).toEqual('success!');
807+
});
808+
mock.expectOne('http://localhost/testing').flush('success!');
809+
});
810+
});
811+
812+
it('can make relative HttpClient requests two slashes', async () => {
813+
const platform = platformDynamicServer([
814+
{provide: INITIAL_CONFIG, useValue: {document: '<app></app>', url: 'http://localhost/'}}
815+
]);
816+
const ref = await platform.bootstrapModule(HttpClientExampleModule);
817+
const mock = ref.injector.get(HttpTestingController) as HttpTestingController;
818+
const http = ref.injector.get(HttpClient);
819+
ref.injector.get(NgZone).run(() => {
820+
http.get<string>('/testing').subscribe((body: string) => {
821+
NgZone.assertInAngularZone();
822+
expect(body).toEqual('success!');
823+
});
824+
mock.expectOne('http://localhost/testing').flush('success!');
825+
});
826+
});
827+
828+
it('can make relative HttpClient requests no slashes', async () => {
829+
const platform = platformDynamicServer([
830+
{provide: INITIAL_CONFIG, useValue: {document: '<app></app>', url: 'http://localhost'}}
831+
]);
832+
const ref = await platform.bootstrapModule(HttpClientExampleModule);
833+
const mock = ref.injector.get(HttpTestingController) as HttpTestingController;
834+
const http = ref.injector.get(HttpClient);
835+
ref.injector.get(NgZone).run(() => {
836+
http.get<string>('testing').subscribe((body: string) => {
837+
NgZone.assertInAngularZone();
838+
expect(body).toEqual('success!');
839+
});
840+
mock.expectOne('http://localhost/testing').flush('success!');
841+
});
842+
});
812843

813844
it('requests are macrotasks', async(() => {
814845
const platform = platformDynamicServer(

0 commit comments

Comments
 (0)