-
Notifications
You must be signed in to change notification settings - Fork 447
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3062 from atmire/legacy-bitstream-redirect_contri…
…bute-main Made legacy bitstream URLs redirect with 301 status code
- Loading branch information
Showing
6 changed files
with
248 additions
and
201 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
158 changes: 158 additions & 0 deletions
158
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,158 @@ | ||
import { cold } from 'jasmine-marbles'; | ||
import { EMPTY } from 'rxjs'; | ||
|
||
import { PAGE_NOT_FOUND_PATH } from '../app-routing-paths'; | ||
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 { BrowserHardRedirectService } from '../core/services/browser-hard-redirect.service'; | ||
import { HardRedirectService } from '../core/services/hard-redirect.service'; | ||
import { Bitstream } from '../core/shared/bitstream.model'; | ||
import { RouterStub } from '../shared/testing/router.stub'; | ||
import { legacyBitstreamURLRedirectGuard } from './legacy-bitstream-url-redirect.guard'; | ||
|
||
describe('legacyBitstreamURLRedirectGuard', () => { | ||
let resolver: any; | ||
let bitstreamDataService: BitstreamDataService; | ||
let remoteDataMocks: { [type: string]: RemoteData<Bitstream> }; | ||
let route; | ||
let state; | ||
let hardRedirectService: HardRedirectService; | ||
let router: RouterStub; | ||
|
||
let bitstream: Bitstream; | ||
|
||
beforeEach(() => { | ||
route = { | ||
params: {}, | ||
queryParams: {}, | ||
}; | ||
router = new RouterStub(); | ||
hardRedirectService = new BrowserHardRedirectService(window.location); | ||
state = {}; | ||
bitstream = Object.assign(new Bitstream(), { | ||
uuid: 'bitstream-id', | ||
}); | ||
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, 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, hardRedirectService, 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, hardRedirectService, 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, hardRedirectService, 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', () => { | ||
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, hardRedirectService, router).subscribe(() => { | ||
expect(bitstreamDataService.findByItemHandle).toHaveBeenCalled(); | ||
expect(router.createUrlTree).toHaveBeenCalledWith([PAGE_NOT_FOUND_PATH]); | ||
}); | ||
}); | ||
|
||
it('...succeeded without content', () => { | ||
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, hardRedirectService, router).subscribe(() => { | ||
expect(bitstreamDataService.findByItemHandle).toHaveBeenCalled(); | ||
expect(router.createUrlTree).toHaveBeenCalledWith([PAGE_NOT_FOUND_PATH]); | ||
}); | ||
}); | ||
|
||
it('...succeeded', () => { | ||
spyOn(hardRedirectService, 'redirect'); | ||
spyOn(bitstreamDataService, 'findByItemHandle').and.returnValue(cold('a-b-c', { | ||
a: remoteDataMocks.RequestPending, | ||
b: remoteDataMocks.ResponsePending, | ||
c: remoteDataMocks.Success, | ||
})); | ||
resolver(route, state, bitstreamDataService, hardRedirectService, router).subscribe(() => { | ||
expect(bitstreamDataService.findByItemHandle).toHaveBeenCalled(); | ||
expect(hardRedirectService.redirect).toHaveBeenCalledWith(new URL(`/bitstreams/${bitstream.uuid}/download`, window.location.origin).href, 301); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); |
57 changes: 57 additions & 0 deletions
57
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,57 @@ | ||
import { inject } from '@angular/core'; | ||
import { | ||
ActivatedRouteSnapshot, | ||
CanActivateFn, | ||
Router, | ||
RouterStateSnapshot, | ||
UrlTree, | ||
} from '@angular/router'; | ||
import { Observable } from 'rxjs'; | ||
import { map } from 'rxjs/operators'; | ||
|
||
import { PAGE_NOT_FOUND_PATH } from '../app-routing-paths'; | ||
import { BitstreamDataService } from '../core/data/bitstream-data.service'; | ||
import { RemoteData } from '../core/data/remote-data'; | ||
import { HardRedirectService } from '../core/services/hard-redirect.service'; | ||
import { Bitstream } from '../core/shared/bitstream.model'; | ||
import { getFirstCompletedRemoteData } from '../core/shared/operators'; | ||
import { hasNoValue } from '../shared/empty.util'; | ||
|
||
/** | ||
* 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 to the regular bitstream download Page. | ||
* | ||
* @returns Either a {@link UrlTree} to the 404 page when the url isn't a valid format or false in order to make the | ||
* user wait until the {@link HardRedirectService#redirect} was performed | ||
*/ | ||
export const legacyBitstreamURLRedirectGuard: CanActivateFn = ( | ||
route: ActivatedRouteSnapshot, | ||
state: RouterStateSnapshot, | ||
bitstreamDataService: BitstreamDataService = inject(BitstreamDataService), | ||
serverHardRedirectService: HardRedirectService = inject(HardRedirectService), | ||
router: Router = inject(Router), | ||
): Observable<UrlTree | false> => { | ||
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(), | ||
map((rd: RemoteData<Bitstream>) => { | ||
if (rd.hasSucceeded && !rd.hasNoContent) { | ||
serverHardRedirectService.redirect(new URL(`/bitstreams/${rd.payload.uuid}/download`, serverHardRedirectService.getCurrentOrigin()).href, 301); | ||
return false; | ||
} else { | ||
return router.createUrlTree([PAGE_NOT_FOUND_PATH]); | ||
} | ||
}), | ||
); | ||
}; |
146 changes: 0 additions & 146 deletions
146
src/app/bitstream-page/legacy-bitstream-url.resolver.spec.ts
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.