diff --git a/src/app/core/url-serializer/bitstream-url-serializer.spec.ts b/src/app/core/url-serializer/bitstream-url-serializer.spec.ts index a66e47b3cd5..a8d5a903f2f 100644 --- a/src/app/core/url-serializer/bitstream-url-serializer.spec.ts +++ b/src/app/core/url-serializer/bitstream-url-serializer.spec.ts @@ -5,6 +5,10 @@ import { DefaultUrlSerializer, UrlTree } from '@angular/router'; describe('BitstreamUrlSerializer', () => { let serializer: BitstreamUrlSerializer; + function pathSegments(tree: UrlTree): string[] { + return tree.root.children.primary.segments.map((segment) => segment.path); + } + beforeEach(() => { TestBed.configureTestingModule({ providers: [BitstreamUrlSerializer] @@ -51,4 +55,18 @@ describe('BitstreamUrlSerializer', () => { const resultUrl = new DefaultUrlSerializer().serialize(result); expect(resultUrl).toBe(expectedUrl); }); + + it('should keep the whole query string when a query value contains a raw "?"', () => { + const result: UrlTree = serializer.parse('/bitstream/handle/123/456/file.pdf?isAllowed=y?x&sequenceId=2'); + + expect(pathSegments(result)).toEqual(['bitstream', 'handle', '123', '456', 'file.pdf']); + expect(result.queryParams).toEqual({ isAllowed: 'y?x', sequenceId: '2' }); + }); + + it('should not encode a fragment into the filename', () => { + const result: UrlTree = serializer.parse('/bitstream/handle/123/456/file.pdf#page=2'); + + expect(pathSegments(result)).toEqual(['bitstream', 'handle', '123', '456', 'file.pdf']); + expect(result.fragment).toBe('page=2'); + }); }); diff --git a/src/app/core/url-serializer/bitstream-url-serializer.ts b/src/app/core/url-serializer/bitstream-url-serializer.ts index 7872732e46a..24b6dfcb171 100644 --- a/src/app/core/url-serializer/bitstream-url-serializer.ts +++ b/src/app/core/url-serializer/bitstream-url-serializer.ts @@ -12,8 +12,10 @@ export class BitstreamUrlSerializer extends DefaultUrlSerializer { // Intercept parsing of every URL parse(url: string): UrlTree { if (url.startsWith('/bitstream/')) { - // Separate the path from the query string - const [path, query] = url.split('?'); + // Separate the path from the query string and fragment (everything from the first raw '?' or '#') + const queryIndex = url.search(/[?#]/); + const path = queryIndex === -1 ? url : url.substring(0, queryIndex); + const queryAndFragment = queryIndex === -1 ? '' : url.substring(queryIndex); // Split the path to isolate the filename const parts = path.split('/'); @@ -24,8 +26,8 @@ export class BitstreamUrlSerializer extends DefaultUrlSerializer { // Reconstruct the path with the encoded filename const newPath = [...parts.slice(0, this.FILENAME_INDEX), encodedFilename].join('/'); - // Reattach query string if present - url = query ? `${newPath}?${query}` : newPath; + // Reattach the query string and fragment unchanged + url = newPath + queryAndFragment; } } return super.parse(url);