2015-06-29 18:30:48 -04:00
|
|
|
/// <reference path="../../typings/rx/rx.d.ts" />
|
2015-04-29 02:07:55 -04:00
|
|
|
|
|
|
|
import {Injectable} from 'angular2/src/di/decorators';
|
2015-06-26 14:10:52 -04:00
|
|
|
import {IRequestOptions, Connection, IHttp} from './interfaces';
|
2015-04-29 02:07:55 -04:00
|
|
|
import {Request} from './static_request';
|
|
|
|
import {Response} from './static_response';
|
|
|
|
import {XHRBackend} from './backends/xhr_backend';
|
|
|
|
import {BaseRequestOptions} from './base_request_options';
|
2015-06-13 18:49:05 -04:00
|
|
|
import {RequestMethods} from './enums';
|
|
|
|
import {URLSearchParams} from './url_search_params';
|
2015-04-29 02:07:55 -04:00
|
|
|
import * as Rx from 'rx';
|
|
|
|
|
2015-06-26 14:10:52 -04:00
|
|
|
function httpRequest(backend: XHRBackend, request: Request): Rx.Observable<Response> {
|
2015-06-09 18:18:57 -04:00
|
|
|
return <Rx.Observable<Response>>(Observable.create(observer => {
|
|
|
|
var connection: Connection = backend.createConnection(request);
|
|
|
|
var internalSubscription = connection.response.subscribe(observer);
|
|
|
|
return () => {
|
|
|
|
internalSubscription.dispose();
|
|
|
|
connection.dispose();
|
2015-06-26 14:10:52 -04:00
|
|
|
};
|
|
|
|
}));
|
2015-06-09 18:18:57 -04:00
|
|
|
}
|
|
|
|
|
2015-04-29 02:07:55 -04:00
|
|
|
/**
|
2015-06-09 18:18:57 -04:00
|
|
|
* 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
|
|
|
|
* received.
|
2015-04-29 02:07:55 -04:00
|
|
|
*
|
|
|
|
* #Example
|
|
|
|
*
|
|
|
|
* ```
|
2015-06-09 18:18:57 -04:00
|
|
|
* import {Http, httpInjectables} from 'angular2/http';
|
|
|
|
* @Component({selector: 'http-app', appInjector: [httpInjectables]})
|
|
|
|
* @View({templateUrl: 'people.html'})
|
|
|
|
* class PeopleComponent {
|
|
|
|
* constructor(http: Http) {
|
|
|
|
* http('people.json')
|
|
|
|
* // Call map on the response observable to get the parsed people object
|
|
|
|
* .map(res => res.json())
|
|
|
|
* // Subscribe to the observable to get the parsed people object and attach it to the
|
|
|
|
* // component
|
|
|
|
* .subscribe(people => this.people = people);
|
|
|
|
* }
|
2015-04-29 02:07:55 -04:00
|
|
|
* }
|
|
|
|
* ```
|
|
|
|
*
|
2015-06-09 18:18:57 -04:00
|
|
|
* The default construct used to perform requests, `XMLHttpRequest`, is abstracted as a "Backend" (
|
|
|
|
* {@link XHRBackend} in this case), which could be mocked with dependency injection by replacing
|
|
|
|
* the {@link XHRBackend} binding, as in the following example:
|
2015-04-29 02:07:55 -04:00
|
|
|
*
|
2015-06-09 18:18:57 -04:00
|
|
|
* #Example
|
2015-04-29 02:07:55 -04:00
|
|
|
*
|
2015-06-09 18:18:57 -04:00
|
|
|
* ```
|
|
|
|
* import {MockBackend, BaseRequestOptions, Http} from 'angular2/http';
|
|
|
|
* var injector = Injector.resolveAndCreate([
|
|
|
|
* BaseRequestOptions,
|
|
|
|
* MockBackend,
|
|
|
|
* bind(Http).toFactory(
|
|
|
|
* function(backend, defaultOptions) {
|
|
|
|
* return new Http(backend, defaultOptions);
|
|
|
|
* },
|
|
|
|
* [MockBackend, BaseRequestOptions])
|
|
|
|
* ]);
|
|
|
|
* var http = injector.get(Http);
|
|
|
|
* http.get('request-from-mock-backend.json').subscribe((res:Response) => doSomething(res));
|
|
|
|
* ```
|
2015-04-29 02:07:55 -04:00
|
|
|
*
|
|
|
|
**/
|
|
|
|
@Injectable()
|
|
|
|
export class Http {
|
2015-06-09 18:18:57 -04:00
|
|
|
constructor(private _backend: XHRBackend, private _defaultOptions: BaseRequestOptions) {}
|
2015-06-13 18:49:05 -04:00
|
|
|
|
2015-06-09 18:18:57 -04:00
|
|
|
/**
|
|
|
|
* Performs any type of http request. First argument is required, and can either be a url or
|
|
|
|
* a {@link Request} instance. If the first argument is a url, an optional {@link RequestOptions}
|
|
|
|
* object can be provided as the 2nd argument. The options object will be merged with the values
|
|
|
|
* of {@link BaseRequestOptions} before performing the request.
|
|
|
|
*/
|
2015-06-13 22:48:40 -04:00
|
|
|
request(url: string | Request, options?: IRequestOptions): Rx.Observable<Response> {
|
2015-06-13 19:44:32 -04:00
|
|
|
if (typeof url === 'string') {
|
2015-06-09 18:18:57 -04:00
|
|
|
return httpRequest(this._backend, new Request(url, this._defaultOptions.merge(options)));
|
2015-06-13 19:44:32 -04:00
|
|
|
} else if (url instanceof Request) {
|
2015-06-09 18:18:57 -04:00
|
|
|
return httpRequest(this._backend, url);
|
2015-06-13 19:44:32 -04:00
|
|
|
}
|
2015-06-13 18:49:05 -04:00
|
|
|
}
|
|
|
|
|
2015-06-09 18:18:57 -04:00
|
|
|
/**
|
|
|
|
* Performs a request with `get` http method.
|
|
|
|
*/
|
2015-06-26 14:10:52 -04:00
|
|
|
get(url: string, options?: IRequestOptions): Rx.Observable<Response> {
|
2015-06-09 18:18:57 -04:00
|
|
|
return httpRequest(this._backend, new Request(url, this._defaultOptions.merge(options)
|
|
|
|
.merge({method: RequestMethods.GET})));
|
2015-06-13 18:49:05 -04:00
|
|
|
}
|
|
|
|
|
2015-06-09 18:18:57 -04:00
|
|
|
/**
|
|
|
|
* Performs a request with `post` http method.
|
|
|
|
*/
|
2015-06-26 14:10:52 -04:00
|
|
|
post(url: string, body: URLSearchParams | FormData | Blob | string,
|
|
|
|
options?: IRequestOptions): Rx.Observable<Response> {
|
2015-06-09 18:18:57 -04:00
|
|
|
return httpRequest(this._backend,
|
|
|
|
new Request(url, this._defaultOptions.merge(options)
|
2015-06-13 18:49:05 -04:00
|
|
|
|
|
|
|
.merge({body: body, method: RequestMethods.POST})));
|
|
|
|
}
|
|
|
|
|
2015-06-09 18:18:57 -04:00
|
|
|
/**
|
|
|
|
* Performs a request with `put` http method.
|
|
|
|
*/
|
2015-06-26 14:10:52 -04:00
|
|
|
put(url: string, body: URLSearchParams | FormData | Blob | string,
|
|
|
|
options?: IRequestOptions): Rx.Observable<Response> {
|
2015-06-09 18:18:57 -04:00
|
|
|
return httpRequest(this._backend,
|
|
|
|
new Request(url, this._defaultOptions.merge(options)
|
2015-06-13 18:49:05 -04:00
|
|
|
.merge({body: body, method: RequestMethods.PUT})));
|
|
|
|
}
|
|
|
|
|
2015-06-09 18:18:57 -04:00
|
|
|
/**
|
|
|
|
* Performs a request with `delete` http method.
|
|
|
|
*/
|
2015-06-26 14:10:52 -04:00
|
|
|
delete (url: string, options?: IRequestOptions): Rx.Observable<Response> {
|
2015-06-09 18:18:57 -04:00
|
|
|
return httpRequest(this._backend, new Request(url, this._defaultOptions.merge(options).merge(
|
|
|
|
{method: RequestMethods.DELETE})));
|
2015-06-13 18:49:05 -04:00
|
|
|
}
|
|
|
|
|
2015-06-09 18:18:57 -04:00
|
|
|
/**
|
|
|
|
* Performs a request with `patch` http method.
|
|
|
|
*/
|
2015-06-26 14:10:52 -04:00
|
|
|
patch(url: string, body: URLSearchParams | FormData | Blob | string,
|
|
|
|
options?: IRequestOptions): Rx.Observable<Response> {
|
2015-06-09 18:18:57 -04:00
|
|
|
return httpRequest(this._backend,
|
|
|
|
new Request(url, this._defaultOptions.merge(options)
|
2015-06-13 18:49:05 -04:00
|
|
|
.merge({body: body, method: RequestMethods.PATCH})));
|
|
|
|
}
|
|
|
|
|
2015-06-09 18:18:57 -04:00
|
|
|
/**
|
|
|
|
* Performs a request with `head` http method.
|
|
|
|
*/
|
2015-06-26 14:10:52 -04:00
|
|
|
head(url: string, options?: IRequestOptions): Rx.Observable<Response> {
|
2015-06-09 18:18:57 -04:00
|
|
|
return httpRequest(this._backend, new Request(url, this._defaultOptions.merge(options)
|
|
|
|
.merge({method: RequestMethods.HEAD})));
|
2015-06-13 18:49:05 -04:00
|
|
|
}
|
2015-04-29 02:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
var Observable;
|
|
|
|
if (Rx.hasOwnProperty('default')) {
|
|
|
|
Observable = (<any>Rx).default.Rx.Observable;
|
|
|
|
} else {
|
|
|
|
Observable = Rx.Observable;
|
|
|
|
}
|
2015-06-09 18:18:57 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* Alias to the `request` method of {@link Http}, for those who'd prefer a simple function instead
|
|
|
|
* of an object. In order to get TypeScript type information about the `HttpFactory`, the {@link
|
|
|
|
* IHttp} interface can be used as shown in the following example.
|
|
|
|
*
|
|
|
|
* #Example
|
|
|
|
*
|
|
|
|
* ```
|
|
|
|
* import {httpInjectables, HttpFactory, IHttp} from 'angular2/http';
|
|
|
|
* @Component({
|
|
|
|
* appInjector: [httpInjectables]
|
|
|
|
* })
|
|
|
|
* @View({
|
|
|
|
* templateUrl: 'people.html'
|
|
|
|
* })
|
|
|
|
* class MyComponent {
|
|
|
|
* constructor(@Inject(HttpFactory) http:IHttp) {
|
|
|
|
* http('people.json').subscribe(res => this.people = res.json());
|
|
|
|
* }
|
|
|
|
* }
|
|
|
|
* ```
|
|
|
|
**/
|
2015-06-26 14:10:52 -04:00
|
|
|
export function HttpFactory(backend: XHRBackend, defaultOptions: BaseRequestOptions): IHttp {
|
2015-06-13 22:48:40 -04:00
|
|
|
return function(url: string | Request, options?: IRequestOptions) {
|
2015-06-13 19:44:32 -04:00
|
|
|
if (typeof url === 'string') {
|
|
|
|
return httpRequest(backend, new Request(url, defaultOptions.merge(options)));
|
|
|
|
} else if (url instanceof Request) {
|
|
|
|
return httpRequest(backend, url);
|
|
|
|
}
|
2015-06-26 14:10:52 -04:00
|
|
|
};
|
2015-04-29 02:07:55 -04:00
|
|
|
}
|