Skip to content

Commit b3d98cb

Browse files
committed
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.
1 parent 146dbf1 commit b3d98cb

20 files changed

+333
-194
lines changed

modules/angular2/core.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@ export * from './src/core/compiler/dynamic_component_loader';
1717
export {ViewRef, ProtoViewRef} from './src/core/compiler/view_ref';
1818
export {ViewContainerRef} from './src/core/compiler/view_container_ref';
1919
export {ElementRef} from './src/core/compiler/element_ref';
20+
export {EventEmitter} from './src/facade/async';
2021

2122
export {NgZone} from './src/core/zone/ng_zone';

modules/angular2/http.ts

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,39 @@
66
* class.
77
*/
88
import {bind, Binding} from 'angular2/di';
9-
import {Http} from './src/http/http';
9+
import {Http} from 'angular2/src/http/http';
1010
import {XHRBackend, XHRConnection} from 'angular2/src/http/backends/xhr_backend';
11-
import {BrowserXHR} from 'angular2/src/http/backends/browser_xhr';
11+
import {BrowserXhr} from 'angular2/src/http/backends/browser_xhr';
1212
import {BaseRequestOptions, RequestOptions} from 'angular2/src/http/base_request_options';
1313
import {ConnectionBackend} from 'angular2/src/http/interfaces';
1414

1515
export {MockConnection, MockBackend} from 'angular2/src/http/backends/mock_backend';
1616
export {Request} from 'angular2/src/http/static_request';
1717
export {Response} from 'angular2/src/http/static_response';
18+
import {BaseResponseOptions, ResponseOptions} from 'angular2/src/http/base_response_options';
1819

1920
export {
2021
IRequestOptions,
21-
IResponse,
22+
IResponseOptions,
2223
Connection,
2324
ConnectionBackend
2425
} from 'angular2/src/http/interfaces';
2526

2627
export {BaseRequestOptions, RequestOptions} from 'angular2/src/http/base_request_options';
28+
export {BaseResponseOptions, ResponseOptions} from 'angular2/src/http/base_response_options';
2729
export {XHRBackend, XHRConnection} from 'angular2/src/http/backends/xhr_backend';
28-
export {Http} from './src/http/http';
30+
export {Http} from 'angular2/src/http/http';
2931

3032
export {Headers} from 'angular2/src/http/headers';
3133

32-
export * from 'angular2/src/http/enums';
34+
export {
35+
ResponseTypes,
36+
ReadyStates,
37+
RequestMethods,
38+
RequestCredentialsOpts,
39+
RequestCacheOpts,
40+
RequestModesOpts
41+
} from 'angular2/src/http/enums';
3342
export {URLSearchParams} from 'angular2/src/http/url_search_params';
3443

3544
/**
@@ -49,5 +58,11 @@ export {URLSearchParams} from 'angular2/src/http/url_search_params';
4958
* ```
5059
*
5160
*/
52-
export var httpInjectables: List<any> =
53-
[bind(ConnectionBackend).toClass(XHRBackend), BrowserXHR, XHRBackend, BaseRequestOptions, Http];
61+
export var httpInjectables: List<any> = [
62+
bind(ConnectionBackend)
63+
.toClass(XHRBackend),
64+
BrowserXhr,
65+
bind(RequestOptions).toClass(BaseRequestOptions),
66+
bind(ResponseOptions).toClass(BaseResponseOptions),
67+
Http
68+
];

modules/angular2/src/http/backends/browser_xhr.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import 'dart:html' show HttpRequest;
44
import 'package:angular2/di.dart';
55

66
@Injectable()
7-
class BrowserXHR {
7+
class BrowserXhr {
88
HttpRequest build() {
99
return new HttpRequest();
1010
}
Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
declare var window;
2-
31
import {Injectable} from 'angular2/di';
42

53
// Make sure not to evaluate this in a non-browser environment!
64
@Injectable()
7-
export class BrowserXHR {
5+
export class BrowserXhr {
86
constructor() {}
9-
build(): any { return <any>(new window.XMLHttpRequest()); }
7+
build(): any { return <any>(new XMLHttpRequest()); }
108
}

modules/angular2/src/http/backends/mock_backend.ts

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,7 @@ import {IMPLEMENTS, BaseException} from 'angular2/src/facade/lang';
99

1010
/**
1111
*
12-
* Connection class used by MockBackend
13-
*
14-
* This class is typically not instantiated directly, but instances can be retrieved by subscribing
15-
*to the `connections` Observable of
16-
* {@link MockBackend} in order to mock responses to requests.
12+
* Mock Connection to represent a {@link Connection} for tests.
1713
*
1814
**/
1915
@IMPLEMENTS(Connection)
@@ -32,9 +28,8 @@ export class MockConnection {
3228
request: Request;
3329

3430
/**
35-
* [RxJS
36-
* Observable](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/observable.md)
37-
* of {@link Response}. Can be subscribed to in order to be notified when a response is available.
31+
* {@link EventEmitter} of {@link Response}. Can be subscribed to in order to be notified when a
32+
* response is available.
3833
*/
3934
response: EventEmitter;
4035

@@ -55,7 +50,7 @@ export class MockConnection {
5550

5651
/**
5752
* Sends a mock response to the connection. This response is the value that is emitted to the
58-
* `Observable` returned by {@link Http}.
53+
* {@link EventEmitter} returned by {@link Http}.
5954
*
6055
* #Example
6156
*
@@ -91,7 +86,8 @@ export class MockConnection {
9186

9287
// TODO(jeffbcross): consider using Response type
9388
/**
94-
* Emits the provided error object as an error to the {@link Response} observable returned
89+
* Emits the provided error object as an error to the {@link Response} {@link EventEmitter}
90+
* returned
9591
* from {@link Http}.
9692
*/
9793
mockError(err?) {
@@ -137,8 +133,7 @@ export class MockConnection {
137133
@IMPLEMENTS(ConnectionBackend)
138134
export class MockBackend {
139135
/**
140-
* [RxJS
141-
* Subject](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/subjects/subject.md)
136+
* {@link EventEmitter}
142137
* of {@link MockConnection} instances that have been created by this backend. Can be subscribed
143138
* to in order to respond to connections.
144139
*
@@ -162,7 +157,7 @@ export class MockBackend {
162157
* http.request('something.json').subscribe(res => {
163158
* text = res.text();
164159
* });
165-
* connection.mockRespond(new Response('Something'));
160+
* connection.mockRespond(new Response({body: 'Something'}));
166161
* expect(text).toBe('Something');
167162
* });
168163
* ```
@@ -179,8 +174,8 @@ export class MockBackend {
179174
*/
180175
connectionsArray: Array<MockConnection>;
181176
/**
182-
* [Observable](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/observable.md)
183-
* of {@link MockConnection} instances that haven't yet been resolved (i.e. with a `readyState`
177+
* {@link EventEmitter} of {@link MockConnection} instances that haven't yet been resolved (i.e.
178+
* with a `readyState`
184179
* less than 4). Used internally to verify that no connections are pending via the
185180
* `verifyNoPendingRequests` method.
186181
*
@@ -193,7 +188,6 @@ export class MockBackend {
193188
ObservableWrapper.subscribe(this.connections,
194189
connection => this.connectionsArray.push(connection));
195190
this.pendingConnections = new EventEmitter();
196-
// Observable.fromArray(this.connectionsArray).filter((c) => c.readyState < ReadyStates.DONE);
197191
}
198192

199193
/**
@@ -218,10 +212,10 @@ export class MockBackend {
218212
/**
219213
* Creates a new {@link MockConnection}. This is equivalent to calling `new
220214
* MockConnection()`, except that it also will emit the new `Connection` to the `connections`
221-
* observable of this `MockBackend` instance. This method will usually only be used by tests
215+
* emitter of this `MockBackend` instance. This method will usually only be used by tests
222216
* against the framework itself, not by end-users.
223217
*/
224-
createConnection(req: Request) {
218+
createConnection(req: Request): Connection {
225219
if (!isPresent(req) || !(req instanceof Request)) {
226220
throw new BaseException(`createConnection requires an instance of Request, got ${req}`);
227221
}

modules/angular2/src/http/backends/xhr_backend.ts

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ import {ConnectionBackend, Connection} from '../interfaces';
22
import {ReadyStates, RequestMethods, RequestMethodsMap} from '../enums';
33
import {Request} from '../static_request';
44
import {Response} from '../static_response';
5+
import {ResponseOptions, BaseResponseOptions} from '../base_response_options';
56
import {Injectable} from 'angular2/di';
6-
import {BrowserXHR} from './browser_xhr';
7+
import {BrowserXhr} from './browser_xhr';
78
import {EventEmitter, ObservableWrapper} from 'angular2/src/facade/async';
89
import {isPresent, ENUM_INDEX} from 'angular2/src/facade/lang';
910

@@ -18,14 +19,14 @@ import {isPresent, ENUM_INDEX} from 'angular2/src/facade/lang';
1819
export class XHRConnection implements Connection {
1920
request: Request;
2021
/**
21-
* Response
22-
* [Subject](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/subjects/subject.md)
23-
* which emits a single {@link Response} value on load event of `XMLHttpRequest`.
22+
* Response {@link EventEmitter} which emits a single {@link Response} value on load event of
23+
* `XMLHttpRequest`.
2424
*/
25-
response: EventEmitter; //<Response>;
25+
response: EventEmitter; // TODO: Make generic of <Response>;
2626
readyState: ReadyStates;
27-
private _xhr;
28-
constructor(req: Request, browserXHR: BrowserXHR) {
27+
private _xhr; // TODO: make type XMLHttpRequest, pending resolution of
28+
// https://github.com/angular/ts2dart/issues/230
29+
constructor(req: Request, browserXHR: BrowserXhr, baseResponseOptions?: ResponseOptions) {
2930
// TODO: get rid of this when enum lookups are available in ts2dart
3031
// https://github.com/angular/ts2dart/issues/221
3132
var requestMethodsMap = new RequestMethodsMap();
@@ -34,12 +35,15 @@ export class XHRConnection implements Connection {
3435
this._xhr = browserXHR.build();
3536
// TODO(jeffbcross): implement error listening/propagation
3637
this._xhr.open(requestMethodsMap.getMethod(ENUM_INDEX(req.method)), req.url);
37-
this._xhr.addEventListener(
38-
'load',
39-
(_) => {ObservableWrapper.callNext(
40-
this.response, new Response({
41-
body: isPresent(this._xhr.response) ? this._xhr.response : this._xhr.responseText
42-
}))});
38+
this._xhr.addEventListener('load', (_) => {
39+
var responseOptions = new ResponseOptions(
40+
{body: isPresent(this._xhr.response) ? this._xhr.response : this._xhr.responseText});
41+
if (isPresent(baseResponseOptions)) {
42+
responseOptions = baseResponseOptions.merge(responseOptions);
43+
}
44+
45+
ObservableWrapper.callNext(this.response, new Response(responseOptions))
46+
});
4347
// TODO(jeffbcross): make this more dynamic based on body type
4448
this._xhr.send(this.request.text());
4549
}
@@ -78,8 +82,8 @@ export class XHRConnection implements Connection {
7882
**/
7983
@Injectable()
8084
export class XHRBackend implements ConnectionBackend {
81-
constructor(private _browserXHR: BrowserXHR) {}
85+
constructor(private _browserXHR: BrowserXhr, private _baseResponseOptions: ResponseOptions) {}
8286
createConnection(request: Request): XHRConnection {
83-
return new XHRConnection(request, this._browserXHR);
87+
return new XHRConnection(request, this._browserXHR, this._baseResponseOptions);
8488
}
8589
}

modules/angular2/src/http/base_request_options.ts

Lines changed: 30 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,22 @@ import {Headers} from './headers';
33
import {RequestModesOpts, RequestMethods, RequestCacheOpts, RequestCredentialsOpts} from './enums';
44
import {IRequestOptions} from './interfaces';
55
import {Injectable} from 'angular2/di';
6-
import {ListWrapper, StringMapWrapper, StringMap} from 'angular2/src/facade/collection';
76

8-
const INITIALIZER = CONST_EXPR({});
97
/**
10-
* Creates a request options object with default properties as described in the [Fetch
8+
* Creates a request options object similar to the `RequestInit` description
9+
* in the [Fetch
1110
* Spec](https://fetch.spec.whatwg.org/#requestinit) to be optionally provided when instantiating a
12-
* {@link Request}. This class is used implicitly by {@link Http} to merge in provided request
13-
* options with the default options specified here. These same default options are injectable via
14-
* the {@link BaseRequestOptions} class.
11+
* {@link Request}.
12+
*
13+
* All values are null by default.
1514
*/
1615
export class RequestOptions implements IRequestOptions {
1716
/**
1817
* Http method with which to execute the request.
1918
*
2019
* Defaults to "GET".
2120
*/
22-
method: RequestMethods = RequestMethods.GET;
21+
method: RequestMethods;
2322
/**
2423
* Headers object based on the `Headers` class in the [Fetch
2524
* Spec](https://fetch.spec.whatwg.org/#headers-class).
@@ -28,54 +27,42 @@ export class RequestOptions implements IRequestOptions {
2827
/**
2928
* Body to be used when creating the request.
3029
*/
31-
// TODO: support FormData, Blob, URLSearchParams, JSON
30+
// TODO: support FormData, Blob, URLSearchParams
3231
body: string;
33-
mode: RequestModesOpts = RequestModesOpts.Cors;
32+
mode: RequestModesOpts;
3433
credentials: RequestCredentialsOpts;
3534
cache: RequestCacheOpts;
3635
url: string;
3736
constructor({method, headers, body, mode, credentials, cache, url}: IRequestOptions = {}) {
38-
this.method = isPresent(method) ? method : RequestMethods.GET;
39-
this.headers = headers;
40-
this.body = body;
41-
this.mode = isPresent(mode) ? mode : RequestModesOpts.Cors;
42-
this.credentials = credentials;
43-
this.cache = cache;
44-
this.url = url;
37+
this.method = isPresent(method) ? method : null;
38+
this.headers = isPresent(headers) ? headers : null;
39+
this.body = isPresent(body) ? body : null;
40+
this.mode = isPresent(mode) ? mode : null;
41+
this.credentials = isPresent(credentials) ? credentials : null;
42+
this.cache = isPresent(cache) ? cache : null;
43+
this.url = isPresent(url) ? url : null;
4544
}
4645

4746
/**
4847
* Creates a copy of the `RequestOptions` instance, using the optional input as values to override
4948
* existing values.
5049
*/
51-
merge({url = null, method = null, headers = null, body = null, mode = null, credentials = null,
52-
cache = null}: any = {}): RequestOptions {
50+
merge(options?: IRequestOptions): RequestOptions {
5351
return new RequestOptions({
54-
method: isPresent(method) ? method : this.method,
55-
headers: isPresent(headers) ? headers : this.headers,
56-
body: isPresent(body) ? body : this.body,
57-
mode: isPresent(mode) ? mode : this.mode,
58-
credentials: isPresent(credentials) ? credentials : this.credentials,
59-
cache: isPresent(cache) ? cache : this.cache,
60-
url: isPresent(url) ? url : this.url
52+
method: isPresent(options) && isPresent(options.method) ? options.method : this.method,
53+
headers: isPresent(options) && isPresent(options.headers) ? options.headers : this.headers,
54+
body: isPresent(options) && isPresent(options.body) ? options.body : this.body,
55+
mode: isPresent(options) && isPresent(options.mode) ? options.mode : this.mode,
56+
credentials: isPresent(options) && isPresent(options.credentials) ? options.credentials :
57+
this.credentials,
58+
cache: isPresent(options) && isPresent(options.cache) ? options.cache : this.cache,
59+
url: isPresent(options) && isPresent(options.url) ? options.url : this.url
6160
});
6261
}
63-
64-
static fromStringWrapper(map: StringMap<string, any>): RequestOptions {
65-
return new RequestOptions({
66-
method: StringMapWrapper.get(map, 'method'),
67-
headers: StringMapWrapper.get(map, 'headers'),
68-
body: StringMapWrapper.get(map, 'body'),
69-
mode: StringMapWrapper.get(map, 'mode'),
70-
credentials: StringMapWrapper.get(map, 'credentials'),
71-
cache: StringMapWrapper.get(map, 'cache'),
72-
url:<string>StringMapWrapper.get(map, 'url')
73-
})
74-
}
7562
}
7663

7764
/**
78-
* Injectable version of {@link RequestOptions}.
65+
* Injectable version of {@link RequestOptions}, with overridable default values.
7966
*
8067
* #Example
8168
*
@@ -84,8 +71,8 @@ export class RequestOptions implements IRequestOptions {
8471
* ...
8572
* class MyComponent {
8673
* constructor(baseRequestOptions:BaseRequestOptions, http:Http) {
87-
* var options = baseRequestOptions.merge({body: 'foobar'});
88-
* var request = new Request('https://foo/', options);
74+
* var options = baseRequestOptions.merge({body: 'foobar', url: 'https://foo/'});
75+
* var request = new Request(options);
8976
* http.request(request).subscribe(res => this.bars = res.json());
9077
* }
9178
* }
@@ -94,5 +81,7 @@ export class RequestOptions implements IRequestOptions {
9481
*/
9582
@Injectable()
9683
export class BaseRequestOptions extends RequestOptions {
97-
constructor() { super(); }
84+
constructor() {
85+
super({method: RequestMethods.GET, headers: new Headers(), mode: RequestModesOpts.Cors});
86+
}
9887
}

0 commit comments

Comments
 (0)