diff --git a/aio/firebase.json b/aio/firebase.json index 3fa9c39bd8..bbf7b2220a 100644 --- a/aio/firebase.json +++ b/aio/firebase.json @@ -92,11 +92,12 @@ {"type": 301, "source": "/**/HTTP_PROVIDERS*", "destination": "/api/http/HttpModule"}, // URLs that use the old scheme of adding the type to the end (e.g. `SomeClass-class`) - {"type": 301, "source": "/api/:package/:api-*", "destination": "/api/:package/:api"}, - {"type": 301, "source": "/api/:package/testing/index/:api-*", "destination": "/api/:package/testing/:api"}, - {"type": 301, "source": "/api/:package/testing/:api-*", "destination": "/api/:package/testing/:api"}, - {"type": 301, "source": "/api/upgrade/:package/index/:api-*", "destination": "/api/upgrade/:package/:api"}, - {"type": 301, "source": "/api/upgrade/:package/:api-*", "destination": "/api/upgrade/:package/:api"}, + // (Exclude disambiguated URLs that might be suffixed with `-\d+` (e.g. `SomeClass-1`)) + {"type": 301, "regex": "^/api/(?P[^/]+)/(?P[^/]+)-\\D*$", "destination": "/api/:package/:api"}, + {"type": 301, "regex": "^/api/(?P[^/]+)/testing/index/(?P[^/]+)$", "destination": "/api/:package/testing/:api"}, + {"type": 301, "regex": "^/api/(?P[^/]+)/testing/(?P[^/]+)-\\D*$", "destination": "/api/:package/testing/:api"}, + {"type": 301, "regex": "^/api/upgrade/(?P[^/]+)/index/(?P[^/]+)$", "destination": "/api/upgrade/:package/:api"}, + {"type": 301, "regex": "^/api/upgrade/(?P[^/]+)/(?P[^/]+)-\\D*$", "destination": "/api/upgrade/:package/:api"}, // URLs that use the old scheme before we moved the docs to the angular/angular repo {"type": 301, "source": "/docs/*/latest", "destination": "/docs"}, diff --git a/aio/ngsw-config.json b/aio/ngsw-config.json index ce6c12bfaf..1231b6dece 100644 --- a/aio/ngsw-config.json +++ b/aio/ngsw-config.json @@ -76,7 +76,7 @@ "!/**/*__*/**", "!/**/stackblitz", "!/**/stackblitz.html", - "!/api/*/**/*-*", + "!/api/*/**/*-\\D{0,}", "!/api/**/AnimationStateDeclarationMetadata*", "!/api/**/CORE_DIRECTIVES*", "!/api/**/DirectiveMetadata*", diff --git a/aio/tests/deployment/unit/testFirebaseRedirection.spec.ts b/aio/tests/deployment/unit/testFirebaseRedirection.spec.ts index 9ac74675f2..7623227ae7 100644 --- a/aio/tests/deployment/unit/testFirebaseRedirection.spec.ts +++ b/aio/tests/deployment/unit/testFirebaseRedirection.spec.ts @@ -33,4 +33,20 @@ describe('firebase.json redirect config', () => { }); }); }); + + it('should not redirect disambiguated URLs', () => { + const redirector = getRedirector(); + + // Disambiguated URL. + const url1 = '/api/core/Foo-0'; + expect(redirector.redirect(url1)).toBe(url1); + + // Disambiguated URL. + const url2 = '/api/core/BAR-1337'; + expect(redirector.redirect(url2)).toBe(url2); + + // Non-disambiguated URL with dash. + const url3 = '/api/core/baz-class'; + expect(redirector.redirect(url3)).toBe('/api/core/baz'); + }); }); diff --git a/aio/tests/deployment/unit/testServiceWorkerRoutes.spec.ts b/aio/tests/deployment/unit/testServiceWorkerRoutes.spec.ts index 98d37fb007..41fc8429ee 100644 --- a/aio/tests/deployment/unit/testServiceWorkerRoutes.spec.ts +++ b/aio/tests/deployment/unit/testServiceWorkerRoutes.spec.ts @@ -35,4 +35,18 @@ describe('ServiceWorker navigation URLs', () => { navigationUrls.forEach(url => expect(isNavigationUrl(url)).toBeTruthy(url)); nonNavigationUrls.forEach(url => expect(isNavigationUrl(url)).toBeFalsy(url)); }); + + it('should treat disambiguated URLs as navigation URLs', () => { + // Disambiguated URL. + const url1 = '/api/core/Foo-0'; + expect(isNavigationUrl(url1)).toBeTruthy(url1); + + // Disambiguated URL. + const url2 = '/api/core/BAR-1337'; + expect(isNavigationUrl(url2)).toBeTruthy(url2); + + // Non-disambiguated URL with dash. + const url3 = '/api/core/baz-class'; + expect(isNavigationUrl(url3)).toBeFalsy(url3); + }); });