2016-04-28 20:50:03 -04:00
|
|
|
import {isString, isPresent} from '../src/facade/lang';
|
|
|
|
import {makeTypeError} from '../src/facade/exceptions';
|
|
|
|
import {Injectable} from '@angular/core';
|
|
|
|
import {RequestOptionsArgs, ConnectionBackend} from './interfaces';
|
2015-04-29 02:07:55 -04:00
|
|
|
import {Request} from './static_request';
|
2015-10-31 02:52:37 -04:00
|
|
|
import {Response} from './static_response';
|
2015-06-19 15:14:12 -04:00
|
|
|
import {BaseRequestOptions, RequestOptions} from './base_request_options';
|
2016-02-26 06:25:55 -05:00
|
|
|
import {URLSearchParams} from './url_search_params';
|
2015-12-03 16:44:14 -05:00
|
|
|
import {RequestMethod} from './enums';
|
2015-12-12 11:29:02 -05:00
|
|
|
import {Observable} from 'rxjs/Observable';
|
2015-06-19 15:14:12 -04:00
|
|
|
|
2015-10-31 02:52:37 -04:00
|
|
|
function httpRequest(backend: ConnectionBackend, request: Request): Observable<Response> {
|
2015-06-19 15:14:12 -04:00
|
|
|
return backend.createConnection(request).response;
|
|
|
|
}
|
2015-04-29 02:07:55 -04:00
|
|
|
|
2016-04-12 12:40:37 -04:00
|
|
|
function mergeOptions(defaultOpts: BaseRequestOptions, providedOpts: RequestOptionsArgs,
|
|
|
|
method: RequestMethod, url: string): RequestOptions {
|
2015-06-19 15:14:12 -04:00
|
|
|
var newOptions = defaultOpts;
|
|
|
|
if (isPresent(providedOpts)) {
|
2015-06-24 03:27:07 -04:00
|
|
|
// Hack so Dart can used named parameters
|
2015-11-19 22:54:23 -05:00
|
|
|
return newOptions.merge(new RequestOptions({
|
|
|
|
method: providedOpts.method || method,
|
|
|
|
url: providedOpts.url || url,
|
2015-07-13 14:47:10 -04:00
|
|
|
search: providedOpts.search,
|
2015-06-24 03:27:07 -04:00
|
|
|
headers: providedOpts.headers,
|
2016-02-24 16:57:35 -05:00
|
|
|
body: providedOpts.body,
|
|
|
|
withCredentials: providedOpts.withCredentials
|
2015-06-24 03:27:07 -04:00
|
|
|
}));
|
2015-06-19 15:14:12 -04:00
|
|
|
}
|
|
|
|
if (isPresent(method)) {
|
2015-06-24 03:27:07 -04:00
|
|
|
return newOptions.merge(new RequestOptions({method: method, url: url}));
|
2015-06-19 15:14:12 -04:00
|
|
|
} else {
|
2015-06-24 03:27:07 -04:00
|
|
|
return newOptions.merge(new RequestOptions({url: url}));
|
2015-06-19 15:14:12 -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
|
2015-12-03 18:49:09 -05:00
|
|
|
* `request` returns an `Observable` which will emit a single {@link Response} when a
|
2015-07-01 13:15:58 -04:00
|
|
|
* response is received.
|
|
|
|
*
|
2015-10-19 10:37:32 -04:00
|
|
|
* ### Example
|
2015-04-29 02:07:55 -04:00
|
|
|
*
|
2015-09-24 04:32:43 -04:00
|
|
|
* ```typescript
|
2016-04-28 20:50:03 -04:00
|
|
|
* import {Http, HTTP_PROVIDERS} from '@angular/http';
|
2015-12-16 03:32:25 -05:00
|
|
|
* import 'rxjs/add/operator/map'
|
2015-10-11 10:41:19 -04:00
|
|
|
* @Component({
|
|
|
|
* selector: 'http-app',
|
|
|
|
* viewProviders: [HTTP_PROVIDERS],
|
|
|
|
* templateUrl: 'people.html'
|
|
|
|
* })
|
2015-06-09 18:18:57 -04:00
|
|
|
* class PeopleComponent {
|
|
|
|
* constructor(http: Http) {
|
2015-07-01 13:15:58 -04:00
|
|
|
* http.get('people.json')
|
2015-06-09 18:18:57 -04:00
|
|
|
* // 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-07-01 13:15:58 -04:00
|
|
|
*
|
2015-10-19 10:37:32 -04:00
|
|
|
* ### Example
|
2015-07-01 13:15:58 -04:00
|
|
|
*
|
|
|
|
* ```
|
2015-12-16 03:32:25 -05:00
|
|
|
* http.get('people.json').subscribe((res:Response) => this.people = res.json());
|
2015-07-01 13:15:58 -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
|
2015-10-11 01:11:13 -04:00
|
|
|
* the {@link XHRBackend} provider, as in the following example:
|
2015-04-29 02:07:55 -04:00
|
|
|
*
|
2015-10-19 10:37:32 -04:00
|
|
|
* ### Example
|
2015-04-29 02:07:55 -04:00
|
|
|
*
|
2015-09-24 04:32:43 -04:00
|
|
|
* ```typescript
|
2016-04-28 20:50:03 -04:00
|
|
|
* import {BaseRequestOptions, Http} from '@angular/http';
|
|
|
|
* import {MockBackend} from '@angular/http/testing';
|
2015-06-09 18:18:57 -04:00
|
|
|
* var injector = Injector.resolveAndCreate([
|
|
|
|
* BaseRequestOptions,
|
|
|
|
* MockBackend,
|
2015-10-12 14:30:34 -04:00
|
|
|
* provide(Http, {useFactory:
|
2015-06-09 18:18:57 -04:00
|
|
|
* function(backend, defaultOptions) {
|
|
|
|
* return new Http(backend, defaultOptions);
|
|
|
|
* },
|
2015-10-11 01:11:13 -04:00
|
|
|
* deps: [MockBackend, BaseRequestOptions]})
|
2015-06-09 18:18:57 -04:00
|
|
|
* ]);
|
|
|
|
* var http = injector.get(Http);
|
2015-09-25 18:53:32 -04:00
|
|
|
* http.get('request-from-mock-backend.json').subscribe((res:Response) => doSomething(res));
|
2015-06-09 18:18:57 -04:00
|
|
|
* ```
|
2015-04-29 02:07:55 -04:00
|
|
|
*
|
|
|
|
**/
|
|
|
|
@Injectable()
|
|
|
|
export class Http {
|
2015-07-14 20:53:04 -04:00
|
|
|
constructor(protected _backend: ConnectionBackend, protected _defaultOptions: RequestOptions) {}
|
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.
|
|
|
|
*/
|
2016-04-12 12:40:37 -04:00
|
|
|
request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
|
2015-10-01 19:04:20 -04:00
|
|
|
var responseObservable: any;
|
2015-06-19 15:14:12 -04:00
|
|
|
if (isString(url)) {
|
|
|
|
responseObservable = httpRequest(
|
|
|
|
this._backend,
|
2016-02-01 20:05:50 -05:00
|
|
|
new Request(mergeOptions(this._defaultOptions, options, RequestMethod.Get, <string>url)));
|
2015-06-13 19:44:32 -04:00
|
|
|
} else if (url instanceof Request) {
|
2015-06-19 15:14:12 -04:00
|
|
|
responseObservable = httpRequest(this._backend, url);
|
2015-09-18 16:30:05 -04:00
|
|
|
} else {
|
|
|
|
throw makeTypeError('First argument must be a url string or Request instance.');
|
2015-06-13 19:44:32 -04:00
|
|
|
}
|
2015-06-19 15:14:12 -04:00
|
|
|
return responseObservable;
|
2015-06-13 18:49:05 -04:00
|
|
|
}
|
|
|
|
|
2015-06-09 18:18:57 -04:00
|
|
|
/**
|
|
|
|
* Performs a request with `get` http method.
|
|
|
|
*/
|
2015-10-31 02:52:37 -04:00
|
|
|
get(url: string, options?: RequestOptionsArgs): Observable<Response> {
|
2016-04-12 12:40:37 -04:00
|
|
|
return httpRequest(this._backend, new Request(mergeOptions(this._defaultOptions, options,
|
|
|
|
RequestMethod.Get, url)));
|
2015-06-13 18:49:05 -04:00
|
|
|
}
|
|
|
|
|
2015-06-09 18:18:57 -04:00
|
|
|
/**
|
|
|
|
* Performs a request with `post` http method.
|
|
|
|
*/
|
2016-02-26 06:25:55 -05:00
|
|
|
post(url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
|
2015-06-24 03:27:07 -04:00
|
|
|
return httpRequest(
|
2016-04-12 12:40:37 -04:00
|
|
|
this._backend,
|
|
|
|
new Request(mergeOptions(this._defaultOptions.merge(new RequestOptions({body: body})),
|
|
|
|
options, RequestMethod.Post, url)));
|
2015-06-13 18:49:05 -04:00
|
|
|
}
|
|
|
|
|
2015-06-09 18:18:57 -04:00
|
|
|
/**
|
|
|
|
* Performs a request with `put` http method.
|
|
|
|
*/
|
2016-02-26 06:25:55 -05:00
|
|
|
put(url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
|
2015-06-24 03:27:07 -04:00
|
|
|
return httpRequest(
|
2016-04-12 12:40:37 -04:00
|
|
|
this._backend,
|
|
|
|
new Request(mergeOptions(this._defaultOptions.merge(new RequestOptions({body: body})),
|
|
|
|
options, RequestMethod.Put, url)));
|
2015-06-13 18:49:05 -04:00
|
|
|
}
|
|
|
|
|
2015-06-09 18:18:57 -04:00
|
|
|
/**
|
|
|
|
* Performs a request with `delete` http method.
|
|
|
|
*/
|
2015-10-31 02:52:37 -04:00
|
|
|
delete (url: string, options?: RequestOptionsArgs): Observable<Response> {
|
2016-04-12 12:40:37 -04:00
|
|
|
return httpRequest(this._backend, new Request(mergeOptions(this._defaultOptions, options,
|
|
|
|
RequestMethod.Delete, url)));
|
2015-06-13 18:49:05 -04:00
|
|
|
}
|
|
|
|
|
2015-06-09 18:18:57 -04:00
|
|
|
/**
|
|
|
|
* Performs a request with `patch` http method.
|
|
|
|
*/
|
2016-02-26 06:25:55 -05:00
|
|
|
patch(url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
|
2015-06-24 03:27:07 -04:00
|
|
|
return httpRequest(
|
2016-04-12 12:40:37 -04:00
|
|
|
this._backend,
|
|
|
|
new Request(mergeOptions(this._defaultOptions.merge(new RequestOptions({body: body})),
|
|
|
|
options, RequestMethod.Patch, url)));
|
2015-06-13 18:49:05 -04:00
|
|
|
}
|
|
|
|
|
2015-06-09 18:18:57 -04:00
|
|
|
/**
|
|
|
|
* Performs a request with `head` http method.
|
|
|
|
*/
|
2015-10-31 02:52:37 -04:00
|
|
|
head(url: string, options?: RequestOptionsArgs): Observable<Response> {
|
2016-04-12 12:40:37 -04:00
|
|
|
return httpRequest(this._backend, new Request(mergeOptions(this._defaultOptions, options,
|
|
|
|
RequestMethod.Head, url)));
|
2015-06-13 18:49:05 -04:00
|
|
|
}
|
2015-04-29 02:07:55 -04:00
|
|
|
}
|
2015-07-14 20:53:04 -04:00
|
|
|
|
|
|
|
@Injectable()
|
|
|
|
export class Jsonp extends Http {
|
|
|
|
constructor(backend: ConnectionBackend, defaultOptions: RequestOptions) {
|
|
|
|
super(backend, defaultOptions);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
2016-04-12 12:40:37 -04:00
|
|
|
request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
|
2015-10-01 19:04:20 -04:00
|
|
|
var responseObservable: any;
|
2015-07-14 20:53:04 -04:00
|
|
|
if (isString(url)) {
|
2016-02-01 20:05:50 -05:00
|
|
|
url =
|
|
|
|
new Request(mergeOptions(this._defaultOptions, options, RequestMethod.Get, <string>url));
|
2015-07-14 20:53:04 -04:00
|
|
|
}
|
|
|
|
if (url instanceof Request) {
|
2015-12-03 16:44:14 -05:00
|
|
|
if (url.method !== RequestMethod.Get) {
|
2015-07-14 20:53:04 -04:00
|
|
|
makeTypeError('JSONP requests must use GET request method.');
|
|
|
|
}
|
|
|
|
responseObservable = httpRequest(this._backend, url);
|
2015-09-18 16:30:05 -04:00
|
|
|
} else {
|
|
|
|
throw makeTypeError('First argument must be a url string or Request instance.');
|
2015-07-14 20:53:04 -04:00
|
|
|
}
|
|
|
|
return responseObservable;
|
|
|
|
}
|
|
|
|
}
|