refactor(http): share 'body' logic between Request and Response
This commit is contained in:
parent
1266460386
commit
e7a8e2757b
|
@ -28,7 +28,7 @@ export {JSONPBackend, JSONPConnection} from './src/backends/jsonp_backend';
|
||||||
export {CookieXSRFStrategy, XHRBackend, XHRConnection} from './src/backends/xhr_backend';
|
export {CookieXSRFStrategy, XHRBackend, XHRConnection} from './src/backends/xhr_backend';
|
||||||
export {BaseRequestOptions, RequestOptions} from './src/base_request_options';
|
export {BaseRequestOptions, RequestOptions} from './src/base_request_options';
|
||||||
export {BaseResponseOptions, ResponseOptions} from './src/base_response_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 {Headers} from './src/headers';
|
||||||
export {Http, Jsonp} from './src/http';
|
export {Http, Jsonp} from './src/http';
|
||||||
export {Connection, ConnectionBackend, RequestOptionsArgs, ResponseOptionsArgs, XSRFStrategy} from './src/interfaces';
|
export {Connection, ConnectionBackend, RequestOptionsArgs, ResponseOptionsArgs, XSRFStrategy} from './src/interfaces';
|
||||||
|
|
|
@ -12,7 +12,7 @@ import {Observable} from 'rxjs/Observable';
|
||||||
import {Observer} from 'rxjs/Observer';
|
import {Observer} from 'rxjs/Observer';
|
||||||
|
|
||||||
import {ResponseOptions} from '../base_response_options';
|
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 {isPresent, isString} from '../facade/lang';
|
||||||
import {Headers} from '../headers';
|
import {Headers} from '../headers';
|
||||||
import {getResponseURL, isSuccess} from '../http_utils';
|
import {getResponseURL, isSuccess} from '../http_utils';
|
||||||
|
@ -24,7 +24,6 @@ import {BrowserXhr} from './browser_xhr';
|
||||||
|
|
||||||
const XSSI_PREFIX = /^\)\]\}',?\n/;
|
const XSSI_PREFIX = /^\)\]\}',?\n/;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates connections using `XMLHttpRequest`. Given a fully-qualified
|
* Creates connections using `XMLHttpRequest`. Given a fully-qualified
|
||||||
* request, an `XHRConnection` will immediately create an `XMLHttpRequest` object and send the
|
* 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;
|
_xhr.withCredentials = req.withCredentials;
|
||||||
}
|
}
|
||||||
// load event handler
|
// load event handler
|
||||||
let onLoad = () => {
|
let onLoad = () => {
|
||||||
// responseText is the old-school way of retrieving response (supported by IE8 & 9)
|
// responseText is the old-school way of retrieving response (supported by IE8 & 9)
|
||||||
// response/responseType properties were introduced in XHR Level2 spec (supported by
|
// response/responseType properties were introduced in XHR Level2 spec (supported by
|
||||||
// IE10)
|
// IE10)
|
||||||
|
@ -110,18 +109,21 @@ export class XHRConnection implements Connection {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select the correct buffer type to store the response
|
// Select the correct buffer type to store the response
|
||||||
if (isPresent(req.buffer) && isPresent(_xhr.responseType)) switch (req.buffer) {
|
if (isPresent(req.responseType) && isPresent(_xhr.responseType)) {
|
||||||
case ResponseBuffer.ArrayBuffer:
|
switch (req.responseType) {
|
||||||
_xhr.responseType = "arraybuffer";
|
case ResponseContentType.ArrayBuffer:
|
||||||
|
_xhr.responseType = 'arraybuffer';
|
||||||
break;
|
break;
|
||||||
case ResponseBuffer.Json:
|
case ResponseContentType.Json:
|
||||||
_xhr.responseType = "json";
|
_xhr.responseType = 'json';
|
||||||
|
break;
|
||||||
|
case ResponseContentType.Text:
|
||||||
|
_xhr.responseType = 'text';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
case ResponseBuffer.Text:
|
throw new Error('The selected responseType is not supported');
|
||||||
_xhr.responseType = "text";
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_xhr.addEventListener('load', onLoad);
|
_xhr.addEventListener('load', onLoad);
|
||||||
_xhr.addEventListener('error', onError);
|
_xhr.addEventListener('error', onError);
|
||||||
|
|
|
@ -10,7 +10,7 @@ import {Injectable} from '@angular/core';
|
||||||
|
|
||||||
import {isPresent, isString} from '../src/facade/lang';
|
import {isPresent, isString} from '../src/facade/lang';
|
||||||
|
|
||||||
import {RequestMethod, ResponseBuffer} from './enums';
|
import {RequestMethod, ResponseContentType} from './enums';
|
||||||
import {Headers} from './headers';
|
import {Headers} from './headers';
|
||||||
import {normalizeMethodName} from './http_utils';
|
import {normalizeMethodName} from './http_utils';
|
||||||
import {RequestOptionsArgs} from './interfaces';
|
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)
|
* Select a buffer to store the response, such as ArrayBuffer, Blob, Json (or Document)
|
||||||
*/
|
*/
|
||||||
buffer: ResponseBuffer;
|
responseType: ResponseContentType;
|
||||||
|
|
||||||
constructor({method, headers, body, url, search, withCredentials, buffer}: RequestOptionsArgs = {}) {
|
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
{method, headers, body, url, search, withCredentials,
|
||||||
|
responseType}: RequestOptionsArgs = {}) {
|
||||||
this.method = isPresent(method) ? normalizeMethodName(method) : null;
|
this.method = isPresent(method) ? normalizeMethodName(method) : null;
|
||||||
this.headers = isPresent(headers) ? headers : null;
|
this.headers = isPresent(headers) ? headers : null;
|
||||||
this.body = isPresent(body) ? body : null;
|
this.body = isPresent(body) ? body : null;
|
||||||
|
@ -84,7 +85,7 @@ export class RequestOptions {
|
||||||
(isString(search) ? new URLSearchParams(<string>(search)) : <URLSearchParams>(search)) :
|
(isString(search) ? new URLSearchParams(<string>(search)) : <URLSearchParams>(search)) :
|
||||||
null;
|
null;
|
||||||
this.withCredentials = isPresent(withCredentials) ? withCredentials : 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,
|
this.search,
|
||||||
withCredentials: isPresent(options) && isPresent(options.withCredentials) ?
|
withCredentials: isPresent(options) && isPresent(options.withCredentials) ?
|
||||||
options.withCredentials :
|
options.withCredentials :
|
||||||
this.withCredentials,
|
this.withCredentials,
|
||||||
buffer: isPresent(options) && isPresent(options.buffer) ? options.buffer : this.buffer
|
responseType: isPresent(options) && isPresent(options.responseType) ? options.responseType :
|
||||||
|
this.responseType
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ export class ResponseOptions {
|
||||||
/**
|
/**
|
||||||
* String, Object, ArrayBuffer representing the body of the {@link Response}.
|
* 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}
|
* Http {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html status code}
|
||||||
* associated with the response.
|
* associated with the response.
|
||||||
|
|
|
@ -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(<string>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(<ArrayBuffer>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 <ArrayBuffer>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 <Blob>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');
|
||||||
|
}
|
||||||
|
}
|
|
@ -62,10 +62,11 @@ export enum ContentType {
|
||||||
ARRAY_BUFFER
|
ARRAY_BUFFER
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Define which buffer to use to store the response
|
* Define which buffer to use to store the response
|
||||||
|
* @experimental
|
||||||
*/
|
*/
|
||||||
export enum ResponseBuffer {
|
export enum ResponseContentType {
|
||||||
ArrayBuffer,
|
ArrayBuffer,
|
||||||
Json,
|
Json,
|
||||||
Text
|
Text
|
||||||
|
|
|
@ -36,7 +36,7 @@ function mergeOptions(
|
||||||
headers: providedOpts.headers,
|
headers: providedOpts.headers,
|
||||||
body: providedOpts.body,
|
body: providedOpts.body,
|
||||||
withCredentials: providedOpts.withCredentials,
|
withCredentials: providedOpts.withCredentials,
|
||||||
buffer: providedOpts.buffer
|
responseType: providedOpts.responseType
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
if (isPresent(method)) {
|
if (isPresent(method)) {
|
||||||
|
|
|
@ -38,10 +38,10 @@ export function getResponseURL(xhr: any): string {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function stringToArrayBuffer(string: String): ArrayBuffer {
|
export function stringToArrayBuffer(input: String): ArrayBuffer {
|
||||||
let view = new Uint16Array(string.length);
|
let view = new Uint16Array(input.length);
|
||||||
for (var i = 0, strLen = string.length; i < strLen; i++) {
|
for (var i = 0, strLen = input.length; i < strLen; i++) {
|
||||||
view[i] = string.charCodeAt(i);
|
view[i] = input.charCodeAt(i);
|
||||||
}
|
}
|
||||||
return view.buffer;
|
return view.buffer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* 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 {Headers} from './headers';
|
||||||
import {Request} from './static_request';
|
import {Request} from './static_request';
|
||||||
import {URLSearchParams} from './url_search_params';
|
import {URLSearchParams} from './url_search_params';
|
||||||
|
@ -52,7 +52,7 @@ export interface RequestOptionsArgs {
|
||||||
headers?: Headers;
|
headers?: Headers;
|
||||||
body?: any;
|
body?: any;
|
||||||
withCredentials?: boolean;
|
withCredentials?: boolean;
|
||||||
buffer?: ResponseBuffer;
|
responseType?: ResponseContentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -68,7 +68,8 @@ export interface RequestArgs extends RequestOptionsArgs { url: string; }
|
||||||
*/
|
*/
|
||||||
export type ResponseOptionsArgs = {
|
export type ResponseOptionsArgs = {
|
||||||
// TODO: Support Blob, JSON
|
// 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;
|
type?: ResponseType;
|
||||||
url?: string;
|
url?: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,8 @@
|
||||||
|
|
||||||
import {StringWrapper, isPresent} from '../src/facade/lang';
|
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 {Headers} from './headers';
|
||||||
import {normalizeMethodName} from './http_utils';
|
import {normalizeMethodName} from './http_utils';
|
||||||
import {RequestArgs} from './interfaces';
|
import {RequestArgs} from './interfaces';
|
||||||
|
@ -55,7 +56,7 @@ import {URLSearchParams} from './url_search_params';
|
||||||
*
|
*
|
||||||
* @experimental
|
* @experimental
|
||||||
*/
|
*/
|
||||||
export class Request {
|
export class Request extends Body {
|
||||||
/**
|
/**
|
||||||
* Http method with which to perform the request.
|
* Http method with which to perform the request.
|
||||||
*/
|
*/
|
||||||
|
@ -66,15 +67,14 @@ export class Request {
|
||||||
headers: Headers;
|
headers: Headers;
|
||||||
/** Url of the remote resource */
|
/** Url of the remote resource */
|
||||||
url: string;
|
url: string;
|
||||||
/** Body of the request **/
|
|
||||||
private _body: any;
|
|
||||||
/** Type of the request body **/
|
/** Type of the request body **/
|
||||||
private contentType: ContentType;
|
private contentType: ContentType;
|
||||||
/** Enable use credentials */
|
/** Enable use credentials */
|
||||||
withCredentials: boolean;
|
withCredentials: boolean;
|
||||||
/* Select a buffer to store the response */
|
/** Buffer to store the response */
|
||||||
buffer: ResponseBuffer;
|
responseType: ResponseContentType;
|
||||||
constructor(requestOptions: RequestArgs) {
|
constructor(requestOptions: RequestArgs) {
|
||||||
|
super();
|
||||||
// TODO: assert that url is present
|
// TODO: assert that url is present
|
||||||
let url = requestOptions.url;
|
let url = requestOptions.url;
|
||||||
this.url = requestOptions.url;
|
this.url = requestOptions.url;
|
||||||
|
@ -97,43 +97,7 @@ export class Request {
|
||||||
// TODO(jeffbcross): implement behavior
|
// TODO(jeffbcross): implement behavior
|
||||||
this.headers = new Headers(requestOptions.headers);
|
this.headers = new Headers(requestOptions.headers);
|
||||||
this.withCredentials = requestOptions.withCredentials;
|
this.withCredentials = requestOptions.withCredentials;
|
||||||
this.buffer = requestOptions.buffer;
|
this.responseType = requestOptions.responseType;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 <ArrayBuffer>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 <Blob>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';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -10,9 +10,10 @@ import {BaseException} from '../src/facade/exceptions';
|
||||||
import {Json, isString} from '../src/facade/lang';
|
import {Json, isString} from '../src/facade/lang';
|
||||||
|
|
||||||
import {ResponseOptions} from './base_response_options';
|
import {ResponseOptions} from './base_response_options';
|
||||||
|
import {Body} from './body';
|
||||||
import {ResponseType} from './enums';
|
import {ResponseType} from './enums';
|
||||||
import {Headers} from './headers';
|
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
|
* @experimental
|
||||||
*/
|
*/
|
||||||
export class Response {
|
export class Response extends Body {
|
||||||
/**
|
/**
|
||||||
* One of "basic", "cors", "default", "error, or "opaque".
|
* One of "basic", "cors", "default", "error, or "opaque".
|
||||||
*
|
*
|
||||||
|
@ -84,10 +85,8 @@ export class Response {
|
||||||
*/
|
*/
|
||||||
headers: Headers;
|
headers: Headers;
|
||||||
|
|
||||||
// TODO: Support FormData, Blob
|
|
||||||
private _body: string | Object | ArrayBuffer;
|
|
||||||
|
|
||||||
constructor(responseOptions: ResponseOptions) {
|
constructor(responseOptions: ResponseOptions) {
|
||||||
|
super();
|
||||||
this._body = responseOptions.body;
|
this._body = responseOptions.body;
|
||||||
this.status = responseOptions.status;
|
this.status = responseOptions.status;
|
||||||
this.ok = (this.status >= 200 && this.status <= 299);
|
this.ok = (this.status >= 200 && this.status <= 299);
|
||||||
|
@ -97,60 +96,7 @@ export class Response {
|
||||||
this.url = responseOptions.url;
|
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(<string>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(<ArrayBuffer>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 = <ArrayBuffer>this._body;
|
|
||||||
} else {
|
|
||||||
bufferResponse = stringToArrayBuffer(this.text());
|
|
||||||
}
|
|
||||||
return bufferResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
toString(): string {
|
toString(): string {
|
||||||
return `Response with status: ${this.status} ${this.statusText} for URL: ${this.url}`;
|
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'); }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -256,7 +256,7 @@ export function main() {
|
||||||
var connection = new XHRConnection(
|
var connection = new XHRConnection(
|
||||||
new Request(base.merge(new RequestOptions({body: body}))), new MockBrowserXHR());
|
new Request(base.merge(new RequestOptions({body: body}))), new MockBrowserXHR());
|
||||||
connection.response.subscribe();
|
connection.response.subscribe();
|
||||||
expect(sendSpy).toHaveBeenCalledWith(JSON.stringify(body));
|
expect(sendSpy).toHaveBeenCalledWith(body);
|
||||||
expect(setRequestHeaderSpy).toHaveBeenCalledWith('Content-Type', 'application/json');
|
expect(setRequestHeaderSpy).toHaveBeenCalledWith('Content-Type', 'application/json');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -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 {afterEach, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
|
||||||
import {AsyncTestCompleter} from '@angular/core/testing/testing_internal';
|
import {AsyncTestCompleter} from '@angular/core/testing/testing_internal';
|
||||||
import {Observable} from 'rxjs/Observable';
|
import {Observable} from 'rxjs/Observable';
|
||||||
import 'rxjs/add/observable/zip';
|
|
||||||
import {Subject} from 'rxjs/Subject';
|
import {Subject} from 'rxjs/Subject';
|
||||||
import {stringToArrayBuffer} from "../src/http_utils";
|
import {zip} from 'rxjs/observable/zip';
|
||||||
import {Json} from "../src/facade/lang";
|
|
||||||
|
|
||||||
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';
|
import {MockBackend, MockConnection} from '../testing/mock_backend';
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
|
@ -388,116 +388,114 @@ export function main() {
|
||||||
it('should attach the provided buffer to the response',
|
it('should attach the provided buffer to the response',
|
||||||
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
||||||
backend.connections.subscribe((c: MockConnection) => {
|
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)})));
|
c.mockRespond(new Response(new ResponseOptions({body: new ArrayBuffer(32)})));
|
||||||
async.done();
|
async.done();
|
||||||
});
|
});
|
||||||
http.get('https://www.google.com',
|
http.get(
|
||||||
new RequestOptions({buffer: ResponseBuffer.ArrayBuffer}))
|
'https://www.google.com',
|
||||||
|
new RequestOptions({responseType: ResponseContentType.ArrayBuffer}))
|
||||||
.subscribe((res: Response) => {});
|
.subscribe((res: Response) => {});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should be able to consume a buffer containing a String as any response type',
|
it('should be able to consume a buffer containing a String as any response type',
|
||||||
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
||||||
backend.connections.subscribe((c: MockConnection) => c.mockRespond(baseResponse));
|
backend.connections.subscribe((c: MockConnection) => c.mockRespond(baseResponse));
|
||||||
http.get('https://www.google.com')
|
http.get('https://www.google.com').subscribe((res: Response) => {
|
||||||
.subscribe((res: Response) => {
|
expect(res.arrayBuffer()).toBeAnInstanceOf(ArrayBuffer);
|
||||||
expect(res.arrayBuffer()).toBeAnInstanceOf(ArrayBuffer);
|
expect(res.text()).toBe('base response');
|
||||||
expect(res.text()).toBe("base response");
|
async.done();
|
||||||
async.done();
|
});
|
||||||
});
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
it('should be able to consume a buffer containing an ArrayBuffer as any response type',
|
it('should be able to consume a buffer containing an ArrayBuffer as any response type',
|
||||||
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
||||||
let arrayBuffer = stringToArrayBuffer('{"response": "ok"}');
|
let arrayBuffer = stringToArrayBuffer('{"response": "ok"}');
|
||||||
backend.connections.subscribe((c: MockConnection) => c.mockRespond(new Response(
|
backend.connections.subscribe(
|
||||||
new ResponseOptions({body: arrayBuffer}))));
|
(c: MockConnection) =>
|
||||||
http.get('https://www.google.com')
|
c.mockRespond(new Response(new ResponseOptions({body: arrayBuffer}))));
|
||||||
.subscribe((res: Response) => {
|
http.get('https://www.google.com').subscribe((res: Response) => {
|
||||||
expect(res.arrayBuffer()).toBe(arrayBuffer);
|
expect(res.arrayBuffer()).toBe(arrayBuffer);
|
||||||
expect(res.text()).toEqual('{"response": "ok"}');
|
expect(res.text()).toEqual('{"response": "ok"}');
|
||||||
expect(res.json()).toEqual({response: "ok"});
|
expect(res.json()).toEqual({response: 'ok'});
|
||||||
async.done();
|
async.done();
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should be able to consume a buffer containing an Object as any response type',
|
it('should be able to consume a buffer containing an Object as any response type',
|
||||||
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
||||||
let simpleObject = {"content": "ok"};
|
let simpleObject = {'content': 'ok'};
|
||||||
backend.connections.subscribe((c: MockConnection) => c.mockRespond(new Response(
|
backend.connections.subscribe(
|
||||||
new ResponseOptions({body: simpleObject}))));
|
(c: MockConnection) =>
|
||||||
http.get('https://www.google.com')
|
c.mockRespond(new Response(new ResponseOptions({body: simpleObject}))));
|
||||||
.subscribe((res: Response) => {
|
http.get('https://www.google.com').subscribe((res: Response) => {
|
||||||
expect(res.arrayBuffer()).toBeAnInstanceOf(ArrayBuffer);
|
expect(res.arrayBuffer()).toBeAnInstanceOf(ArrayBuffer);
|
||||||
expect(res.text()).toEqual(Json.stringify(simpleObject));
|
expect(res.text()).toEqual(Json.stringify(simpleObject));
|
||||||
expect(res.json()).toBe(simpleObject);
|
expect(res.json()).toBe(simpleObject);
|
||||||
async.done();
|
async.done();
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should preserve encoding of ArrayBuffer response',
|
it('should preserve encoding of ArrayBuffer response',
|
||||||
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
||||||
let message = "é@θЂ";
|
let message = 'é@θЂ';
|
||||||
let arrayBuffer = stringToArrayBuffer(message);
|
let arrayBuffer = stringToArrayBuffer(message);
|
||||||
backend.connections.subscribe((c: MockConnection) => c.mockRespond(new Response(
|
backend.connections.subscribe(
|
||||||
new ResponseOptions({body: arrayBuffer}))));
|
(c: MockConnection) =>
|
||||||
http.get('https://www.google.com')
|
c.mockRespond(new Response(new ResponseOptions({body: arrayBuffer}))));
|
||||||
.subscribe((res: Response) => {
|
http.get('https://www.google.com').subscribe((res: Response) => {
|
||||||
expect(res.arrayBuffer()).toBeAnInstanceOf(ArrayBuffer);
|
expect(res.arrayBuffer()).toBeAnInstanceOf(ArrayBuffer);
|
||||||
expect(res.text()).toEqual(message);
|
expect(res.text()).toEqual(message);
|
||||||
async.done();
|
async.done();
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should preserve encoding of String response',
|
it('should preserve encoding of String response',
|
||||||
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
||||||
let message = "é@θЂ";
|
let message = 'é@θЂ';
|
||||||
backend.connections.subscribe((c: MockConnection) => c.mockRespond(
|
backend.connections.subscribe(
|
||||||
new Response(new ResponseOptions({body: message}))));
|
(c: MockConnection) =>
|
||||||
http.get('https://www.google.com')
|
c.mockRespond(new Response(new ResponseOptions({body: message}))));
|
||||||
.subscribe((res: Response) => {
|
http.get('https://www.google.com').subscribe((res: Response) => {
|
||||||
expect(res.arrayBuffer()).toEqual(stringToArrayBuffer(message));
|
expect(res.arrayBuffer()).toEqual(stringToArrayBuffer(message));
|
||||||
async.done();
|
async.done();
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should have an equivalent response independently of the buffer used',
|
it('should have an equivalent response independently of the buffer used',
|
||||||
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
||||||
let message = {"param": "content"};
|
let message = {'param': 'content'};
|
||||||
|
|
||||||
backend.connections.subscribe((c: MockConnection) => {
|
backend.connections.subscribe((c: MockConnection) => {
|
||||||
let body = (): any => {
|
let body = (): any => {
|
||||||
switch (c.request.buffer) {
|
switch (c.request.responseType) {
|
||||||
case ResponseBuffer.Text:
|
case ResponseContentType.Text:
|
||||||
return Json.stringify(message);
|
return Json.stringify(message);
|
||||||
case ResponseBuffer.Json:
|
case ResponseContentType.Json:
|
||||||
return message;
|
return message;
|
||||||
case ResponseBuffer.ArrayBuffer:
|
case ResponseContentType.ArrayBuffer:
|
||||||
return stringToArrayBuffer(Json.stringify(message));
|
return stringToArrayBuffer(Json.stringify(message));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
c.mockRespond(new Response(new ResponseOptions({body: body()})))
|
c.mockRespond(new Response(new ResponseOptions({body: body()})))
|
||||||
});
|
});
|
||||||
|
|
||||||
Observable.zip(http.get('https://www.google.com',
|
zip(http.get(
|
||||||
new RequestOptions({buffer: ResponseBuffer.Text})),
|
'https://www.google.com',
|
||||||
http.get('https://www.google.com',
|
new RequestOptions({responseType: ResponseContentType.Text})),
|
||||||
new RequestOptions({buffer: ResponseBuffer.Json})),
|
http.get(
|
||||||
http.get('https://www.google.com',
|
'https://www.google.com',
|
||||||
new RequestOptions({buffer: ResponseBuffer.ArrayBuffer})),
|
new RequestOptions({responseType: ResponseContentType.Json})),
|
||||||
(x, y, z) => [x, y, z])
|
http.get(
|
||||||
.subscribe((res: Array<Response>) => {
|
'https://www.google.com',
|
||||||
|
new RequestOptions({responseType: ResponseContentType.ArrayBuffer})))
|
||||||
|
.subscribe((res: Array<any>) => {
|
||||||
expect(res[0].text()).toEqual(res[1].text());
|
expect(res[0].text()).toEqual(res[1].text());
|
||||||
expect(res[1].text()).toEqual(res[2].text());
|
expect(res[1].text()).toEqual(res[2].text());
|
||||||
async.done();
|
async.done();
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,18 +117,15 @@ export declare enum ReadyState {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @experimental */
|
/** @experimental */
|
||||||
export declare class Request {
|
export declare class Request extends Body {
|
||||||
headers: Headers;
|
headers: Headers;
|
||||||
method: RequestMethod;
|
method: RequestMethod;
|
||||||
|
responseType: ResponseContentType;
|
||||||
url: string;
|
url: string;
|
||||||
withCredentials: boolean;
|
withCredentials: boolean;
|
||||||
constructor(requestOptions: RequestArgs);
|
constructor(requestOptions: RequestArgs);
|
||||||
arrayBuffer(): ArrayBuffer;
|
|
||||||
blob(): Blob;
|
|
||||||
detectContentType(): ContentType;
|
detectContentType(): ContentType;
|
||||||
getBody(): any;
|
getBody(): any;
|
||||||
json(): string;
|
|
||||||
text(): string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @experimental */
|
/** @experimental */
|
||||||
|
@ -147,10 +144,11 @@ export declare class RequestOptions {
|
||||||
body: any;
|
body: any;
|
||||||
headers: Headers;
|
headers: Headers;
|
||||||
method: RequestMethod | string;
|
method: RequestMethod | string;
|
||||||
|
responseType: ResponseContentType;
|
||||||
search: URLSearchParams;
|
search: URLSearchParams;
|
||||||
url: string;
|
url: string;
|
||||||
withCredentials: boolean;
|
withCredentials: boolean;
|
||||||
constructor({method, headers, body, url, search, withCredentials}?: RequestOptionsArgs);
|
constructor({method, headers, body, url, search, withCredentials, responseType}?: RequestOptionsArgs);
|
||||||
merge(options?: RequestOptionsArgs): RequestOptions;
|
merge(options?: RequestOptionsArgs): RequestOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,13 +157,14 @@ export interface RequestOptionsArgs {
|
||||||
body?: any;
|
body?: any;
|
||||||
headers?: Headers;
|
headers?: Headers;
|
||||||
method?: string | RequestMethod;
|
method?: string | RequestMethod;
|
||||||
|
responseType?: ResponseContentType;
|
||||||
search?: string | URLSearchParams;
|
search?: string | URLSearchParams;
|
||||||
url?: string;
|
url?: string;
|
||||||
withCredentials?: boolean;
|
withCredentials?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @experimental */
|
/** @experimental */
|
||||||
export declare class Response {
|
export declare class Response extends Body {
|
||||||
bytesLoaded: number;
|
bytesLoaded: number;
|
||||||
headers: Headers;
|
headers: Headers;
|
||||||
ok: boolean;
|
ok: boolean;
|
||||||
|
@ -175,16 +174,19 @@ export declare class Response {
|
||||||
type: ResponseType;
|
type: ResponseType;
|
||||||
url: string;
|
url: string;
|
||||||
constructor(responseOptions: ResponseOptions);
|
constructor(responseOptions: ResponseOptions);
|
||||||
arrayBuffer(): any;
|
|
||||||
blob(): any;
|
|
||||||
json(): any;
|
|
||||||
text(): string;
|
|
||||||
toString(): string;
|
toString(): string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @experimental */
|
||||||
|
export declare enum ResponseContentType {
|
||||||
|
ArrayBuffer = 0,
|
||||||
|
Json = 1,
|
||||||
|
Text = 2,
|
||||||
|
}
|
||||||
|
|
||||||
/** @experimental */
|
/** @experimental */
|
||||||
export declare class ResponseOptions {
|
export declare class ResponseOptions {
|
||||||
body: string | Object;
|
body: string | Object | ArrayBuffer;
|
||||||
headers: Headers;
|
headers: Headers;
|
||||||
status: number;
|
status: number;
|
||||||
url: string;
|
url: string;
|
||||||
|
@ -194,7 +196,7 @@ export declare class ResponseOptions {
|
||||||
|
|
||||||
/** @experimental */
|
/** @experimental */
|
||||||
export declare type ResponseOptionsArgs = {
|
export declare type ResponseOptionsArgs = {
|
||||||
body?: string | Object | FormData;
|
body?: string | Object | FormData | ArrayBuffer;
|
||||||
status?: number;
|
status?: number;
|
||||||
statusText?: string;
|
statusText?: string;
|
||||||
headers?: Headers;
|
headers?: Headers;
|
||||||
|
|
Loading…
Reference in New Issue