From e7a8e2757b06d572f614f53b648d2fd75df370d2 Mon Sep 17 00:00:00 2001 From: Damien Cassan Date: Fri, 27 May 2016 00:47:20 +0200 Subject: [PATCH] refactor(http): share 'body' logic between Request and Response --- modules/@angular/http/http.ts | 2 +- .../@angular/http/src/backends/xhr_backend.ts | 24 ++-- .../@angular/http/src/base_request_options.ts | 16 ++- .../http/src/base_response_options.ts | 2 +- modules/@angular/http/src/body.ts | 84 +++++++++++ modules/@angular/http/src/enums.ts | 5 +- modules/@angular/http/src/http.ts | 2 +- modules/@angular/http/src/http_utils.ts | 8 +- modules/@angular/http/src/interfaces.ts | 7 +- modules/@angular/http/src/static_request.ts | 50 +------ modules/@angular/http/src/static_response.ts | 62 +-------- .../http/test/backends/xhr_backend_spec.ts | 2 +- modules/@angular/http/test/http_spec.ts | 130 +++++++++--------- tools/public_api_guard/http/index.d.ts | 28 ++-- 14 files changed, 211 insertions(+), 211 deletions(-) create mode 100644 modules/@angular/http/src/body.ts diff --git a/modules/@angular/http/http.ts b/modules/@angular/http/http.ts index 61c3312ea0..fe6eaa971c 100644 --- a/modules/@angular/http/http.ts +++ b/modules/@angular/http/http.ts @@ -28,7 +28,7 @@ export {JSONPBackend, JSONPConnection} from './src/backends/jsonp_backend'; export {CookieXSRFStrategy, XHRBackend, XHRConnection} from './src/backends/xhr_backend'; export {BaseRequestOptions, RequestOptions} from './src/base_request_options'; export {BaseResponseOptions, ResponseOptions} from './src/base_response_options'; -export {ReadyState, RequestMethod, ResponseBuffer, ResponseType} from './src/enums'; +export {ReadyState, RequestMethod, ResponseContentType, ResponseType} from './src/enums'; export {Headers} from './src/headers'; export {Http, Jsonp} from './src/http'; export {Connection, ConnectionBackend, RequestOptionsArgs, ResponseOptionsArgs, XSRFStrategy} from './src/interfaces'; diff --git a/modules/@angular/http/src/backends/xhr_backend.ts b/modules/@angular/http/src/backends/xhr_backend.ts index fbb379dcc7..99bf4f0123 100644 --- a/modules/@angular/http/src/backends/xhr_backend.ts +++ b/modules/@angular/http/src/backends/xhr_backend.ts @@ -12,7 +12,7 @@ import {Observable} from 'rxjs/Observable'; import {Observer} from 'rxjs/Observer'; import {ResponseOptions} from '../base_response_options'; -import {ContentType, ReadyState, RequestMethod, ResponseType, ResponseBuffer} from '../enums'; +import {ContentType, ReadyState, RequestMethod, ResponseContentType, ResponseType} from '../enums'; import {isPresent, isString} from '../facade/lang'; import {Headers} from '../headers'; import {getResponseURL, isSuccess} from '../http_utils'; @@ -24,7 +24,6 @@ import {BrowserXhr} from './browser_xhr'; const XSSI_PREFIX = /^\)\]\}',?\n/; - /** * Creates connections using `XMLHttpRequest`. Given a fully-qualified * request, an `XHRConnection` will immediately create an `XMLHttpRequest` object and send the @@ -52,7 +51,7 @@ export class XHRConnection implements Connection { _xhr.withCredentials = req.withCredentials; } // load event handler - let onLoad = () => { + let onLoad = () => { // responseText is the old-school way of retrieving response (supported by IE8 & 9) // response/responseType properties were introduced in XHR Level2 spec (supported by // IE10) @@ -110,18 +109,21 @@ export class XHRConnection implements Connection { } // Select the correct buffer type to store the response - if (isPresent(req.buffer) && isPresent(_xhr.responseType)) switch (req.buffer) { - case ResponseBuffer.ArrayBuffer: - _xhr.responseType = "arraybuffer"; + if (isPresent(req.responseType) && isPresent(_xhr.responseType)) { + switch (req.responseType) { + case ResponseContentType.ArrayBuffer: + _xhr.responseType = 'arraybuffer'; break; - case ResponseBuffer.Json: - _xhr.responseType = "json"; + case ResponseContentType.Json: + _xhr.responseType = 'json'; + break; + case ResponseContentType.Text: + _xhr.responseType = 'text'; break; default: - case ResponseBuffer.Text: - _xhr.responseType = "text"; - break; + throw new Error('The selected responseType is not supported'); } + } _xhr.addEventListener('load', onLoad); _xhr.addEventListener('error', onError); diff --git a/modules/@angular/http/src/base_request_options.ts b/modules/@angular/http/src/base_request_options.ts index 54e274eefe..ba33246b9b 100644 --- a/modules/@angular/http/src/base_request_options.ts +++ b/modules/@angular/http/src/base_request_options.ts @@ -10,7 +10,7 @@ import {Injectable} from '@angular/core'; import {isPresent, isString} from '../src/facade/lang'; -import {RequestMethod, ResponseBuffer} from './enums'; +import {RequestMethod, ResponseContentType} from './enums'; import {Headers} from './headers'; import {normalizeMethodName} from './http_utils'; import {RequestOptionsArgs} from './interfaces'; @@ -72,10 +72,11 @@ export class RequestOptions { /* * Select a buffer to store the response, such as ArrayBuffer, Blob, Json (or Document) */ - buffer: ResponseBuffer; - - constructor({method, headers, body, url, search, withCredentials, buffer}: RequestOptionsArgs = {}) { + responseType: ResponseContentType; + constructor( + {method, headers, body, url, search, withCredentials, + responseType}: RequestOptionsArgs = {}) { this.method = isPresent(method) ? normalizeMethodName(method) : null; this.headers = isPresent(headers) ? headers : null; this.body = isPresent(body) ? body : null; @@ -84,7 +85,7 @@ export class RequestOptions { (isString(search) ? new URLSearchParams((search)) : (search)) : null; this.withCredentials = isPresent(withCredentials) ? withCredentials : null; - this.buffer = isPresent(buffer) ? buffer : null; + this.responseType = isPresent(responseType) ? responseType : null; } /** @@ -124,8 +125,9 @@ export class RequestOptions { this.search, withCredentials: isPresent(options) && isPresent(options.withCredentials) ? options.withCredentials : - this.withCredentials, - buffer: isPresent(options) && isPresent(options.buffer) ? options.buffer : this.buffer + this.withCredentials, + responseType: isPresent(options) && isPresent(options.responseType) ? options.responseType : + this.responseType }); } } diff --git a/modules/@angular/http/src/base_response_options.ts b/modules/@angular/http/src/base_response_options.ts index 689bb89a32..e0a58bf34f 100644 --- a/modules/@angular/http/src/base_response_options.ts +++ b/modules/@angular/http/src/base_response_options.ts @@ -48,7 +48,7 @@ export class ResponseOptions { /** * String, Object, ArrayBuffer representing the body of the {@link Response}. */ - body: string | Object | ArrayBuffer; + body: string|Object|ArrayBuffer; /** * Http {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html status code} * associated with the response. diff --git a/modules/@angular/http/src/body.ts b/modules/@angular/http/src/body.ts new file mode 100644 index 0000000000..babd1e59c7 --- /dev/null +++ b/modules/@angular/http/src/body.ts @@ -0,0 +1,84 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * 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 {Json, isString} from '../src/facade/lang'; + +import {isJsObject, stringToArrayBuffer} from './http_utils'; +import {URLSearchParams} from './url_search_params'; + + +/** + * HTTP request body used by both {@link Request} and {@link Response} + * https://fetch.spec.whatwg.org/#body + */ +export abstract class Body { + /** + * @internal + */ + protected _body: any; + + /** + * Attempts to return body as parsed `JSON` object, or raises an exception. + */ + json(): any { + if (isString(this._body)) { + return Json.parse(this._body); + } + + if (this._body instanceof ArrayBuffer) { + return Json.parse(this.text()); + } + + return this._body; + } + + /** + * Returns the body as a string, presuming `toString()` can be called on the response body. + */ + text(): string { + if (this._body instanceof URLSearchParams) { + return this._body.toString(); + } + + if (this._body instanceof ArrayBuffer) { + return String.fromCharCode.apply(null, new Uint16Array(this._body)); + } + + if (isJsObject(this._body)) { + return Json.stringify(this._body); + } + + return this._body.toString(); + } + + /** + * Return the body as an ArrayBuffer + */ + arrayBuffer(): ArrayBuffer { + if (this._body instanceof ArrayBuffer) { + return this._body; + } + + return stringToArrayBuffer(this.text()); + } + + /** + * Returns the request's body as a Blob, assuming that body exists. + */ + blob(): Blob { + if (this._body instanceof Blob) { + return this._body; + } + + if (this._body instanceof ArrayBuffer) { + return new Blob([this._body]); + } + + throw new Error('The request body isn\'t either a blob or an array buffer'); + } +} diff --git a/modules/@angular/http/src/enums.ts b/modules/@angular/http/src/enums.ts index 1506cf50b5..5604263678 100644 --- a/modules/@angular/http/src/enums.ts +++ b/modules/@angular/http/src/enums.ts @@ -62,10 +62,11 @@ export enum ContentType { ARRAY_BUFFER } -/* +/** * Define which buffer to use to store the response + * @experimental */ -export enum ResponseBuffer { +export enum ResponseContentType { ArrayBuffer, Json, Text diff --git a/modules/@angular/http/src/http.ts b/modules/@angular/http/src/http.ts index d6cdaca4c8..53641d2924 100644 --- a/modules/@angular/http/src/http.ts +++ b/modules/@angular/http/src/http.ts @@ -36,7 +36,7 @@ function mergeOptions( headers: providedOpts.headers, body: providedOpts.body, withCredentials: providedOpts.withCredentials, - buffer: providedOpts.buffer + responseType: providedOpts.responseType })); } if (isPresent(method)) { diff --git a/modules/@angular/http/src/http_utils.ts b/modules/@angular/http/src/http_utils.ts index 67fbcc4f33..a69fa0445c 100644 --- a/modules/@angular/http/src/http_utils.ts +++ b/modules/@angular/http/src/http_utils.ts @@ -38,10 +38,10 @@ export function getResponseURL(xhr: any): string { return; } -export function stringToArrayBuffer(string: String): ArrayBuffer { - let view = new Uint16Array(string.length); - for (var i = 0, strLen = string.length; i < strLen; i++) { - view[i] = string.charCodeAt(i); +export function stringToArrayBuffer(input: String): ArrayBuffer { + let view = new Uint16Array(input.length); + for (var i = 0, strLen = input.length; i < strLen; i++) { + view[i] = input.charCodeAt(i); } return view.buffer; } diff --git a/modules/@angular/http/src/interfaces.ts b/modules/@angular/http/src/interfaces.ts index 50c30c030d..8cb8b40546 100644 --- a/modules/@angular/http/src/interfaces.ts +++ b/modules/@angular/http/src/interfaces.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {ReadyState, RequestMethod, ResponseType, ResponseBuffer} from './enums'; +import {ReadyState, RequestMethod, ResponseContentType, ResponseType} from './enums'; import {Headers} from './headers'; import {Request} from './static_request'; import {URLSearchParams} from './url_search_params'; @@ -52,7 +52,7 @@ export interface RequestOptionsArgs { headers?: Headers; body?: any; withCredentials?: boolean; - buffer?: ResponseBuffer; + responseType?: ResponseContentType; } /** @@ -68,7 +68,8 @@ export interface RequestArgs extends RequestOptionsArgs { url: string; } */ export type ResponseOptionsArgs = { // TODO: Support Blob, JSON - body?: string | Object | FormData | ArrayBuffer; status?: number; statusText?: string; headers?: Headers; + body?: string | Object | FormData | ArrayBuffer; status?: number; statusText?: string; + headers?: Headers; type?: ResponseType; url?: string; } diff --git a/modules/@angular/http/src/static_request.ts b/modules/@angular/http/src/static_request.ts index 08f30bd178..c4167dff57 100644 --- a/modules/@angular/http/src/static_request.ts +++ b/modules/@angular/http/src/static_request.ts @@ -8,7 +8,8 @@ import {StringWrapper, isPresent} from '../src/facade/lang'; -import {ContentType, RequestMethod, ResponseBuffer} from './enums'; +import {Body} from './body'; +import {ContentType, RequestMethod, ResponseContentType} from './enums'; import {Headers} from './headers'; import {normalizeMethodName} from './http_utils'; import {RequestArgs} from './interfaces'; @@ -55,7 +56,7 @@ import {URLSearchParams} from './url_search_params'; * * @experimental */ -export class Request { +export class Request extends Body { /** * Http method with which to perform the request. */ @@ -66,15 +67,14 @@ export class Request { headers: Headers; /** Url of the remote resource */ url: string; - /** Body of the request **/ - private _body: any; /** Type of the request body **/ private contentType: ContentType; /** Enable use credentials */ withCredentials: boolean; - /* Select a buffer to store the response */ - buffer: ResponseBuffer; + /** Buffer to store the response */ + responseType: ResponseContentType; constructor(requestOptions: RequestArgs) { + super(); // TODO: assert that url is present let url = requestOptions.url; this.url = requestOptions.url; @@ -97,43 +97,7 @@ export class Request { // TODO(jeffbcross): implement behavior this.headers = new Headers(requestOptions.headers); this.withCredentials = requestOptions.withCredentials; - this.buffer = requestOptions.buffer; - } - - - /** - * Returns the request's body as string, assuming that body exists. If body is undefined, return - * empty - * string. - */ - text(): string { return isPresent(this._body) ? this._body.toString() : ''; } - - /** - * Returns the request's body as JSON string, assuming that body exists. If body is undefined, - * return - * empty - * string. - */ - json(): string { return isPresent(this._body) ? JSON.stringify(this._body) : ''; } - - /** - * Returns the request's body as array buffer, assuming that body exists. If body is undefined, - * return - * null. - */ - arrayBuffer(): ArrayBuffer { - if (this._body instanceof ArrayBuffer) return this._body; - throw 'The request body isn\'t an array buffer'; - } - - /** - * Returns the request's body as blob, assuming that body exists. If body is undefined, return - * null. - */ - blob(): Blob { - if (this._body instanceof Blob) return this._body; - if (this._body instanceof ArrayBuffer) return new Blob([this._body]); - throw 'The request body isn\'t either a blob or an array buffer'; + this.responseType = requestOptions.responseType; } /** diff --git a/modules/@angular/http/src/static_response.ts b/modules/@angular/http/src/static_response.ts index 25b24d86c1..c1f74b6e75 100644 --- a/modules/@angular/http/src/static_response.ts +++ b/modules/@angular/http/src/static_response.ts @@ -10,9 +10,10 @@ import {BaseException} from '../src/facade/exceptions'; import {Json, isString} from '../src/facade/lang'; import {ResponseOptions} from './base_response_options'; +import {Body} from './body'; import {ResponseType} from './enums'; import {Headers} from './headers'; -import {isJsObject, stringToArrayBuffer} from './http_utils'; +import {isJsObject} from './http_utils'; /** @@ -35,7 +36,7 @@ import {isJsObject, stringToArrayBuffer} from './http_utils'; * * @experimental */ -export class Response { +export class Response extends Body { /** * One of "basic", "cors", "default", "error, or "opaque". * @@ -84,10 +85,8 @@ export class Response { */ headers: Headers; - // TODO: Support FormData, Blob - private _body: string | Object | ArrayBuffer; - constructor(responseOptions: ResponseOptions) { + super(); this._body = responseOptions.body; this.status = responseOptions.status; this.ok = (this.status >= 200 && this.status <= 299); @@ -97,60 +96,7 @@ export class Response { this.url = responseOptions.url; } - /** - * Attempts to return body as parsed `JSON` object, or raises an exception. - */ - json(): any { - var jsonResponse: string|Object; - if (isJsObject(this._body)) { - jsonResponse = this._body; - } else if (isString(this._body)) { - jsonResponse = Json.parse(this._body); - } else if (this._body instanceof ArrayBuffer) { - jsonResponse = Json.parse(this.text()); - } else { - jsonResponse = this._body; - } - return jsonResponse; - } - - /** - * Returns the body as a string, presuming `toString()` can be called on the response body. - */ - text(): string { - var textResponse: string; - if (this._body instanceof ArrayBuffer) { - textResponse = String.fromCharCode.apply(null, new Uint16Array(this._body)); - } else if (isJsObject(this._body)) { - textResponse = Json.stringify(this._body); - } else { - textResponse = this._body.toString(); - } - return textResponse; - } - - /** - * Return the body as an ArrayBuffer - */ - arrayBuffer(): ArrayBuffer { - var bufferResponse: ArrayBuffer; - if (this._body instanceof ArrayBuffer) { - bufferResponse = this._body; - } else { - bufferResponse = stringToArrayBuffer(this.text()); - } - return bufferResponse; - } - - toString(): string { return `Response with status: ${this.status} ${this.statusText} for URL: ${this.url}`; } - - /** - * Not yet implemented - */ - // TODO: Blob return type - blob(): any { throw new BaseException('"blob()" method not implemented on Response superclass'); } - } diff --git a/modules/@angular/http/test/backends/xhr_backend_spec.ts b/modules/@angular/http/test/backends/xhr_backend_spec.ts index f1c75890fa..2ae46d62c0 100644 --- a/modules/@angular/http/test/backends/xhr_backend_spec.ts +++ b/modules/@angular/http/test/backends/xhr_backend_spec.ts @@ -256,7 +256,7 @@ export function main() { var connection = new XHRConnection( new Request(base.merge(new RequestOptions({body: body}))), new MockBrowserXHR()); connection.response.subscribe(); - expect(sendSpy).toHaveBeenCalledWith(JSON.stringify(body)); + expect(sendSpy).toHaveBeenCalledWith(body); expect(setRequestHeaderSpy).toHaveBeenCalledWith('Content-Type', 'application/json'); }); diff --git a/modules/@angular/http/test/http_spec.ts b/modules/@angular/http/test/http_spec.ts index 05cf0c6f59..5e9bbe792c 100644 --- a/modules/@angular/http/test/http_spec.ts +++ b/modules/@angular/http/test/http_spec.ts @@ -10,12 +10,12 @@ import {Injector, ReflectiveInjector, provide} from '@angular/core'; import {afterEach, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal'; import {AsyncTestCompleter} from '@angular/core/testing/testing_internal'; import {Observable} from 'rxjs/Observable'; -import 'rxjs/add/observable/zip'; import {Subject} from 'rxjs/Subject'; -import {stringToArrayBuffer} from "../src/http_utils"; -import {Json} from "../src/facade/lang"; +import {zip} from 'rxjs/observable/zip'; -import {BaseRequestOptions, ConnectionBackend, HTTP_PROVIDERS, Http, JSONPBackend, JSONP_PROVIDERS, Jsonp, Request, RequestMethod, RequestOptions, Response, ResponseBuffer, ResponseOptions, URLSearchParams, XHRBackend} from '../http'; +import {BaseRequestOptions, ConnectionBackend, HTTP_PROVIDERS, Http, JSONPBackend, JSONP_PROVIDERS, Jsonp, Request, RequestMethod, RequestOptions, Response, ResponseContentType, ResponseOptions, URLSearchParams, XHRBackend} from '../http'; +import {Json} from '../src/facade/lang'; +import {stringToArrayBuffer} from '../src/http_utils'; import {MockBackend, MockConnection} from '../testing/mock_backend'; export function main() { @@ -388,116 +388,114 @@ export function main() { it('should attach the provided buffer to the response', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { backend.connections.subscribe((c: MockConnection) => { - expect(c.request.buffer).toBe(ResponseBuffer.ArrayBuffer); + expect(c.request.responseType).toBe(ResponseContentType.ArrayBuffer); c.mockRespond(new Response(new ResponseOptions({body: new ArrayBuffer(32)}))); async.done(); }); - http.get('https://www.google.com', - new RequestOptions({buffer: ResponseBuffer.ArrayBuffer})) + http.get( + 'https://www.google.com', + new RequestOptions({responseType: ResponseContentType.ArrayBuffer})) .subscribe((res: Response) => {}); })); it('should be able to consume a buffer containing a String as any response type', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { backend.connections.subscribe((c: MockConnection) => c.mockRespond(baseResponse)); - http.get('https://www.google.com') - .subscribe((res: Response) => { - expect(res.arrayBuffer()).toBeAnInstanceOf(ArrayBuffer); - expect(res.text()).toBe("base response"); - async.done(); - }); + http.get('https://www.google.com').subscribe((res: Response) => { + expect(res.arrayBuffer()).toBeAnInstanceOf(ArrayBuffer); + expect(res.text()).toBe('base response'); + async.done(); + }); })); it('should be able to consume a buffer containing an ArrayBuffer as any response type', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { let arrayBuffer = stringToArrayBuffer('{"response": "ok"}'); - backend.connections.subscribe((c: MockConnection) => c.mockRespond(new Response( - new ResponseOptions({body: arrayBuffer})))); - http.get('https://www.google.com') - .subscribe((res: Response) => { - expect(res.arrayBuffer()).toBe(arrayBuffer); - expect(res.text()).toEqual('{"response": "ok"}'); - expect(res.json()).toEqual({response: "ok"}); - async.done(); - }); + backend.connections.subscribe( + (c: MockConnection) => + c.mockRespond(new Response(new ResponseOptions({body: arrayBuffer})))); + http.get('https://www.google.com').subscribe((res: Response) => { + expect(res.arrayBuffer()).toBe(arrayBuffer); + expect(res.text()).toEqual('{"response": "ok"}'); + expect(res.json()).toEqual({response: 'ok'}); + async.done(); + }); })); it('should be able to consume a buffer containing an Object as any response type', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - let simpleObject = {"content": "ok"}; - backend.connections.subscribe((c: MockConnection) => c.mockRespond(new Response( - new ResponseOptions({body: simpleObject})))); - http.get('https://www.google.com') - .subscribe((res: Response) => { - expect(res.arrayBuffer()).toBeAnInstanceOf(ArrayBuffer); - expect(res.text()).toEqual(Json.stringify(simpleObject)); - expect(res.json()).toBe(simpleObject); - async.done(); - }); + let simpleObject = {'content': 'ok'}; + backend.connections.subscribe( + (c: MockConnection) => + c.mockRespond(new Response(new ResponseOptions({body: simpleObject})))); + http.get('https://www.google.com').subscribe((res: Response) => { + expect(res.arrayBuffer()).toBeAnInstanceOf(ArrayBuffer); + expect(res.text()).toEqual(Json.stringify(simpleObject)); + expect(res.json()).toBe(simpleObject); + async.done(); + }); })); it('should preserve encoding of ArrayBuffer response', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - let message = "é@θЂ"; + let message = 'é@θЂ'; let arrayBuffer = stringToArrayBuffer(message); - backend.connections.subscribe((c: MockConnection) => c.mockRespond(new Response( - new ResponseOptions({body: arrayBuffer})))); - http.get('https://www.google.com') - .subscribe((res: Response) => { - expect(res.arrayBuffer()).toBeAnInstanceOf(ArrayBuffer); - expect(res.text()).toEqual(message); - async.done(); - }); + backend.connections.subscribe( + (c: MockConnection) => + c.mockRespond(new Response(new ResponseOptions({body: arrayBuffer})))); + http.get('https://www.google.com').subscribe((res: Response) => { + expect(res.arrayBuffer()).toBeAnInstanceOf(ArrayBuffer); + expect(res.text()).toEqual(message); + async.done(); + }); })); it('should preserve encoding of String response', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - let message = "é@θЂ"; - backend.connections.subscribe((c: MockConnection) => c.mockRespond( - new Response(new ResponseOptions({body: message})))); - http.get('https://www.google.com') - .subscribe((res: Response) => { - expect(res.arrayBuffer()).toEqual(stringToArrayBuffer(message)); - async.done(); - }); + let message = 'é@θЂ'; + backend.connections.subscribe( + (c: MockConnection) => + c.mockRespond(new Response(new ResponseOptions({body: message})))); + http.get('https://www.google.com').subscribe((res: Response) => { + expect(res.arrayBuffer()).toEqual(stringToArrayBuffer(message)); + async.done(); + }); })); it('should have an equivalent response independently of the buffer used', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - let message = {"param": "content"}; + let message = {'param': 'content'}; backend.connections.subscribe((c: MockConnection) => { let body = (): any => { - switch (c.request.buffer) { - case ResponseBuffer.Text: + switch (c.request.responseType) { + case ResponseContentType.Text: return Json.stringify(message); - case ResponseBuffer.Json: + case ResponseContentType.Json: return message; - case ResponseBuffer.ArrayBuffer: + case ResponseContentType.ArrayBuffer: return stringToArrayBuffer(Json.stringify(message)); } }; c.mockRespond(new Response(new ResponseOptions({body: body()}))) }); - Observable.zip(http.get('https://www.google.com', - new RequestOptions({buffer: ResponseBuffer.Text})), - http.get('https://www.google.com', - new RequestOptions({buffer: ResponseBuffer.Json})), - http.get('https://www.google.com', - new RequestOptions({buffer: ResponseBuffer.ArrayBuffer})), - (x, y, z) => [x, y, z]) - .subscribe((res: Array) => { + zip(http.get( + 'https://www.google.com', + new RequestOptions({responseType: ResponseContentType.Text})), + http.get( + 'https://www.google.com', + new RequestOptions({responseType: ResponseContentType.Json})), + http.get( + 'https://www.google.com', + new RequestOptions({responseType: ResponseContentType.ArrayBuffer}))) + .subscribe((res: Array) => { expect(res[0].text()).toEqual(res[1].text()); expect(res[1].text()).toEqual(res[2].text()); async.done(); }); })); - - }); - - }); } diff --git a/tools/public_api_guard/http/index.d.ts b/tools/public_api_guard/http/index.d.ts index c8cd31291e..dcafbccd4b 100644 --- a/tools/public_api_guard/http/index.d.ts +++ b/tools/public_api_guard/http/index.d.ts @@ -117,18 +117,15 @@ export declare enum ReadyState { } /** @experimental */ -export declare class Request { +export declare class Request extends Body { headers: Headers; method: RequestMethod; + responseType: ResponseContentType; url: string; withCredentials: boolean; constructor(requestOptions: RequestArgs); - arrayBuffer(): ArrayBuffer; - blob(): Blob; detectContentType(): ContentType; getBody(): any; - json(): string; - text(): string; } /** @experimental */ @@ -147,10 +144,11 @@ export declare class RequestOptions { body: any; headers: Headers; method: RequestMethod | string; + responseType: ResponseContentType; search: URLSearchParams; url: string; withCredentials: boolean; - constructor({method, headers, body, url, search, withCredentials}?: RequestOptionsArgs); + constructor({method, headers, body, url, search, withCredentials, responseType}?: RequestOptionsArgs); merge(options?: RequestOptionsArgs): RequestOptions; } @@ -159,13 +157,14 @@ export interface RequestOptionsArgs { body?: any; headers?: Headers; method?: string | RequestMethod; + responseType?: ResponseContentType; search?: string | URLSearchParams; url?: string; withCredentials?: boolean; } /** @experimental */ -export declare class Response { +export declare class Response extends Body { bytesLoaded: number; headers: Headers; ok: boolean; @@ -175,16 +174,19 @@ export declare class Response { type: ResponseType; url: string; constructor(responseOptions: ResponseOptions); - arrayBuffer(): any; - blob(): any; - json(): any; - text(): string; toString(): string; } +/** @experimental */ +export declare enum ResponseContentType { + ArrayBuffer = 0, + Json = 1, + Text = 2, +} + /** @experimental */ export declare class ResponseOptions { - body: string | Object; + body: string | Object | ArrayBuffer; headers: Headers; status: number; url: string; @@ -194,7 +196,7 @@ export declare class ResponseOptions { /** @experimental */ export declare type ResponseOptionsArgs = { - body?: string | Object | FormData; + body?: string | Object | FormData | ArrayBuffer; status?: number; statusText?: string; headers?: Headers;