-
Notifications
You must be signed in to change notification settings - Fork 26.7k
Description
Which @angular/* package(s) are the source of the bug?
common
Is this a regression?
No
Description
This came up when testing an authentication http interceptor.
auth.interceptor.ts
export const authInterceptor: HttpInterceptorFn = (req, next) => {
return next(req).pipe(
catchError((err, caught) => {
if (err instanceof HttpErrorResponse && err.status === 401 && new URL(err.url).pathname !== '/api/logon') {
return doLogonAndRetry(err, caught);
}
throw err;
})
);
};Even if just the path specified when the request was made, when a 401 response comes back from the server err.url contains a full URL e.g. https://angular.example/api/logon. So the above code works with a service like:
auth.service.ts
@Injectable({providedIn: 'root'})
export class AuthService {
private readonly http = inject(HttpClient);
logon(username: string, password: string) {
return this.http.post('/api/logon', {username, password});
}
validateSession(username: string, password: string) {
return this.http.get('/api/whoami');
}
}However in a test using the HttpTestingController e.g.
auth.interceptor.spec.ts
it('should not intercept logon requests') {
const http = TestBed.inject(HttpTestingController);
const authService = TestBed.inject(AuthService);
let receivedError: unknown;
authService.logon('user', 'pass').subscribe({
error: (error) => receivedError = error;
});
const req = controller.expectOne('/api/logon');
req.flush({}, {status: 401, statusText: 'Unauthorized'});
expect(receivedError).toBeInstanceOf(HttpErrorResponse);
if (receivedError instanceof HttpErrorResponse) {
expect(receivedError.status).toBe(401);
expect(receivedError.statusText).toBe('Unauthorized');
}
});Instead receivedError is "TypeError: Failed to construct 'URL': Invalid URL". This is because err.url only contains the string /logon.
I would expect HttpTestingController to emulate the behavior of connecting to an actual server as much as possible and so would expect the path to be expanded in to a full URL.
This also means I cannot use existing services to test the interceptor in this case.
Please provide a link to a minimal reproduction of the bug
No response
Please provide the exception or error you saw
TypeError: Failed to construct 'URL': Invalid URL
Please provide the environment you discovered this bug in (run ng version)
_ _ ____ _ ___
/ \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _|
/ △ \ | '_ \ / _` | | | | |/ _` | '__| | | | | | |
/ ___ \| | | | (_| | |_| | | (_| | | | |___| |___ | |
/_/ \_\_| |_|\__, |\__,_|_|\__,_|_| \____|_____|___|
|___/
Angular CLI: 20.1.3
Node: 22.13.1
Package Manager: npm 10.9.2
OS: win32 x64
Angular: 20.1.3
... build, cdk, cli, common, compiler, compiler-cli, core, forms
... platform-browser, router
Package Version
------------------------------------------------------
@angular-devkit/architect 0.2001.3
@angular-devkit/core 20.1.3
@angular-devkit/schematics 20.1.3
@schematics/angular 20.1.3
rxjs 7.8.2
typescript 5.8.3
Repoduction
https://stackblitz.com/edit/stackblitz-starters-oo4yziqx?file=index.js
First try running in two terminals npm run backend and npm start.
You can see the error has the full URL.
Then try running npm run test you can see the URL is the relative path.