refactor(http): remove default settings from `RequestOptions` constructor
The BaseRequestOptions class is responsible for declaring default values, while the RequestOptions class is merely responsible for setting values based on values provided in the constructor.
This commit is contained in:
parent
146dbf1270
commit
b3d98cba77
|
@ -17,5 +17,6 @@ export * from './src/core/compiler/dynamic_component_loader';
|
|||
export {ViewRef, ProtoViewRef} from './src/core/compiler/view_ref';
|
||||
export {ViewContainerRef} from './src/core/compiler/view_container_ref';
|
||||
export {ElementRef} from './src/core/compiler/element_ref';
|
||||
export {EventEmitter} from './src/facade/async';
|
||||
|
||||
export {NgZone} from './src/core/zone/ng_zone';
|
|
@ -6,30 +6,39 @@
|
|||
* class.
|
||||
*/
|
||||
import {bind, Binding} from 'angular2/di';
|
||||
import {Http} from './src/http/http';
|
||||
import {Http} from 'angular2/src/http/http';
|
||||
import {XHRBackend, XHRConnection} from 'angular2/src/http/backends/xhr_backend';
|
||||
import {BrowserXHR} from 'angular2/src/http/backends/browser_xhr';
|
||||
import {BrowserXhr} from 'angular2/src/http/backends/browser_xhr';
|
||||
import {BaseRequestOptions, RequestOptions} from 'angular2/src/http/base_request_options';
|
||||
import {ConnectionBackend} from 'angular2/src/http/interfaces';
|
||||
|
||||
export {MockConnection, MockBackend} from 'angular2/src/http/backends/mock_backend';
|
||||
export {Request} from 'angular2/src/http/static_request';
|
||||
export {Response} from 'angular2/src/http/static_response';
|
||||
import {BaseResponseOptions, ResponseOptions} from 'angular2/src/http/base_response_options';
|
||||
|
||||
export {
|
||||
IRequestOptions,
|
||||
IResponse,
|
||||
IResponseOptions,
|
||||
Connection,
|
||||
ConnectionBackend
|
||||
} from 'angular2/src/http/interfaces';
|
||||
|
||||
export {BaseRequestOptions, RequestOptions} from 'angular2/src/http/base_request_options';
|
||||
export {BaseResponseOptions, ResponseOptions} from 'angular2/src/http/base_response_options';
|
||||
export {XHRBackend, XHRConnection} from 'angular2/src/http/backends/xhr_backend';
|
||||
export {Http} from './src/http/http';
|
||||
export {Http} from 'angular2/src/http/http';
|
||||
|
||||
export {Headers} from 'angular2/src/http/headers';
|
||||
|
||||
export * from 'angular2/src/http/enums';
|
||||
export {
|
||||
ResponseTypes,
|
||||
ReadyStates,
|
||||
RequestMethods,
|
||||
RequestCredentialsOpts,
|
||||
RequestCacheOpts,
|
||||
RequestModesOpts
|
||||
} from 'angular2/src/http/enums';
|
||||
export {URLSearchParams} from 'angular2/src/http/url_search_params';
|
||||
|
||||
/**
|
||||
|
@ -49,5 +58,11 @@ export {URLSearchParams} from 'angular2/src/http/url_search_params';
|
|||
* ```
|
||||
*
|
||||
*/
|
||||
export var httpInjectables: List<any> =
|
||||
[bind(ConnectionBackend).toClass(XHRBackend), BrowserXHR, XHRBackend, BaseRequestOptions, Http];
|
||||
export var httpInjectables: List<any> = [
|
||||
bind(ConnectionBackend)
|
||||
.toClass(XHRBackend),
|
||||
BrowserXhr,
|
||||
bind(RequestOptions).toClass(BaseRequestOptions),
|
||||
bind(ResponseOptions).toClass(BaseResponseOptions),
|
||||
Http
|
||||
];
|
||||
|
|
|
@ -4,7 +4,7 @@ import 'dart:html' show HttpRequest;
|
|||
import 'package:angular2/di.dart';
|
||||
|
||||
@Injectable()
|
||||
class BrowserXHR {
|
||||
class BrowserXhr {
|
||||
HttpRequest build() {
|
||||
return new HttpRequest();
|
||||
}
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
declare var window;
|
||||
|
||||
import {Injectable} from 'angular2/di';
|
||||
|
||||
// Make sure not to evaluate this in a non-browser environment!
|
||||
@Injectable()
|
||||
export class BrowserXHR {
|
||||
export class BrowserXhr {
|
||||
constructor() {}
|
||||
build(): any { return <any>(new window.XMLHttpRequest()); }
|
||||
build(): any { return <any>(new XMLHttpRequest()); }
|
||||
}
|
||||
|
|
|
@ -9,11 +9,7 @@ import {IMPLEMENTS, BaseException} from 'angular2/src/facade/lang';
|
|||
|
||||
/**
|
||||
*
|
||||
* Connection class used by MockBackend
|
||||
*
|
||||
* This class is typically not instantiated directly, but instances can be retrieved by subscribing
|
||||
*to the `connections` Observable of
|
||||
* {@link MockBackend} in order to mock responses to requests.
|
||||
* Mock Connection to represent a {@link Connection} for tests.
|
||||
*
|
||||
**/
|
||||
@IMPLEMENTS(Connection)
|
||||
|
@ -32,9 +28,8 @@ export class MockConnection {
|
|||
request: Request;
|
||||
|
||||
/**
|
||||
* [RxJS
|
||||
* Observable](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/observable.md)
|
||||
* of {@link Response}. Can be subscribed to in order to be notified when a response is available.
|
||||
* {@link EventEmitter} of {@link Response}. Can be subscribed to in order to be notified when a
|
||||
* response is available.
|
||||
*/
|
||||
response: EventEmitter;
|
||||
|
||||
|
@ -55,7 +50,7 @@ export class MockConnection {
|
|||
|
||||
/**
|
||||
* Sends a mock response to the connection. This response is the value that is emitted to the
|
||||
* `Observable` returned by {@link Http}.
|
||||
* {@link EventEmitter} returned by {@link Http}.
|
||||
*
|
||||
* #Example
|
||||
*
|
||||
|
@ -91,7 +86,8 @@ export class MockConnection {
|
|||
|
||||
// TODO(jeffbcross): consider using Response type
|
||||
/**
|
||||
* Emits the provided error object as an error to the {@link Response} observable returned
|
||||
* Emits the provided error object as an error to the {@link Response} {@link EventEmitter}
|
||||
* returned
|
||||
* from {@link Http}.
|
||||
*/
|
||||
mockError(err?) {
|
||||
|
@ -137,8 +133,7 @@ export class MockConnection {
|
|||
@IMPLEMENTS(ConnectionBackend)
|
||||
export class MockBackend {
|
||||
/**
|
||||
* [RxJS
|
||||
* Subject](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/subjects/subject.md)
|
||||
* {@link EventEmitter}
|
||||
* of {@link MockConnection} instances that have been created by this backend. Can be subscribed
|
||||
* to in order to respond to connections.
|
||||
*
|
||||
|
@ -162,7 +157,7 @@ export class MockBackend {
|
|||
* http.request('something.json').subscribe(res => {
|
||||
* text = res.text();
|
||||
* });
|
||||
* connection.mockRespond(new Response('Something'));
|
||||
* connection.mockRespond(new Response({body: 'Something'}));
|
||||
* expect(text).toBe('Something');
|
||||
* });
|
||||
* ```
|
||||
|
@ -179,8 +174,8 @@ export class MockBackend {
|
|||
*/
|
||||
connectionsArray: Array<MockConnection>;
|
||||
/**
|
||||
* [Observable](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/observable.md)
|
||||
* of {@link MockConnection} instances that haven't yet been resolved (i.e. with a `readyState`
|
||||
* {@link EventEmitter} of {@link MockConnection} instances that haven't yet been resolved (i.e.
|
||||
* with a `readyState`
|
||||
* less than 4). Used internally to verify that no connections are pending via the
|
||||
* `verifyNoPendingRequests` method.
|
||||
*
|
||||
|
@ -193,7 +188,6 @@ export class MockBackend {
|
|||
ObservableWrapper.subscribe(this.connections,
|
||||
connection => this.connectionsArray.push(connection));
|
||||
this.pendingConnections = new EventEmitter();
|
||||
// Observable.fromArray(this.connectionsArray).filter((c) => c.readyState < ReadyStates.DONE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -218,10 +212,10 @@ export class MockBackend {
|
|||
/**
|
||||
* Creates a new {@link MockConnection}. This is equivalent to calling `new
|
||||
* MockConnection()`, except that it also will emit the new `Connection` to the `connections`
|
||||
* observable of this `MockBackend` instance. This method will usually only be used by tests
|
||||
* emitter of this `MockBackend` instance. This method will usually only be used by tests
|
||||
* against the framework itself, not by end-users.
|
||||
*/
|
||||
createConnection(req: Request) {
|
||||
createConnection(req: Request): Connection {
|
||||
if (!isPresent(req) || !(req instanceof Request)) {
|
||||
throw new BaseException(`createConnection requires an instance of Request, got ${req}`);
|
||||
}
|
||||
|
|
|
@ -2,8 +2,9 @@ import {ConnectionBackend, Connection} from '../interfaces';
|
|||
import {ReadyStates, RequestMethods, RequestMethodsMap} from '../enums';
|
||||
import {Request} from '../static_request';
|
||||
import {Response} from '../static_response';
|
||||
import {ResponseOptions, BaseResponseOptions} from '../base_response_options';
|
||||
import {Injectable} from 'angular2/di';
|
||||
import {BrowserXHR} from './browser_xhr';
|
||||
import {BrowserXhr} from './browser_xhr';
|
||||
import {EventEmitter, ObservableWrapper} from 'angular2/src/facade/async';
|
||||
import {isPresent, ENUM_INDEX} from 'angular2/src/facade/lang';
|
||||
|
||||
|
@ -18,14 +19,14 @@ import {isPresent, ENUM_INDEX} from 'angular2/src/facade/lang';
|
|||
export class XHRConnection implements Connection {
|
||||
request: Request;
|
||||
/**
|
||||
* Response
|
||||
* [Subject](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/subjects/subject.md)
|
||||
* which emits a single {@link Response} value on load event of `XMLHttpRequest`.
|
||||
* Response {@link EventEmitter} which emits a single {@link Response} value on load event of
|
||||
* `XMLHttpRequest`.
|
||||
*/
|
||||
response: EventEmitter; //<Response>;
|
||||
response: EventEmitter; // TODO: Make generic of <Response>;
|
||||
readyState: ReadyStates;
|
||||
private _xhr;
|
||||
constructor(req: Request, browserXHR: BrowserXHR) {
|
||||
private _xhr; // TODO: make type XMLHttpRequest, pending resolution of
|
||||
// https://github.com/angular/ts2dart/issues/230
|
||||
constructor(req: Request, browserXHR: BrowserXhr, baseResponseOptions?: ResponseOptions) {
|
||||
// TODO: get rid of this when enum lookups are available in ts2dart
|
||||
// https://github.com/angular/ts2dart/issues/221
|
||||
var requestMethodsMap = new RequestMethodsMap();
|
||||
|
@ -34,12 +35,15 @@ export class XHRConnection implements Connection {
|
|||
this._xhr = browserXHR.build();
|
||||
// TODO(jeffbcross): implement error listening/propagation
|
||||
this._xhr.open(requestMethodsMap.getMethod(ENUM_INDEX(req.method)), req.url);
|
||||
this._xhr.addEventListener(
|
||||
'load',
|
||||
(_) => {ObservableWrapper.callNext(
|
||||
this.response, new Response({
|
||||
body: isPresent(this._xhr.response) ? this._xhr.response : this._xhr.responseText
|
||||
}))});
|
||||
this._xhr.addEventListener('load', (_) => {
|
||||
var responseOptions = new ResponseOptions(
|
||||
{body: isPresent(this._xhr.response) ? this._xhr.response : this._xhr.responseText});
|
||||
if (isPresent(baseResponseOptions)) {
|
||||
responseOptions = baseResponseOptions.merge(responseOptions);
|
||||
}
|
||||
|
||||
ObservableWrapper.callNext(this.response, new Response(responseOptions))
|
||||
});
|
||||
// TODO(jeffbcross): make this more dynamic based on body type
|
||||
this._xhr.send(this.request.text());
|
||||
}
|
||||
|
@ -78,8 +82,8 @@ export class XHRConnection implements Connection {
|
|||
**/
|
||||
@Injectable()
|
||||
export class XHRBackend implements ConnectionBackend {
|
||||
constructor(private _browserXHR: BrowserXHR) {}
|
||||
constructor(private _browserXHR: BrowserXhr, private _baseResponseOptions: ResponseOptions) {}
|
||||
createConnection(request: Request): XHRConnection {
|
||||
return new XHRConnection(request, this._browserXHR);
|
||||
return new XHRConnection(request, this._browserXHR, this._baseResponseOptions);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,15 +3,14 @@ import {Headers} from './headers';
|
|||
import {RequestModesOpts, RequestMethods, RequestCacheOpts, RequestCredentialsOpts} from './enums';
|
||||
import {IRequestOptions} from './interfaces';
|
||||
import {Injectable} from 'angular2/di';
|
||||
import {ListWrapper, StringMapWrapper, StringMap} from 'angular2/src/facade/collection';
|
||||
|
||||
const INITIALIZER = CONST_EXPR({});
|
||||
/**
|
||||
* Creates a request options object with default properties as described in the [Fetch
|
||||
* Creates a request options object similar to the `RequestInit` description
|
||||
* in the [Fetch
|
||||
* Spec](https://fetch.spec.whatwg.org/#requestinit) to be optionally provided when instantiating a
|
||||
* {@link Request}. This class is used implicitly by {@link Http} to merge in provided request
|
||||
* options with the default options specified here. These same default options are injectable via
|
||||
* the {@link BaseRequestOptions} class.
|
||||
* {@link Request}.
|
||||
*
|
||||
* All values are null by default.
|
||||
*/
|
||||
export class RequestOptions implements IRequestOptions {
|
||||
/**
|
||||
|
@ -19,7 +18,7 @@ export class RequestOptions implements IRequestOptions {
|
|||
*
|
||||
* Defaults to "GET".
|
||||
*/
|
||||
method: RequestMethods = RequestMethods.GET;
|
||||
method: RequestMethods;
|
||||
/**
|
||||
* Headers object based on the `Headers` class in the [Fetch
|
||||
* Spec](https://fetch.spec.whatwg.org/#headers-class).
|
||||
|
@ -28,54 +27,42 @@ export class RequestOptions implements IRequestOptions {
|
|||
/**
|
||||
* Body to be used when creating the request.
|
||||
*/
|
||||
// TODO: support FormData, Blob, URLSearchParams, JSON
|
||||
// TODO: support FormData, Blob, URLSearchParams
|
||||
body: string;
|
||||
mode: RequestModesOpts = RequestModesOpts.Cors;
|
||||
mode: RequestModesOpts;
|
||||
credentials: RequestCredentialsOpts;
|
||||
cache: RequestCacheOpts;
|
||||
url: string;
|
||||
constructor({method, headers, body, mode, credentials, cache, url}: IRequestOptions = {}) {
|
||||
this.method = isPresent(method) ? method : RequestMethods.GET;
|
||||
this.headers = headers;
|
||||
this.body = body;
|
||||
this.mode = isPresent(mode) ? mode : RequestModesOpts.Cors;
|
||||
this.credentials = credentials;
|
||||
this.cache = cache;
|
||||
this.url = url;
|
||||
this.method = isPresent(method) ? method : null;
|
||||
this.headers = isPresent(headers) ? headers : null;
|
||||
this.body = isPresent(body) ? body : null;
|
||||
this.mode = isPresent(mode) ? mode : null;
|
||||
this.credentials = isPresent(credentials) ? credentials : null;
|
||||
this.cache = isPresent(cache) ? cache : null;
|
||||
this.url = isPresent(url) ? url : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a copy of the `RequestOptions` instance, using the optional input as values to override
|
||||
* existing values.
|
||||
*/
|
||||
merge({url = null, method = null, headers = null, body = null, mode = null, credentials = null,
|
||||
cache = null}: any = {}): RequestOptions {
|
||||
merge(options?: IRequestOptions): RequestOptions {
|
||||
return new RequestOptions({
|
||||
method: isPresent(method) ? method : this.method,
|
||||
headers: isPresent(headers) ? headers : this.headers,
|
||||
body: isPresent(body) ? body : this.body,
|
||||
mode: isPresent(mode) ? mode : this.mode,
|
||||
credentials: isPresent(credentials) ? credentials : this.credentials,
|
||||
cache: isPresent(cache) ? cache : this.cache,
|
||||
url: isPresent(url) ? url : this.url
|
||||
method: isPresent(options) && isPresent(options.method) ? options.method : this.method,
|
||||
headers: isPresent(options) && isPresent(options.headers) ? options.headers : this.headers,
|
||||
body: isPresent(options) && isPresent(options.body) ? options.body : this.body,
|
||||
mode: isPresent(options) && isPresent(options.mode) ? options.mode : this.mode,
|
||||
credentials: isPresent(options) && isPresent(options.credentials) ? options.credentials :
|
||||
this.credentials,
|
||||
cache: isPresent(options) && isPresent(options.cache) ? options.cache : this.cache,
|
||||
url: isPresent(options) && isPresent(options.url) ? options.url : this.url
|
||||
});
|
||||
}
|
||||
|
||||
static fromStringWrapper(map: StringMap<string, any>): RequestOptions {
|
||||
return new RequestOptions({
|
||||
method: StringMapWrapper.get(map, 'method'),
|
||||
headers: StringMapWrapper.get(map, 'headers'),
|
||||
body: StringMapWrapper.get(map, 'body'),
|
||||
mode: StringMapWrapper.get(map, 'mode'),
|
||||
credentials: StringMapWrapper.get(map, 'credentials'),
|
||||
cache: StringMapWrapper.get(map, 'cache'),
|
||||
url:<string>StringMapWrapper.get(map, 'url')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injectable version of {@link RequestOptions}.
|
||||
* Injectable version of {@link RequestOptions}, with overridable default values.
|
||||
*
|
||||
* #Example
|
||||
*
|
||||
|
@ -84,8 +71,8 @@ export class RequestOptions implements IRequestOptions {
|
|||
* ...
|
||||
* class MyComponent {
|
||||
* constructor(baseRequestOptions:BaseRequestOptions, http:Http) {
|
||||
* var options = baseRequestOptions.merge({body: 'foobar'});
|
||||
* var request = new Request('https://foo', options);
|
||||
* var options = baseRequestOptions.merge({body: 'foobar', url: 'https://foo'});
|
||||
* var request = new Request(options);
|
||||
* http.request(request).subscribe(res => this.bars = res.json());
|
||||
* }
|
||||
* }
|
||||
|
@ -94,5 +81,7 @@ export class RequestOptions implements IRequestOptions {
|
|||
*/
|
||||
@Injectable()
|
||||
export class BaseRequestOptions extends RequestOptions {
|
||||
constructor() { super(); }
|
||||
constructor() {
|
||||
super({method: RequestMethods.GET, headers: new Headers(), mode: RequestModesOpts.Cors});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,54 @@
|
|||
import {Injectable} from 'angular2/di';
|
||||
import {isPresent, isJsObject} from 'angular2/src/facade/lang';
|
||||
import {Headers} from './headers';
|
||||
import {ResponseTypes} from './enums';
|
||||
import {ResponseOptions} from './interfaces';
|
||||
import {IResponseOptions} from './interfaces';
|
||||
|
||||
export class BaseResponseOptions implements ResponseOptions {
|
||||
/**
|
||||
* Creates a response options object similar to the
|
||||
* [ResponseInit](https://fetch.spec.whatwg.org/#responseinit) description
|
||||
* in the Fetch
|
||||
* Spec to be optionally provided when instantiating a
|
||||
* {@link Response}.
|
||||
*
|
||||
* All values are null by default.
|
||||
*/
|
||||
export class ResponseOptions implements IResponseOptions {
|
||||
// TODO: ArrayBuffer | FormData | Blob
|
||||
body: string | Object;
|
||||
status: number;
|
||||
headers: Headers;
|
||||
statusText: string;
|
||||
type: ResponseTypes;
|
||||
url: string;
|
||||
constructor({body, status, headers, statusText, type, url}: IResponseOptions = {}) {
|
||||
this.body = isPresent(body) ? body : null;
|
||||
this.status = isPresent(status) ? status : null;
|
||||
this.headers = isPresent(headers) ? headers : null;
|
||||
this.statusText = isPresent(statusText) ? statusText : null;
|
||||
this.type = isPresent(type) ? type : null;
|
||||
this.url = isPresent(url) ? url : null;
|
||||
}
|
||||
|
||||
merge(options?: IResponseOptions): ResponseOptions {
|
||||
return new ResponseOptions({
|
||||
body: isPresent(options) && isPresent(options.body) ? options.body : this.body,
|
||||
status: isPresent(options) && isPresent(options.status) ? options.status : this.status,
|
||||
headers: isPresent(options) && isPresent(options.headers) ? options.headers : this.headers,
|
||||
statusText: isPresent(options) && isPresent(options.statusText) ? options.statusText :
|
||||
this.statusText,
|
||||
type: isPresent(options) && isPresent(options.type) ? options.type : this.type,
|
||||
url: isPresent(options) && isPresent(options.url) ? options.url : this.url,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injectable version of {@link ResponseOptions}, with overridable default values.
|
||||
*/
|
||||
@Injectable()
|
||||
export class BaseResponseOptions extends ResponseOptions {
|
||||
// TODO: Object | ArrayBuffer | JSON | FormData | Blob
|
||||
body: string | Object | ArrayBuffer | JSON | FormData | Blob;
|
||||
status: number;
|
||||
headers: Headers;
|
||||
|
@ -11,11 +57,6 @@ export class BaseResponseOptions implements ResponseOptions {
|
|||
url: string;
|
||||
|
||||
constructor() {
|
||||
this.status = 200;
|
||||
this.statusText = 'Ok';
|
||||
this.type = ResponseTypes.Default;
|
||||
this.headers = new Headers();
|
||||
super({status: 200, statusText: 'Ok', type: ResponseTypes.Default, headers: new Headers()});
|
||||
}
|
||||
}
|
||||
|
||||
export var baseResponseOptions = new BaseResponseOptions();
|
||||
|
|
|
@ -1,11 +1,19 @@
|
|||
import {StringMap, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||
|
||||
/**
|
||||
* Acceptable origin modes to be associated with a {@link Request}, based on
|
||||
* [RequestMode](https://fetch.spec.whatwg.org/#requestmode) from the Fetch spec.
|
||||
*/
|
||||
export enum RequestModesOpts {
|
||||
Cors,
|
||||
NoCors,
|
||||
SameOrigin
|
||||
}
|
||||
|
||||
/**
|
||||
* Acceptable cache option to be associated with a {@link Request}, based on
|
||||
* [RequestCache](https://fetch.spec.whatwg.org/#requestcache) from the Fetch spec.
|
||||
*/
|
||||
export enum RequestCacheOpts {
|
||||
Default,
|
||||
NoStore,
|
||||
|
@ -15,12 +23,19 @@ export enum RequestCacheOpts {
|
|||
OnlyIfCached
|
||||
}
|
||||
|
||||
/**
|
||||
* Acceptable credentials option to be associated with a {@link Request}, based on
|
||||
* [RequestCredentials](https://fetch.spec.whatwg.org/#requestcredentials) from the Fetch spec.
|
||||
*/
|
||||
export enum RequestCredentialsOpts {
|
||||
Omit,
|
||||
SameOrigin,
|
||||
Include
|
||||
}
|
||||
|
||||
/**
|
||||
* Supported http methods.
|
||||
*/
|
||||
export enum RequestMethods {
|
||||
GET,
|
||||
POST,
|
||||
|
@ -38,7 +53,11 @@ export class RequestMethodsMap {
|
|||
constructor() { this._methods = ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD', 'PATCH']; }
|
||||
getMethod(method: int): string { return this._methods[method]; }
|
||||
}
|
||||
|
||||
/**
|
||||
* All possible states in which a connection can be, based on
|
||||
* [States](http://www.w3.org/TR/XMLHttpRequest/#states) from the `XMLHttpRequest` spec, but with an
|
||||
* additional "CANCELLED" state.
|
||||
*/
|
||||
export enum ReadyStates {
|
||||
UNSENT,
|
||||
OPEN,
|
||||
|
@ -48,6 +67,10 @@ export enum ReadyStates {
|
|||
CANCELLED
|
||||
}
|
||||
|
||||
/**
|
||||
* Acceptable response types to be associated with a {@link Response}, based on
|
||||
* [ResponseType](https://fetch.spec.whatwg.org/#responsetype) from the Fetch spec.
|
||||
*/
|
||||
export enum ResponseTypes {
|
||||
Basic,
|
||||
Cors,
|
||||
|
|
|
@ -42,6 +42,9 @@ export class Headers {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a header to existing list of header values for a given header name.
|
||||
*/
|
||||
append(name: string, value: string): void {
|
||||
var mapName = this._headersMap.get(name);
|
||||
var list = isListLikeIterable(mapName) ? mapName : [];
|
||||
|
@ -49,26 +52,36 @@ export class Headers {
|
|||
this._headersMap.set(name, list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all header values for the given name.
|
||||
*/
|
||||
delete (name: string): void { MapWrapper.delete(this._headersMap, name); }
|
||||
|
||||
forEach(fn: Function) { MapWrapper.forEach(this._headersMap, fn); }
|
||||
|
||||
/**
|
||||
* Returns first header that matches given name.
|
||||
*/
|
||||
get(header: string): string { return ListWrapper.first(this._headersMap.get(header)); }
|
||||
|
||||
/**
|
||||
* Check for existence of header by given name.
|
||||
*/
|
||||
has(header: string): boolean { return this._headersMap.has(header); }
|
||||
|
||||
/**
|
||||
* Provides names of set headers
|
||||
*/
|
||||
keys(): List<string> { return MapWrapper.keys(this._headersMap); }
|
||||
|
||||
/**
|
||||
* Sets or overrides header value for given name.
|
||||
*/
|
||||
set(header: string, value: string | List<string>): void {
|
||||
var list = [];
|
||||
var isDart = false;
|
||||
// Dart hack
|
||||
if (list.toString().length === 2) {
|
||||
isDart = true;
|
||||
}
|
||||
|
||||
if (isListLikeIterable(value)) {
|
||||
var pushValue = (<List<string>>value).toString();
|
||||
if (isDart) pushValue = pushValue.substring(1, pushValue.length - 1);
|
||||
var pushValue = (<List<string>>value).join(',');
|
||||
list.push(pushValue);
|
||||
} else {
|
||||
list.push(value);
|
||||
|
@ -77,12 +90,21 @@ export class Headers {
|
|||
this._headersMap.set(header, list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns values of all headers.
|
||||
*/
|
||||
values(): List<List<string>> { return MapWrapper.values(this._headersMap); }
|
||||
|
||||
/**
|
||||
* Returns list of header values for a given name.
|
||||
*/
|
||||
getAll(header: string): Array<string> {
|
||||
var headers = this._headersMap.get(header);
|
||||
return isListLikeIterable(headers) ? headers : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is not implemented.
|
||||
*/
|
||||
entries() { throw new BaseException('"entries" method is not implemented on Headers class'); }
|
||||
}
|
||||
|
|
|
@ -13,12 +13,21 @@ function httpRequest(backend: ConnectionBackend, request: Request): EventEmitter
|
|||
function mergeOptions(defaultOpts, providedOpts, method, url): RequestOptions {
|
||||
var newOptions = defaultOpts;
|
||||
if (isPresent(providedOpts)) {
|
||||
newOptions = newOptions.merge(providedOpts);
|
||||
// Hack so Dart can used named parameters
|
||||
newOptions = newOptions.merge(new RequestOptions({
|
||||
method: providedOpts.method,
|
||||
url: providedOpts.url,
|
||||
headers: providedOpts.headers,
|
||||
body: providedOpts.body,
|
||||
mode: providedOpts.mode,
|
||||
credentials: providedOpts.credentials,
|
||||
cache: providedOpts.cache
|
||||
}));
|
||||
}
|
||||
if (isPresent(method)) {
|
||||
return newOptions.merge({method: method, url: url});
|
||||
return newOptions.merge(new RequestOptions({method: method, url: url}));
|
||||
} else {
|
||||
return newOptions.merge({url: url});
|
||||
return newOptions.merge(new RequestOptions({url: url}));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,9 +35,8 @@ function mergeOptions(defaultOpts, providedOpts, method, url): RequestOptions {
|
|||
* Performs http requests using `XMLHttpRequest` as the default backend.
|
||||
*
|
||||
* `Http` is available as an injectable class, with methods to perform http requests. Calling
|
||||
* `request` returns an
|
||||
* [Observable](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/observable.md),
|
||||
* which will emit a single {@link Response} when a response is
|
||||
* `request` returns an {@link EventEmitter} which will emit a single {@link Response} when a
|
||||
*response is
|
||||
* received.
|
||||
*
|
||||
* #Example
|
||||
|
@ -73,7 +81,7 @@ function mergeOptions(defaultOpts, providedOpts, method, url): RequestOptions {
|
|||
**/
|
||||
@Injectable()
|
||||
export class Http {
|
||||
constructor(private _backend: ConnectionBackend, private _defaultOptions: BaseRequestOptions) {}
|
||||
constructor(private _backend: ConnectionBackend, private _defaultOptions: RequestOptions) {}
|
||||
|
||||
/**
|
||||
* Performs any type of http request. First argument is required, and can either be a url or
|
||||
|
@ -96,7 +104,7 @@ export class Http {
|
|||
/**
|
||||
* Performs a request with `get` http method.
|
||||
*/
|
||||
get(url: string, options?: IRequestOptions) {
|
||||
get(url: string, options?: IRequestOptions): EventEmitter {
|
||||
return httpRequest(this._backend, new Request(mergeOptions(this._defaultOptions, options,
|
||||
RequestMethods.GET, url)));
|
||||
}
|
||||
|
@ -104,25 +112,27 @@ export class Http {
|
|||
/**
|
||||
* Performs a request with `post` http method.
|
||||
*/
|
||||
post(url: string, body: string, options?: IRequestOptions) {
|
||||
return httpRequest(this._backend,
|
||||
new Request(mergeOptions(this._defaultOptions.merge({body: body}), options,
|
||||
RequestMethods.POST, url)));
|
||||
post(url: string, body: string, options?: IRequestOptions): EventEmitter {
|
||||
return httpRequest(
|
||||
this._backend,
|
||||
new Request(mergeOptions(this._defaultOptions.merge(new RequestOptions({body: body})),
|
||||
options, RequestMethods.POST, url)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a request with `put` http method.
|
||||
*/
|
||||
put(url: string, body: string, options?: IRequestOptions) {
|
||||
return httpRequest(this._backend,
|
||||
new Request(mergeOptions(this._defaultOptions.merge({body: body}), options,
|
||||
RequestMethods.PUT, url)));
|
||||
put(url: string, body: string, options?: IRequestOptions): EventEmitter {
|
||||
return httpRequest(
|
||||
this._backend,
|
||||
new Request(mergeOptions(this._defaultOptions.merge(new RequestOptions({body: body})),
|
||||
options, RequestMethods.PUT, url)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a request with `delete` http method.
|
||||
*/
|
||||
delete (url: string, options?: IRequestOptions) {
|
||||
delete (url: string, options?: IRequestOptions): EventEmitter {
|
||||
return httpRequest(this._backend, new Request(mergeOptions(this._defaultOptions, options,
|
||||
RequestMethods.DELETE, url)));
|
||||
}
|
||||
|
@ -130,16 +140,17 @@ export class Http {
|
|||
/**
|
||||
* Performs a request with `patch` http method.
|
||||
*/
|
||||
patch(url: string, body: string, options?: IRequestOptions) {
|
||||
return httpRequest(this._backend,
|
||||
new Request(mergeOptions(this._defaultOptions.merge({body: body}), options,
|
||||
RequestMethods.PATCH, url)));
|
||||
patch(url: string, body: string, options?: IRequestOptions): EventEmitter {
|
||||
return httpRequest(
|
||||
this._backend,
|
||||
new Request(mergeOptions(this._defaultOptions.merge(new RequestOptions({body: body})),
|
||||
options, RequestMethods.PATCH, url)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a request with `head` http method.
|
||||
*/
|
||||
head(url: string, options?: IRequestOptions) {
|
||||
head(url: string, options?: IRequestOptions): EventEmitter {
|
||||
return httpRequest(this._backend, new Request(mergeOptions(this._defaultOptions, options,
|
||||
RequestMethods.HEAD, url)));
|
||||
}
|
||||
|
|
|
@ -13,18 +13,31 @@ import {BaseException} from 'angular2/src/facade/lang';
|
|||
import {EventEmitter} from 'angular2/src/facade/async';
|
||||
import {Request} from './static_request';
|
||||
|
||||
/**
|
||||
* Abstract class from which real backends are derived.
|
||||
*
|
||||
* The primary purpose of a `ConnectionBackend` is to create new connections to fulfill a given
|
||||
* {@link Request}.
|
||||
*/
|
||||
export class ConnectionBackend {
|
||||
constructor() {}
|
||||
createConnection(request: any): Connection { throw new BaseException('Abstract!'); }
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract class from which real connections are derived.
|
||||
*/
|
||||
export class Connection {
|
||||
readyState: ReadyStates;
|
||||
request: Request;
|
||||
response: EventEmitter; //<IResponse>;
|
||||
response: EventEmitter; // TODO: generic of <Response>;
|
||||
dispose(): void { throw new BaseException('Abstract!'); }
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for options to construct a Request, based on
|
||||
* [RequestInit](https://fetch.spec.whatwg.org/#requestinit) from the Fetch spec.
|
||||
*/
|
||||
export interface IRequestOptions {
|
||||
url?: string;
|
||||
method?: RequestMethods;
|
||||
|
@ -36,27 +49,16 @@ export interface IRequestOptions {
|
|||
cache?: RequestCacheOpts;
|
||||
}
|
||||
|
||||
export interface ResponseOptions {
|
||||
/**
|
||||
* Interface for options to construct a Response, based on
|
||||
* [ResponseInit](https://fetch.spec.whatwg.org/#responseinit) from the Fetch spec.
|
||||
*/
|
||||
export interface IResponseOptions {
|
||||
// TODO: Support Blob, ArrayBuffer, JSON
|
||||
body?: string | Object | FormData;
|
||||
status?: number;
|
||||
statusText?: string;
|
||||
headers?: Headers | Object;
|
||||
headers?: Headers;
|
||||
type?: ResponseTypes;
|
||||
url?: string;
|
||||
}
|
||||
|
||||
export interface IResponse {
|
||||
headers: Headers;
|
||||
ok: boolean;
|
||||
status: number;
|
||||
statusText: string;
|
||||
type: ResponseTypes;
|
||||
url: string;
|
||||
totalBytes: number;
|
||||
bytesLoaded: number;
|
||||
blob(): any; // TODO: Blob
|
||||
arrayBuffer(): any; // TODO: ArrayBuffer
|
||||
text(): string;
|
||||
json(): Object;
|
||||
}
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
import {RequestMethods, RequestModesOpts, RequestCredentialsOpts, RequestCacheOpts} from './enums';
|
||||
import {RequestOptions} from './base_request_options';
|
||||
import {IRequestOptions} from './interfaces';
|
||||
import {Headers} from './headers';
|
||||
import {BaseException, RegExpWrapper, CONST_EXPR, isPresent} from 'angular2/src/facade/lang';
|
||||
import {StringMap, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||
import {
|
||||
BaseException,
|
||||
RegExpWrapper,
|
||||
CONST_EXPR,
|
||||
isPresent,
|
||||
isJsObject
|
||||
} from 'angular2/src/facade/lang';
|
||||
|
||||
// TODO(jeffbcross): properly implement body accessors
|
||||
/**
|
||||
* Creates `Request` instances with default values.
|
||||
* Creates `Request` instances from provided values.
|
||||
*
|
||||
* The Request's interface is inspired by the Request constructor defined in the [Fetch
|
||||
* Spec](https://fetch.spec.whatwg.org/#request-class),
|
||||
|
@ -33,12 +37,8 @@ export class Request {
|
|||
// TODO: support URLSearchParams | FormData | Blob | ArrayBuffer
|
||||
private _body: string;
|
||||
cache: RequestCacheOpts;
|
||||
// TODO(jeffbcross): determine way to add type to destructured args
|
||||
constructor(options?: IRequestOptions) {
|
||||
var requestOptions: RequestOptions = options instanceof
|
||||
StringMap ? RequestOptions.fromStringWrapper(<StringMap<string, any>>options) :
|
||||
<RequestOptions>options;
|
||||
|
||||
constructor(requestOptions: RequestOptions) {
|
||||
// TODO: assert that url is present
|
||||
this.url = requestOptions.url;
|
||||
this._body = requestOptions.body;
|
||||
this.method = requestOptions.method;
|
||||
|
@ -47,10 +47,11 @@ export class Request {
|
|||
// Defaults to 'omit', consistent with browser
|
||||
// TODO(jeffbcross): implement behavior
|
||||
this.credentials = requestOptions.credentials;
|
||||
this.headers = requestOptions.headers;
|
||||
this.headers = new Headers(requestOptions.headers);
|
||||
this.cache = requestOptions.cache;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the request's body as string, assuming that body exists. If body is undefined, return
|
||||
* empty
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
import {IResponse, ResponseOptions} from './interfaces';
|
||||
import {ResponseTypes} from './enums';
|
||||
import {baseResponseOptions} from './base_response_options';
|
||||
import {BaseException, isJsObject, isString, isPresent, Json} from 'angular2/src/facade/lang';
|
||||
import {
|
||||
BaseException,
|
||||
CONST_EXPR,
|
||||
isJsObject,
|
||||
isString,
|
||||
isPresent,
|
||||
Json
|
||||
} from 'angular2/src/facade/lang';
|
||||
import {Headers} from './headers';
|
||||
import {ResponseOptions} from './base_response_options';
|
||||
|
||||
// TODO: make this injectable so baseResponseOptions can be overridden, mostly for the benefit of
|
||||
// headers merging.
|
||||
/**
|
||||
* Creates `Response` instances with default values.
|
||||
* Creates `Response` instances from provided values.
|
||||
*
|
||||
* Though this object isn't
|
||||
* usually instantiated by end-users, it is the primary object interacted with when it comes time to
|
||||
|
@ -19,12 +23,12 @@ import {Headers} from './headers';
|
|||
* http.request('my-friends.txt').subscribe(response => this.friends = response.text());
|
||||
* ```
|
||||
*
|
||||
* The Response's interface is inspired by the Request constructor defined in the [Fetch
|
||||
* The Response's interface is inspired by the Response constructor defined in the [Fetch
|
||||
* Spec](https://fetch.spec.whatwg.org/#response-class), but is considered a static value whose body
|
||||
* can be accessed many times. There are other differences in the implementation, but this is the
|
||||
* most significant.
|
||||
*/
|
||||
export class Response implements IResponse {
|
||||
export class Response {
|
||||
/**
|
||||
* One of "basic", "cors", "default", "error, or "opaque".
|
||||
*
|
||||
|
@ -74,16 +78,13 @@ export class Response implements IResponse {
|
|||
headers: Headers;
|
||||
// TODO: Support ArrayBuffer, JSON, FormData, Blob
|
||||
private _body: string | Object;
|
||||
constructor({body, status, statusText, headers, type, url}: ResponseOptions = {}) {
|
||||
if (isJsObject(headers)) {
|
||||
headers = new Headers(headers);
|
||||
}
|
||||
this._body = isPresent(body) ? body : baseResponseOptions.body;
|
||||
this.status = isPresent(status) ? status : baseResponseOptions.status;
|
||||
this.statusText = isPresent(statusText) ? statusText : baseResponseOptions.statusText;
|
||||
this.headers = isPresent(headers) ? <Headers>headers : baseResponseOptions.headers;
|
||||
this.type = isPresent(type) ? type : baseResponseOptions.type;
|
||||
this.url = isPresent(url) ? url : baseResponseOptions.url;
|
||||
constructor(responseOptions: ResponseOptions) {
|
||||
this._body = responseOptions.body;
|
||||
this.status = responseOptions.status;
|
||||
this.statusText = responseOptions.statusText;
|
||||
this.headers = responseOptions.headers;
|
||||
this.type = responseOptions.type;
|
||||
this.url = responseOptions.url;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,6 +21,11 @@ function paramParser(rawParams: string): Map<string, List<string>> {
|
|||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map-like representation of url search parameters, based on
|
||||
* [URLSearchParams](https://url.spec.whatwg.org/#urlsearchparams) in the url living standard.
|
||||
*
|
||||
*/
|
||||
export class URLSearchParams {
|
||||
paramsMap: Map<string, List<string>>;
|
||||
constructor(public rawParams: string) { this.paramsMap = paramParser(rawParams); }
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import {
|
||||
AsyncTestCompleter,
|
||||
afterEach,
|
||||
beforeEach,
|
||||
ddescribe,
|
||||
describe,
|
||||
|
@ -10,35 +11,47 @@ import {
|
|||
xit,
|
||||
SpyObject
|
||||
} from 'angular2/test_lib';
|
||||
import {BrowserXHR} from 'angular2/src/http/backends/browser_xhr';
|
||||
import {ObservableWrapper} from 'angular2/src/facade/async';
|
||||
import {BrowserXhr} from 'angular2/src/http/backends/browser_xhr';
|
||||
import {XHRConnection, XHRBackend} from 'angular2/src/http/backends/xhr_backend';
|
||||
import {bind, Injector} from 'angular2/di';
|
||||
import {Request} from 'angular2/src/http/static_request';
|
||||
import {StringMapWrapper} from 'angular2/src/facade/collection';
|
||||
import {RequestOptions} from 'angular2/src/http/base_request_options';
|
||||
import {Map} from 'angular2/src/facade/collection';
|
||||
import {RequestOptions, BaseRequestOptions} from 'angular2/src/http/base_request_options';
|
||||
import {BaseResponseOptions, ResponseOptions} from 'angular2/src/http/base_response_options';
|
||||
import {ResponseTypes} from 'angular2/src/http/enums';
|
||||
|
||||
var abortSpy;
|
||||
var sendSpy;
|
||||
var openSpy;
|
||||
var addEventListenerSpy;
|
||||
var existingXHRs = [];
|
||||
|
||||
class MockBrowserXHR extends BrowserXHR {
|
||||
class MockBrowserXHR extends BrowserXhr {
|
||||
abort: any;
|
||||
send: any;
|
||||
open: any;
|
||||
addEventListener: any;
|
||||
response: any;
|
||||
responseText: string;
|
||||
callbacks: Map<string, Function>;
|
||||
constructor() {
|
||||
super();
|
||||
var spy = new SpyObject();
|
||||
this.abort = abortSpy = spy.spy('abort');
|
||||
this.send = sendSpy = spy.spy('send');
|
||||
this.open = openSpy = spy.spy('open');
|
||||
this.addEventListener = addEventListenerSpy = spy.spy('addEventListener');
|
||||
this.callbacks = new Map();
|
||||
}
|
||||
|
||||
build() { return new MockBrowserXHR(); }
|
||||
addEventListener(type: string, cb: Function) { this.callbacks.set(type, cb); }
|
||||
|
||||
dispatchEvent(type: string) { this.callbacks.get(type)({}); }
|
||||
|
||||
build() {
|
||||
var xhr = new MockBrowserXHR();
|
||||
existingXHRs.push(xhr);
|
||||
return xhr;
|
||||
}
|
||||
}
|
||||
|
||||
export function main() {
|
||||
|
@ -47,17 +60,35 @@ export function main() {
|
|||
var sampleRequest;
|
||||
|
||||
beforeEach(() => {
|
||||
var injector =
|
||||
Injector.resolveAndCreate([bind(BrowserXHR).toClass(MockBrowserXHR), XHRBackend]);
|
||||
var injector = Injector.resolveAndCreate([
|
||||
bind(ResponseOptions)
|
||||
.toClass(BaseResponseOptions),
|
||||
bind(BrowserXhr).toClass(MockBrowserXHR),
|
||||
XHRBackend
|
||||
]);
|
||||
backend = injector.get(XHRBackend);
|
||||
sampleRequest = new Request(new RequestOptions({url: 'https://google.com'}));
|
||||
var base = new BaseRequestOptions();
|
||||
sampleRequest = new Request(base.merge(new RequestOptions({url: 'https://google.com'})));
|
||||
});
|
||||
|
||||
afterEach(() => { existingXHRs = []; });
|
||||
|
||||
it('should create a connection',
|
||||
() => { expect(() => backend.createConnection(sampleRequest)).not.toThrow(); });
|
||||
|
||||
|
||||
describe('XHRConnection', () => {
|
||||
it('should use the injected BaseResponseOptions to create the response',
|
||||
inject([AsyncTestCompleter], async => {
|
||||
var connection = new XHRConnection(sampleRequest, new MockBrowserXHR(),
|
||||
new ResponseOptions({type: ResponseTypes.Error}));
|
||||
ObservableWrapper.subscribe(connection.response, res => {
|
||||
expect(res.type).toBe(ResponseTypes.Error);
|
||||
async.done();
|
||||
});
|
||||
existingXHRs[0].dispatchEvent('load');
|
||||
}));
|
||||
|
||||
it('should call abort when disposed', () => {
|
||||
var connection = new XHRConnection(sampleRequest, new MockBrowserXHR());
|
||||
connection.dispose();
|
||||
|
@ -73,7 +104,9 @@ export function main() {
|
|||
|
||||
it('should automatically call send on the backend with request body', () => {
|
||||
var body = 'Some body to love';
|
||||
new XHRConnection(new Request(new RequestOptions({body: body})), new MockBrowserXHR());
|
||||
var base = new BaseRequestOptions();
|
||||
new XHRConnection(new Request(base.merge(new RequestOptions({body: body}))),
|
||||
new MockBrowserXHR());
|
||||
expect(sendSpy).toHaveBeenCalledWith(body);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -9,22 +9,22 @@ import {
|
|||
it,
|
||||
xit
|
||||
} from 'angular2/test_lib';
|
||||
import {BaseRequestOptions} from 'angular2/src/http/base_request_options';
|
||||
import {BaseRequestOptions, RequestOptions} from 'angular2/src/http/base_request_options';
|
||||
import {RequestMethods, RequestModesOpts} from 'angular2/src/http/enums';
|
||||
|
||||
export function main() {
|
||||
describe('BaseRequestOptions', () => {
|
||||
it('should create a new object when calling merge', () => {
|
||||
var options1 = new BaseRequestOptions();
|
||||
var options2 = options1.merge({method: RequestMethods.DELETE});
|
||||
var options2 = options1.merge(new RequestOptions({method: RequestMethods.DELETE}));
|
||||
expect(options2).not.toBe(options1);
|
||||
expect(options2.method).toBe(RequestMethods.DELETE);
|
||||
});
|
||||
|
||||
it('should retain previously merged values when merging again', () => {
|
||||
var options1 = new BaseRequestOptions();
|
||||
var options2 = options1.merge({method: RequestMethods.DELETE});
|
||||
var options3 = options2.merge({mode: RequestModesOpts.NoCors});
|
||||
var options2 = options1.merge(new RequestOptions({method: RequestMethods.DELETE}));
|
||||
var options3 = options2.merge(new RequestOptions({mode: RequestModesOpts.NoCors}));
|
||||
expect(options3.mode).toBe(RequestModesOpts.NoCors);
|
||||
expect(options3.method).toBe(RequestMethods.DELETE);
|
||||
});
|
||||
|
|
|
@ -17,6 +17,7 @@ import {MockBackend} from 'angular2/src/http/backends/mock_backend';
|
|||
import {Response} from 'angular2/src/http/static_response';
|
||||
import {RequestMethods} from 'angular2/src/http/enums';
|
||||
import {BaseRequestOptions, RequestOptions} from 'angular2/src/http/base_request_options';
|
||||
import {ResponseOptions} from 'angular2/src/http/base_response_options';
|
||||
import {Request} from 'angular2/src/http/static_request';
|
||||
import {EventEmitter, ObservableWrapper} from 'angular2/src/facade/async';
|
||||
import {ConnectionBackend} from 'angular2/src/http/interfaces';
|
||||
|
@ -52,7 +53,7 @@ export function main() {
|
|||
]);
|
||||
http = injector.get(Http);
|
||||
backend = injector.get(MockBackend);
|
||||
baseResponse = new Response({body: 'base response'});
|
||||
baseResponse = new Response(new ResponseOptions({body: 'base response'}));
|
||||
});
|
||||
|
||||
afterEach(() => backend.verifyNoPendingRequests());
|
||||
|
@ -67,7 +68,7 @@ export function main() {
|
|||
inject([AsyncTestCompleter], (async) => {
|
||||
ObservableWrapper.subscribe(backend.connections, c => {
|
||||
expect(c.request.url).toBe('https://google.com');
|
||||
c.mockRespond(new Response({body: 'Thank you'}));
|
||||
c.mockRespond(new Response(new ResponseOptions({body: 'Thank you'})));
|
||||
async.done();
|
||||
});
|
||||
ObservableWrapper.subscribe(
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {bootstrap, Component, View, NgFor, Inject} from 'angular2/angular2';
|
||||
import {Component, View, NgFor} from 'angular2/angular2';
|
||||
import {Http} from 'angular2/http';
|
||||
import {ObservableWrapper} from 'angular2/src/facade/async';
|
||||
import {Http, httpInjectables} from 'angular2/http';
|
||||
|
||||
@Component({selector: 'http-app'})
|
||||
@View({
|
||||
|
@ -19,4 +19,4 @@ export class HttpCmp {
|
|||
constructor(http: Http) {
|
||||
ObservableWrapper.subscribe(http.get('./people.json'), res => this.people = res.json());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
/// <reference path="../../../angular2/typings/rx/rx.all.d.ts" />
|
||||
|
||||
import {
|
||||
bootstrap,
|
||||
} from 'angular2/angular2';
|
||||
import {bootstrap} from 'angular2/angular2';
|
||||
import {reflector} from 'angular2/src/reflection/reflection';
|
||||
import {ReflectionCapabilities} from 'angular2/src/reflection/reflection_capabilities';
|
||||
import {httpInjectables} from 'angular2/http';
|
||||
|
|
Loading…
Reference in New Issue