Skip to content

Commit 23644e9

Browse files
114624: Made the legacyBitstreamURLRedirectGuard return false for valid bitstream urls in combination with a HardRedirectService#redirect, this will make ensure the redirect is visible for curl instead of being performed by Angular
1 parent 369bd69 commit 23644e9

3 files changed

Lines changed: 47 additions & 39 deletions

File tree

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

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,42 @@
1+
import { cold } from 'jasmine-marbles';
12
import { EMPTY } from 'rxjs';
3+
4+
import { PAGE_NOT_FOUND_PATH } from '../app-routing-paths';
25
import { BitstreamDataService } from '../core/data/bitstream-data.service';
36
import { RemoteData } from '../core/data/remote-data';
47
import { RequestEntryState } from '../core/data/request-entry-state.model';
5-
import { legacyBitstreamURLRedirectGuard } from './legacy-bitstream-url-redirect.guard';
6-
import { RouterStub } from '../shared/testing/router.stub';
7-
import { ServerResponseServiceStub } from '../shared/testing/server-response-service.stub';
8-
import { fakeAsync } from '@angular/core/testing';
9-
import { cold } from 'jasmine-marbles';
10-
import { PAGE_NOT_FOUND_PATH } from '../app-routing-paths';
8+
import { BrowserHardRedirectService } from '../core/services/browser-hard-redirect.service';
9+
import { HardRedirectService } from '../core/services/hard-redirect.service';
1110
import { Bitstream } from '../core/shared/bitstream.model';
11+
import { RouterStub } from '../shared/testing/router.stub';
12+
import { legacyBitstreamURLRedirectGuard } from './legacy-bitstream-url-redirect.guard';
1213

1314
describe('legacyBitstreamURLRedirectGuard', () => {
1415
let resolver: any;
1516
let bitstreamDataService: BitstreamDataService;
1617
let remoteDataMocks: { [type: string]: RemoteData<any> };
1718
let route;
1819
let state;
19-
let serverResponseService: ServerResponseServiceStub;
20+
let hardRedirectService: HardRedirectService;
2021
let router: RouterStub;
2122

23+
let bitstream: Bitstream;
24+
2225
beforeEach(() => {
2326
route = {
2427
params: {},
2528
queryParams: {}
2629
};
2730
router = new RouterStub();
28-
serverResponseService = new ServerResponseServiceStub();
31+
hardRedirectService = new BrowserHardRedirectService(window.location);
2932
state = {};
33+
bitstream = Object.assign(new Bitstream(), {
34+
uuid: 'bitstream-id',
35+
});
3036
remoteDataMocks = {
3137
RequestPending: new RemoteData(undefined, 0, 0, RequestEntryState.RequestPending, undefined, undefined, undefined),
3238
ResponsePending: new RemoteData(undefined, 0, 0, RequestEntryState.ResponsePending, undefined, undefined, undefined),
33-
Success: new RemoteData(0, 0, 0, RequestEntryState.Success, undefined, new Bitstream(), 200),
39+
Success: new RemoteData(0, 0, 0, RequestEntryState.Success, undefined, bitstream, 200),
3440
NoContent: new RemoteData(0, 0, 0, RequestEntryState.Success, undefined, undefined, 204),
3541
Error: new RemoteData(0, 0, 0, RequestEntryState.Error, 'Internal server error', undefined, 500),
3642
};
@@ -54,7 +60,7 @@ describe('legacyBitstreamURLRedirectGuard', () => {
5460
});
5561
});
5662
it(`should call findByItemHandle with the handle, sequence id, and filename from the route`, () => {
57-
resolver(route, state, bitstreamDataService, serverResponseService, router);
63+
resolver(route, state, bitstreamDataService, hardRedirectService, router);
5864
expect(bitstreamDataService.findByItemHandle).toHaveBeenCalledWith(
5965
`${route.params.prefix}/${route.params.suffix}`,
6066
route.params.sequence_id,
@@ -79,7 +85,7 @@ describe('legacyBitstreamURLRedirectGuard', () => {
7985
});
8086
});
8187
it(`should call findByItemHandle with the handle and filename from the route, and the sequence ID from the queryParams`, () => {
82-
resolver(route, state, bitstreamDataService, serverResponseService, router);
88+
resolver(route, state, bitstreamDataService, hardRedirectService, router);
8389
expect(bitstreamDataService.findByItemHandle).toHaveBeenCalledWith(
8490
`${route.params.prefix}/${route.params.suffix}`,
8591
route.queryParams.sequenceId,
@@ -99,7 +105,7 @@ describe('legacyBitstreamURLRedirectGuard', () => {
99105
});
100106
});
101107
it(`should call findByItemHandle with the handle, and filename from the route`, () => {
102-
resolver(route, state, bitstreamDataService, serverResponseService, router);
108+
resolver(route, state, bitstreamDataService, hardRedirectService, router);
103109
expect(bitstreamDataService.findByItemHandle).toHaveBeenCalledWith(
104110
`${route.params.prefix}/${route.params.suffix}`,
105111
undefined,
@@ -109,45 +115,44 @@ describe('legacyBitstreamURLRedirectGuard', () => {
109115
});
110116
});
111117
describe('should return and complete after the RemoteData has...', () => {
112-
it('...failed', fakeAsync(() => {
118+
it('...failed', () => {
113119
spyOn(router, 'createUrlTree').and.callThrough();
114120
spyOn(bitstreamDataService, 'findByItemHandle').and.returnValue(cold('a-b-c', {
115121
a: remoteDataMocks.RequestPending,
116122
b: remoteDataMocks.ResponsePending,
117123
c: remoteDataMocks.Error,
118124
}));
119-
resolver(route, state, bitstreamDataService, serverResponseService, router).subscribe(() => {
125+
resolver(route, state, bitstreamDataService, hardRedirectService, router).subscribe(() => {
120126
expect(bitstreamDataService.findByItemHandle).toHaveBeenCalled();
121127
expect(router.createUrlTree).toHaveBeenCalledWith([PAGE_NOT_FOUND_PATH]);
122128
});
123-
}));
129+
});
124130

125-
it('...succeeded without content', fakeAsync(() => {
131+
it('...succeeded without content', () => {
126132
spyOn(router, 'createUrlTree').and.callThrough();
127133
spyOn(bitstreamDataService, 'findByItemHandle').and.returnValue(cold('a-b-c', {
128134
a: remoteDataMocks.RequestPending,
129135
b: remoteDataMocks.ResponsePending,
130136
c: remoteDataMocks.NoContent,
131137
}));
132-
resolver(route, state, bitstreamDataService, serverResponseService, router).subscribe(() => {
138+
resolver(route, state, bitstreamDataService, hardRedirectService, router).subscribe(() => {
133139
expect(bitstreamDataService.findByItemHandle).toHaveBeenCalled();
134140
expect(router.createUrlTree).toHaveBeenCalledWith([PAGE_NOT_FOUND_PATH]);
135141
});
136-
}));
142+
});
137143

138-
it('...succeeded', fakeAsync(() => {
139-
spyOn(serverResponseService, 'setStatus').and.callThrough();
144+
it('...succeeded', () => {
145+
spyOn(hardRedirectService, 'redirect');
140146
spyOn(bitstreamDataService, 'findByItemHandle').and.returnValue(cold('a-b-c', {
141147
a: remoteDataMocks.RequestPending,
142148
b: remoteDataMocks.ResponsePending,
143149
c: remoteDataMocks.Success,
144150
}));
145-
resolver(route, state, bitstreamDataService, serverResponseService, router).subscribe(() => {
151+
resolver(route, state, bitstreamDataService, hardRedirectService, router).subscribe(() => {
146152
expect(bitstreamDataService.findByItemHandle).toHaveBeenCalled();
147-
expect(serverResponseService.setStatus).toHaveBeenCalledWith(301);
148-
expect(router.parseUrl).toHaveBeenCalled();
153+
expect(hardRedirectService.redirect).toHaveBeenCalledWith(new URL(`/bitstreams/${bitstream.uuid}/download`, window.location.origin).href, 301);
149154
});
150-
}));
155+
});
151156
});
152157
});
153158
});

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

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
11
import { inject } from '@angular/core';
2-
import { ActivatedRouteSnapshot, CanActivateFn, UrlTree, Router, RouterStateSnapshot } from '@angular/router';
2+
import {
3+
ActivatedRouteSnapshot,
4+
CanActivateFn,
5+
Router,
6+
RouterStateSnapshot,
7+
UrlTree,
8+
} from '@angular/router';
39
import { Observable } from 'rxjs';
10+
import { map } from 'rxjs/operators';
11+
12+
import { PAGE_NOT_FOUND_PATH } from '../app-routing-paths';
13+
import { BitstreamDataService } from '../core/data/bitstream-data.service';
414
import { RemoteData } from '../core/data/remote-data';
15+
import { HardRedirectService } from '../core/services/hard-redirect.service';
516
import { Bitstream } from '../core/shared/bitstream.model';
6-
import { hasNoValue } from '../shared/empty.util';
7-
import { BitstreamDataService } from '../core/data/bitstream-data.service';
8-
import { ServerResponseService } from '../core/services/server-response.service';
9-
import { map, tap } from 'rxjs/operators';
10-
import { PAGE_NOT_FOUND_PATH } from '../app-routing-paths';
1117
import { getFirstCompletedRemoteData } from '../core/shared/operators';
18+
import { hasNoValue } from '../shared/empty.util';
1219

1320
/**
1421
* Redirects to a bitstream based on the handle of the item, and the sequence id or the filename of the
@@ -21,9 +28,9 @@ export const legacyBitstreamURLRedirectGuard: CanActivateFn = (
2128
route: ActivatedRouteSnapshot,
2229
state: RouterStateSnapshot,
2330
bitstreamDataService: BitstreamDataService = inject(BitstreamDataService),
24-
serverResponseService: ServerResponseService = inject(ServerResponseService),
31+
serverHardRedirectService: HardRedirectService = inject(HardRedirectService),
2532
router: Router = inject(Router),
26-
): Observable<UrlTree> => {
33+
): Observable<UrlTree | boolean> => {
2734
const prefix = route.params.prefix;
2835
const suffix = route.params.suffix;
2936
const filename = route.params.filename;
@@ -37,14 +44,10 @@ export const legacyBitstreamURLRedirectGuard: CanActivateFn = (
3744
filename,
3845
).pipe(
3946
getFirstCompletedRemoteData(),
40-
tap((rd: RemoteData<Bitstream>) => {
41-
if (rd.hasSucceeded && !rd.hasNoContent) {
42-
serverResponseService.setStatus(301);
43-
}
44-
}),
4547
map((rd: RemoteData<Bitstream>) => {
4648
if (rd.hasSucceeded && !rd.hasNoContent) {
47-
return router.parseUrl(`/bitstreams/${rd.payload.uuid}/download`);
49+
serverHardRedirectService.redirect(new URL(`/bitstreams/${rd.payload.uuid}/download`, serverHardRedirectService.getCurrentOrigin()).href, 301);
50+
return false;
4851
} else {
4952
return router.createUrlTree([PAGE_NOT_FOUND_PATH]);
5053
}

src/app/core/data/bitstream-data.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ export class BitstreamDataService extends IdentifiableDataService<Bitstream> imp
171171
searchParams.push(new RequestParam('sequenceId', sequenceId));
172172
}
173173
if (hasValue(filename)) {
174-
searchParams.push(new RequestParam('filename', filename));
174+
searchParams.push(new RequestParam('filename', encodeURIComponent(filename)));
175175
}
176176

177177
const hrefObs = this.getSearchByHref(

0 commit comments

Comments
 (0)