forked from DSpace/dspace-angular
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
114624: Refactored legacyBitstreamURL resolver into a guard to set th…
…e redirect status code to 301 Moved Permanently
- Loading branch information
1 parent
404ccd9
commit 369bd69
Showing
6 changed files
with
239 additions
and
200 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
153 changes: 153 additions & 0 deletions
153
src/app/bitstream-page/legacy-bitstream-url-redirect.guard.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
import { EMPTY } from 'rxjs'; | ||
import { BitstreamDataService } from '../core/data/bitstream-data.service'; | ||
import { RemoteData } from '../core/data/remote-data'; | ||
import { RequestEntryState } from '../core/data/request-entry-state.model'; | ||
import { legacyBitstreamURLRedirectGuard } from './legacy-bitstream-url-redirect.guard'; | ||
import { RouterStub } from '../shared/testing/router.stub'; | ||
import { ServerResponseServiceStub } from '../shared/testing/server-response-service.stub'; | ||
import { fakeAsync } from '@angular/core/testing'; | ||
import { cold } from 'jasmine-marbles'; | ||
import { PAGE_NOT_FOUND_PATH } from '../app-routing-paths'; | ||
import { Bitstream } from '../core/shared/bitstream.model'; | ||
|
||
describe('legacyBitstreamURLRedirectGuard', () => { | ||
let resolver: any; | ||
let bitstreamDataService: BitstreamDataService; | ||
let remoteDataMocks: { [type: string]: RemoteData<any> }; | ||
let route; | ||
let state; | ||
let serverResponseService: ServerResponseServiceStub; | ||
let router: RouterStub; | ||
|
||
beforeEach(() => { | ||
route = { | ||
params: {}, | ||
queryParams: {} | ||
}; | ||
router = new RouterStub(); | ||
serverResponseService = new ServerResponseServiceStub(); | ||
state = {}; | ||
remoteDataMocks = { | ||
RequestPending: new RemoteData(undefined, 0, 0, RequestEntryState.RequestPending, undefined, undefined, undefined), | ||
ResponsePending: new RemoteData(undefined, 0, 0, RequestEntryState.ResponsePending, undefined, undefined, undefined), | ||
Success: new RemoteData(0, 0, 0, RequestEntryState.Success, undefined, new Bitstream(), 200), | ||
NoContent: new RemoteData(0, 0, 0, RequestEntryState.Success, undefined, undefined, 204), | ||
Error: new RemoteData(0, 0, 0, RequestEntryState.Error, 'Internal server error', undefined, 500), | ||
}; | ||
bitstreamDataService = { | ||
findByItemHandle: () => undefined | ||
} as any; | ||
resolver = legacyBitstreamURLRedirectGuard; | ||
}); | ||
|
||
describe(`resolve`, () => { | ||
describe(`For JSPUI-style URLs`, () => { | ||
beforeEach(() => { | ||
spyOn(bitstreamDataService, 'findByItemHandle').and.returnValue(EMPTY); | ||
route = Object.assign({}, route, { | ||
params: { | ||
prefix: '123456789', | ||
suffix: '1234', | ||
filename: 'some-file.pdf', | ||
sequence_id: '5' | ||
} | ||
}); | ||
}); | ||
it(`should call findByItemHandle with the handle, sequence id, and filename from the route`, () => { | ||
resolver(route, state, bitstreamDataService, serverResponseService, router); | ||
expect(bitstreamDataService.findByItemHandle).toHaveBeenCalledWith( | ||
`${route.params.prefix}/${route.params.suffix}`, | ||
route.params.sequence_id, | ||
route.params.filename | ||
); | ||
}); | ||
}); | ||
|
||
describe(`For XMLUI-style URLs`, () => { | ||
describe(`when there is a sequenceId query parameter`, () => { | ||
beforeEach(() => { | ||
spyOn(bitstreamDataService, 'findByItemHandle').and.returnValue(EMPTY); | ||
route = Object.assign({}, route, { | ||
params: { | ||
prefix: '123456789', | ||
suffix: '1234', | ||
filename: 'some-file.pdf', | ||
}, | ||
queryParams: { | ||
sequenceId: '5' | ||
} | ||
}); | ||
}); | ||
it(`should call findByItemHandle with the handle and filename from the route, and the sequence ID from the queryParams`, () => { | ||
resolver(route, state, bitstreamDataService, serverResponseService, router); | ||
expect(bitstreamDataService.findByItemHandle).toHaveBeenCalledWith( | ||
`${route.params.prefix}/${route.params.suffix}`, | ||
route.queryParams.sequenceId, | ||
route.params.filename | ||
); | ||
}); | ||
}); | ||
describe(`when there's no sequenceId query parameter`, () => { | ||
beforeEach(() => { | ||
spyOn(bitstreamDataService, 'findByItemHandle').and.returnValue(EMPTY); | ||
route = Object.assign({}, route, { | ||
params: { | ||
prefix: '123456789', | ||
suffix: '1234', | ||
filename: 'some-file.pdf', | ||
}, | ||
}); | ||
}); | ||
it(`should call findByItemHandle with the handle, and filename from the route`, () => { | ||
resolver(route, state, bitstreamDataService, serverResponseService, router); | ||
expect(bitstreamDataService.findByItemHandle).toHaveBeenCalledWith( | ||
`${route.params.prefix}/${route.params.suffix}`, | ||
undefined, | ||
route.params.filename | ||
); | ||
}); | ||
}); | ||
}); | ||
describe('should return and complete after the RemoteData has...', () => { | ||
it('...failed', fakeAsync(() => { | ||
spyOn(router, 'createUrlTree').and.callThrough(); | ||
spyOn(bitstreamDataService, 'findByItemHandle').and.returnValue(cold('a-b-c', { | ||
a: remoteDataMocks.RequestPending, | ||
b: remoteDataMocks.ResponsePending, | ||
c: remoteDataMocks.Error, | ||
})); | ||
resolver(route, state, bitstreamDataService, serverResponseService, router).subscribe(() => { | ||
expect(bitstreamDataService.findByItemHandle).toHaveBeenCalled(); | ||
expect(router.createUrlTree).toHaveBeenCalledWith([PAGE_NOT_FOUND_PATH]); | ||
}); | ||
})); | ||
|
||
it('...succeeded without content', fakeAsync(() => { | ||
spyOn(router, 'createUrlTree').and.callThrough(); | ||
spyOn(bitstreamDataService, 'findByItemHandle').and.returnValue(cold('a-b-c', { | ||
a: remoteDataMocks.RequestPending, | ||
b: remoteDataMocks.ResponsePending, | ||
c: remoteDataMocks.NoContent, | ||
})); | ||
resolver(route, state, bitstreamDataService, serverResponseService, router).subscribe(() => { | ||
expect(bitstreamDataService.findByItemHandle).toHaveBeenCalled(); | ||
expect(router.createUrlTree).toHaveBeenCalledWith([PAGE_NOT_FOUND_PATH]); | ||
}); | ||
})); | ||
|
||
it('...succeeded', fakeAsync(() => { | ||
spyOn(serverResponseService, 'setStatus').and.callThrough(); | ||
spyOn(bitstreamDataService, 'findByItemHandle').and.returnValue(cold('a-b-c', { | ||
a: remoteDataMocks.RequestPending, | ||
b: remoteDataMocks.ResponsePending, | ||
c: remoteDataMocks.Success, | ||
})); | ||
resolver(route, state, bitstreamDataService, serverResponseService, router).subscribe(() => { | ||
expect(bitstreamDataService.findByItemHandle).toHaveBeenCalled(); | ||
expect(serverResponseService.setStatus).toHaveBeenCalledWith(301); | ||
expect(router.parseUrl).toHaveBeenCalled(); | ||
}); | ||
})); | ||
}); | ||
}); | ||
}); |
53 changes: 53 additions & 0 deletions
53
src/app/bitstream-page/legacy-bitstream-url-redirect.guard.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import { inject } from '@angular/core'; | ||
import { ActivatedRouteSnapshot, CanActivateFn, UrlTree, Router, RouterStateSnapshot } from '@angular/router'; | ||
import { Observable } from 'rxjs'; | ||
import { RemoteData } from '../core/data/remote-data'; | ||
import { Bitstream } from '../core/shared/bitstream.model'; | ||
import { hasNoValue } from '../shared/empty.util'; | ||
import { BitstreamDataService } from '../core/data/bitstream-data.service'; | ||
import { ServerResponseService } from '../core/services/server-response.service'; | ||
import { map, tap } from 'rxjs/operators'; | ||
import { PAGE_NOT_FOUND_PATH } from '../app-routing-paths'; | ||
import { getFirstCompletedRemoteData } from '../core/shared/operators'; | ||
|
||
/** | ||
* Redirects to a bitstream based on the handle of the item, and the sequence id or the filename of the | ||
* bitstream. In production mode the status code will also be set the status code to 301 marking it as a permanent URL | ||
* redirect for bots. | ||
* | ||
* @returns Observable<UrlTree> Returns a URL to redirect the user to the new URL format | ||
*/ | ||
export const legacyBitstreamURLRedirectGuard: CanActivateFn = ( | ||
route: ActivatedRouteSnapshot, | ||
state: RouterStateSnapshot, | ||
bitstreamDataService: BitstreamDataService = inject(BitstreamDataService), | ||
serverResponseService: ServerResponseService = inject(ServerResponseService), | ||
router: Router = inject(Router), | ||
): Observable<UrlTree> => { | ||
const prefix = route.params.prefix; | ||
const suffix = route.params.suffix; | ||
const filename = route.params.filename; | ||
let sequenceId = route.params.sequence_id; | ||
if (hasNoValue(sequenceId)) { | ||
sequenceId = route.queryParams.sequenceId; | ||
} | ||
return bitstreamDataService.findByItemHandle( | ||
`${prefix}/${suffix}`, | ||
sequenceId, | ||
filename, | ||
).pipe( | ||
getFirstCompletedRemoteData(), | ||
tap((rd: RemoteData<Bitstream>) => { | ||
if (rd.hasSucceeded && !rd.hasNoContent) { | ||
serverResponseService.setStatus(301); | ||
} | ||
}), | ||
map((rd: RemoteData<Bitstream>) => { | ||
if (rd.hasSucceeded && !rd.hasNoContent) { | ||
return router.parseUrl(`/bitstreams/${rd.payload.uuid}/download`); | ||
} else { | ||
return router.createUrlTree([PAGE_NOT_FOUND_PATH]); | ||
} | ||
}) | ||
); | ||
}; |
145 changes: 0 additions & 145 deletions
145
src/app/bitstream-page/legacy-bitstream-url.resolver.spec.ts
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.