Skip to content

Commit b469c3c

Browse files
committed
Ensure we are no longer using/trusting "Host" HTTP Header. Require setting existing environment.ui.baseUrl. Replace ServerHardRedirectService.getCurrentOrigin() with getBaseUrl() to read this setting.
1 parent 8723aa9 commit b469c3c

14 files changed

+89
-37
lines changed

config/config.example.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ ui:
88
ssl: false
99
host: localhost
1010
port: 4000
11+
# Specify the public URL that this user interface responds to. This corresponds to the "dspace.ui.url" property in your backend's local.cfg.
12+
# The baseUrl is used for redirects and SEO links (in robots.txt).
13+
baseUrl: http://localhost:4000
1114
# NOTE: Space is capitalized because 'namespace' is a reserved string in TypeScript
1215
nameSpace: /
1316
# The rateLimiter settings limit each IP to a 'max' of 500 requests per 'windowMs' (1 minute).

server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ export function app() {
167167
server.get('/robots.txt', (req, res) => {
168168
res.setHeader('content-type', 'text/plain');
169169
res.render('assets/robots.txt.ejs', {
170-
'origin': req.protocol + '://' + req.headers.host
170+
'origin': environment.ui.baseUrl,
171171
});
172172
});
173173

src/app/bitstream-page/legacy-bitstream-url-redirect.guard.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { cold } from 'jasmine-marbles';
22
import { EMPTY } from 'rxjs';
33

4+
import { environment } from '../../environments/environment';
45
import { PAGE_NOT_FOUND_PATH } from '../app-routing-paths';
56
import { BitstreamDataService } from '../core/data/bitstream-data.service';
67
import { RemoteData } from '../core/data/remote-data';
@@ -150,7 +151,7 @@ describe('legacyBitstreamURLRedirectGuard', () => {
150151
}));
151152
resolver(route, state, bitstreamDataService, hardRedirectService, router).subscribe(() => {
152153
expect(bitstreamDataService.findByItemHandle).toHaveBeenCalled();
153-
expect(hardRedirectService.redirect).toHaveBeenCalledWith(new URL(`/bitstreams/${bitstream.uuid}/download`, window.location.origin).href, 301);
154+
expect(hardRedirectService.redirect).toHaveBeenCalledWith(new URL(`/bitstreams/${bitstream.uuid}/download`, environment.ui.baseUrl).href, 301);
154155
});
155156
});
156157
});

src/app/bitstream-page/legacy-bitstream-url-redirect.guard.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ import {
99
import { Observable } from 'rxjs';
1010
import { map } from 'rxjs/operators';
1111

12-
import { PAGE_NOT_FOUND_PATH } from '../app-routing-paths';
12+
import {
13+
getBitstreamDownloadRoute,
14+
PAGE_NOT_FOUND_PATH,
15+
} from '../app-routing-paths';
1316
import { BitstreamDataService } from '../core/data/bitstream-data.service';
1417
import { RemoteData } from '../core/data/remote-data';
1518
import { HardRedirectService } from '../core/services/hard-redirect.service';
@@ -46,7 +49,7 @@ export const legacyBitstreamURLRedirectGuard: CanActivateFn = (
4649
getFirstCompletedRemoteData(),
4750
map((rd: RemoteData<Bitstream>) => {
4851
if (rd.hasSucceeded && !rd.hasNoContent) {
49-
serverHardRedirectService.redirect(new URL(`/bitstreams/${rd.payload.uuid}/download`, serverHardRedirectService.getCurrentOrigin()).href, 301);
52+
serverHardRedirectService.redirect(new URL(getBitstreamDownloadRoute(rd.payload), serverHardRedirectService.getBaseUrl()).href, 301);
5053
return false;
5154
} else {
5255
return router.createUrlTree([PAGE_NOT_FOUND_PATH]);

src/app/core/metadata/metadata.service.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ describe('MetadataService', () => {
8484
}
8585
} as any as Router;
8686
hardRedirectService = jasmine.createSpyObj( {
87-
getCurrentOrigin: 'https://request.org',
87+
getBaseUrl: 'https://request.org',
8888
});
8989
authorizationService = jasmine.createSpyObj('authorizationService', {
9090
isAuthorized: observableOf(true)

src/app/core/metadata/metadata.service.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ export class MetadataService {
299299
if (this.currentObject.value instanceof Item) {
300300
let url = this.getMetaTagValue('dc.identifier.uri');
301301
if (hasNoValue(url)) {
302-
url = new URLCombiner(this.hardRedirectService.getCurrentOrigin(), this.router.url).toString();
302+
url = new URLCombiner(this.hardRedirectService.getBaseUrl(), this.router.url).toString();
303303
}
304304
this.addMetaTag('citation_abstract_html_url', url);
305305
}
@@ -382,7 +382,7 @@ export class MetadataService {
382382
// Use the found link to set the <meta> tag
383383
this.addMetaTag(
384384
'citation_pdf_url',
385-
new URLCombiner(this.hardRedirectService.getCurrentOrigin(), link).toString()
385+
new URLCombiner(this.hardRedirectService.getBaseUrl(), link).toString()
386386
);
387387
});
388388
}

src/app/core/services/browser-hard-redirect.service.spec.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import { TestBed } from '@angular/core/testing';
2+
3+
import { environment } from '../../../environments/environment';
24
import { BrowserHardRedirectService } from './browser-hard-redirect.service';
35

46
describe('BrowserHardRedirectService', () => {
57
let origin: string;
68
let mockLocation: Location;
79
let service: BrowserHardRedirectService;
10+
let originalBaseUrl;
811

912
beforeEach(() => {
1013
origin = 'https://test-host.com:4000';
@@ -19,11 +22,22 @@ describe('BrowserHardRedirectService', () => {
1922
} as Location;
2023
spyOn(mockLocation, 'replace');
2124

25+
// Store original environment variable to restore after tests
26+
originalBaseUrl = environment.ui.baseUrl;
27+
28+
// Set environment variable to match our mock location origin for testing
29+
environment.ui.baseUrl = origin;
30+
2231
service = new BrowserHardRedirectService(mockLocation);
2332

2433
TestBed.configureTestingModule({});
2534
});
2635

36+
afterEach(() => {
37+
// Restore original environment variable after tests
38+
environment.ui.baseUrl = originalBaseUrl;
39+
});
40+
2741
it('should be created', () => {
2842
expect(service).toBeTruthy();
2943
});
@@ -51,7 +65,7 @@ describe('BrowserHardRedirectService', () => {
5165
describe('when requesting the origin', () => {
5266

5367
it('should return the location origin', () => {
54-
expect(service.getCurrentOrigin()).toEqual(origin);
68+
expect(service.getBaseUrl()).toEqual(origin);
5569
});
5670
});
5771

src/app/core/services/browser-hard-redirect.service.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Inject, Injectable, InjectionToken } from '@angular/core';
2+
import { environment } from '../../../environments/environment';
23
import { HardRedirectService } from './hard-redirect.service';
34

45
export const LocationToken = new InjectionToken('Location');
@@ -36,12 +37,11 @@ export class BrowserHardRedirectService extends HardRedirectService {
3637
}
3738

3839
/**
39-
* Get the origin of the current URL
40+
* Get the base public URL of our application.
41+
* This is used as the base URL for redirects, and should be in the format of
4042
* i.e. <scheme> "://" <hostname> [ ":" <port> ]
41-
* e.g. if the URL is https://demo.dspace.org/search?query=test,
42-
* the origin would be https://demo.dspace.org
4343
*/
44-
getCurrentOrigin(): string {
45-
return this.location.origin;
44+
getBaseUrl(): string {
45+
return environment.ui.baseUrl;
4646
}
4747
}

src/app/core/services/browser.referrer.service.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ describe(`BrowserReferrerService`, () => {
1515
service = new BrowserReferrerService(
1616
{ referrer: documentReferrer },
1717
routeService,
18-
{ getCurrentOrigin: () => origin } as any
18+
{ getBaseUrl: () => origin } as any,
1919
);
2020
});
2121

src/app/core/services/browser.referrer.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export class BrowserReferrerService extends ReferrerService {
4646
const reversedHistory = [...history].reverse();
4747
// and find the first URL that differs from the current one
4848
const prevUrl = reversedHistory.find((url: string) => url !== currentURL);
49-
return new URLCombiner(this.hardRedirectService.getCurrentOrigin(), prevUrl).toString();
49+
return new URLCombiner(this.hardRedirectService.getBaseUrl(), prevUrl).toString();
5050
}
5151
})
5252
);

0 commit comments

Comments
 (0)