fix(docs-infra): correctly serve index.html with a query string (#42547)
				
					
				
			Previously, due to a bug in Firebase hosting, requests to `/index.html?<query>` would lead to an infinite redirect and eventually a failure. This affected, for example, cache-busting requests from the ServiceWorker, which look like: `/index.html?ngsw-cache-bust=...` For more details see https://github.com/angular/angular/issues/42518#issuecomment-858545483 This commit temporarily works around the bug by explicitly redirecting `/index.html?<query>` to `/?<query>`. Fixes #42518 PR Close #42547
This commit is contained in:
		
							parent
							
								
									828fde6e0d
								
							
						
					
					
						commit
						56a0582d79
					
				| @ -124,6 +124,10 @@ | ||||
|       {"type": 301, "source": "/testing", "destination": "/guide/testing"}, | ||||
|       {"type": 301, "source": "/testing/**", "destination": "/guide/testing"}, | ||||
| 
 | ||||
|       // Work around Firebase hosting bug with `/index.html?<query>` leading to infinite redirects. | ||||
|       // See https://github.com/angular/angular/issues/42518#issuecomment-858545483 for details. | ||||
|       {"type": 301, "source": "/index.html:query*", "destination": "/:query*"}, | ||||
| 
 | ||||
|       // Strip off the `.html` extension, because Firebase will not do this automatically any more | ||||
|       // (unless the new URL points to an existing file, which is not necessarily the case here). | ||||
|       {"type": 301, "source": "/:somePath*/:file.html", "destination": "/:somePath*/:file"}, | ||||
|  | ||||
| @ -188,6 +188,7 @@ | ||||
| /guide/updating-to-version-10 --> https://v10.angular.io/guide/updating-to-version-10 | ||||
| /guide/updating-to-version-11 --> https://v11.angular.io/guide/updating-to-version-11 | ||||
| /guide/webpack --> https://v5.angular.io/guide/webpack | ||||
| /index.html?foo=bar --> /?foo=bar | ||||
| /news --> https://blog.angular.io/ | ||||
| /news.html --> https://blog.angular.io/ | ||||
| /start/data --> /start/start-data | ||||
|  | ||||
| @ -137,6 +137,21 @@ describe('FirebaseRedirectSource', () => { | ||||
|         }); | ||||
|       }); | ||||
| 
 | ||||
|       it('should capture a named param not preceded by a slash', () => { | ||||
|         testGlobMatch('/a/b:x', { | ||||
|           named: ['x'] | ||||
|         }, { | ||||
|           '/a/bc': {x: 'c'}, | ||||
|           '/a/bcd': {x: 'cd'}, | ||||
|           '/a/b-c': {x: '-c'}, | ||||
|           '/a': undefined, | ||||
|           '/a/': undefined, | ||||
|           '/a/b/': undefined, | ||||
|           '/a/cd': undefined, | ||||
|           '/a/b/c': undefined, | ||||
|         }); | ||||
|       }); | ||||
| 
 | ||||
|       it('should capture multiple named params', () => { | ||||
|         testGlobMatch('/a/:b/:c', { | ||||
|           named: ['b', 'c'] | ||||
| @ -187,6 +202,35 @@ describe('FirebaseRedirectSource', () => { | ||||
|         }); | ||||
|       }); | ||||
| 
 | ||||
|       it('should capture a rest param not preceded by a slash', () => { | ||||
|         testGlobMatch('/a:bc*', { | ||||
|           rest: ['bc'] | ||||
|         }, { | ||||
|           '/ab': {bc: 'b'}, | ||||
|           '/a/b': {bc: '/b'}, | ||||
|           '/a/bcd': {bc: '/bcd'}, | ||||
|           '/a/b/c': {bc: '/b/c'}, | ||||
|           '/a//': {bc: '//'}, | ||||
|           '/ab/c': {bc: 'b/c'}, | ||||
|           '/ab/c/': {bc: 'b/c/'}, | ||||
|           '/a': {bc: undefined}, | ||||
|           '/bc': undefined, | ||||
|         }); | ||||
| 
 | ||||
|         testGlobMatch('/a/b:c*', { | ||||
|           rest: ['c'] | ||||
|         }, { | ||||
|           '/a/bc': {c: 'c'}, | ||||
|           '/a/bcd': {c: 'cd'}, | ||||
|           '/a/b/': {c: '/'}, | ||||
|           '/a/b/c/': {c: '/c/'}, | ||||
|           '/a/ba/c': {c: 'a/c'}, | ||||
|           '/a/ba/c/': {c: 'a/c/'}, | ||||
|           '/a/b': {c: undefined}, | ||||
|           '/a/': undefined, | ||||
|         }); | ||||
|       }); | ||||
| 
 | ||||
|       it('should capture a rest param mixed with a named param', () => { | ||||
|         testGlobMatch('/:abc/:rest*', { | ||||
|           named: ['abc'], | ||||
|  | ||||
| @ -24,8 +24,8 @@ export class FirebaseRedirectSource { | ||||
|     const star = /\*/g; | ||||
|     const doubleStar = /(^|\/)\*\*($|\/)/g;           // e.g. a/**/b or **/b or a/** but not a**b
 | ||||
|     const modifiedPatterns = /(.)\(([^)]+)\)/g;       // e.g. `@(a|b)
 | ||||
|     const restParam = /\/:([A-Za-z]+)\*/g;            // e.g. `:rest*`
 | ||||
|     const namedParam = /\/:([A-Za-z]+)/g;             // e.g. `:api`
 | ||||
|     const restParam = /(\/?):([A-Za-z]+)\*/g;            // e.g. `:rest*`
 | ||||
|     const namedParam = /(\/?):([A-Za-z]+)/g;             // e.g. `:api`
 | ||||
|     const possiblyEmptyInitialSegments = /^\.🐷\//g;  // e.g. `**/a` can also match `a`
 | ||||
|     const possiblyEmptySegments = /\/\.🐷\//g;        // e.g. `a/**/b` can also match `a/b`
 | ||||
|     const willBeStar = /🐷/g;                         // e.g. `a**b` not matched by previous rule
 | ||||
| @ -35,12 +35,12 @@ export class FirebaseRedirectSource { | ||||
|       const pattern = glob | ||||
|           .replace(dot, '\\.') | ||||
|           .replace(modifiedPatterns, replaceModifiedPattern) | ||||
|           .replace(restParam, (_, param) => { | ||||
|           .replace(restParam, (_, leadingSlash, groupName) => { | ||||
|             // capture the rest of the string
 | ||||
|             restNamedGroups.push(param); | ||||
|             return `(?:/(?<${param}>.🐷))?`; | ||||
|             restNamedGroups.push(groupName); | ||||
|             return `(?:${leadingSlash}(?<${groupName}>.🐷))?`; | ||||
|           }) | ||||
|           .replace(namedParam, `/(?<$1>[^/]+)`) | ||||
|           .replace(namedParam, `$1(?<$2>[^/]+)`) | ||||
|           .replace(doubleStar, '$1.🐷$2')                 // use the pig to avoid replacing ** in next rule
 | ||||
|           .replace(star, '[^/]*')                         // match a single segment
 | ||||
|           .replace(possiblyEmptyInitialSegments, '(?:.*)')// deal with **/ special cases
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user