angular/packages/common/http/test/jsonp_spec.ts
Maddie Klein d43c0e973f fix(http): Throw error when headers are supplied in JSONP request (#45210)
JSONP does not support headers being set on requests. This
enables JSONP to throw an error when headers are supplied
in the request to prevent attempts to set them.

BREAKING CHANGE: JSONP will throw an error when headers are set on a reques

JSONP does not support headers being set on requests. Before when
a request was sent to a JSONP backend that had headers set the headers
were ignored. The JSONP backend will now throw an error if it
receives a request that has any headers set. Any uses of JSONP
on requests with headers set will need to remove the headers
to avoid the error.

Closes #9141

PR Close #45210
2022-03-28 09:38:19 -07:00

102 lines
3.8 KiB
TypeScript

/**
* @license
* Copyright Google LLC All Rights Reserved.sonpCallbackContext
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {HttpHeaders} from '@angular/common/http/src/headers';
import {JSONP_ERR_HEADERS_NOT_SUPPORTED, JSONP_ERR_NO_CALLBACK, JSONP_ERR_WRONG_METHOD, JSONP_ERR_WRONG_RESPONSE_TYPE, JsonpClientBackend} from '@angular/common/http/src/jsonp';
import {HttpRequest} from '@angular/common/http/src/request';
import {HttpErrorResponse, HttpEventType} from '@angular/common/http/src/response';
import {toArray} from 'rxjs/operators';
import {MockDocument} from './jsonp_mock';
function runOnlyCallback(home: any, data: Object) {
const keys = Object.keys(home);
expect(keys.length).toBe(1);
const callback = home[keys[0]];
callback(data);
}
const SAMPLE_REQ = new HttpRequest<never>('JSONP', '/test');
{
describe('JsonpClientBackend', () => {
let home: any;
let document: MockDocument;
let backend: JsonpClientBackend;
beforeEach(() => {
home = {};
document = new MockDocument();
backend = new JsonpClientBackend(home, document);
});
it('handles a basic request', done => {
backend.handle(SAMPLE_REQ).pipe(toArray()).subscribe(events => {
expect(events.map(event => event.type)).toEqual([
HttpEventType.Sent,
HttpEventType.Response,
]);
done();
});
runOnlyCallback(home, {data: 'This is a test'});
document.mockLoad();
});
// Issue #39496
it('handles a request with callback call wrapped in promise', done => {
backend.handle(SAMPLE_REQ).subscribe(() => {
done();
});
Promise.resolve().then(() => {
runOnlyCallback(home, {data: 'This is a test'});
});
document.mockLoad();
});
it('handles an error response properly', done => {
const error = new Error('This is a test error');
backend.handle(SAMPLE_REQ).pipe(toArray()).subscribe(undefined, (err: HttpErrorResponse) => {
expect(err.status).toBe(0);
expect(err.error).toBe(error);
done();
});
document.mockError(error);
});
it('prevents the script from executing when the request is cancelled', () => {
const sub = backend.handle(SAMPLE_REQ).subscribe();
expect(Object.keys(home).length).toBe(1);
const keys = Object.keys(home);
const spy = jasmine.createSpy('spy', home[keys[0]]);
sub.unsubscribe();
document.mockLoad();
expect(Object.keys(home).length).toBe(0);
expect(spy).not.toHaveBeenCalled();
// The script element should have been transferred to a different document to prevent it from
// executing.
expect(document.mock!.ownerDocument).not.toEqual(document);
});
describe('throws an error', () => {
it('when request method is not JSONP',
() => expect(() => backend.handle(SAMPLE_REQ.clone<never>({method: 'GET'})))
.toThrowError(JSONP_ERR_WRONG_METHOD));
it('when response type is not json',
() => expect(() => backend.handle(SAMPLE_REQ.clone<never>({responseType: 'text'})))
.toThrowError(JSONP_ERR_WRONG_RESPONSE_TYPE));
it('when headers are set in request',
() => expect(() => backend.handle(SAMPLE_REQ.clone<never>({
headers: new HttpHeaders({'Content-Type': 'application/json'})
}))).toThrowError(JSONP_ERR_HEADERS_NOT_SUPPORTED));
it('when callback is never called', done => {
backend.handle(SAMPLE_REQ).subscribe(undefined, (err: HttpErrorResponse) => {
expect(err.status).toBe(0);
expect(err.error instanceof Error).toEqual(true);
expect(err.error.message).toEqual(JSONP_ERR_NO_CALLBACK);
done();
});
document.mockLoad();
});
});
});
}