HTTP is the primary protocol for browser/server communication.
WebSocket protocol is another important communication technology;
it isn't covered in this page.
Modern browsers support two HTTP-based APIs: XMLHttpRequest (XHR) and JSONP. A few browsers also support Fetch.
The Angular HTTP library simplifies application programming with the XHR and JSONP APIs. This page covers:
- The Tour of Heroes HTTP client demo.
- Fetch data with http.get.
- RxJS library.
- Enable RxJS operators.
- Process the response object.
- Always handle errors.
- Send data to the server.
- Fall back to promises.
- Cross-Origin Requests: Wikipedia example.
- Guarding against Cross-Site Request Forgery.
- Override default request headers (and other request options).
- Appendix: Tour of Heroes in-memory web api.
This page describes server communication with the help of the following demos:
- The Tour of Heroes HTTP client demo.
- Fall back to Promises.
- Cross-Origin Requests: Wikipedia example.
- More fun with observables.
AppComponent orchestrates these demos:
There is nothing remarkable here except for the import of RxJS operators, which is described later.
Providing HTTP services
First, configure the application to use server communication facilities.
Http client communicates with the server using a familiar HTTP request/response protocol.
Http client is one of a family of services in the Angular HTTP library.
When importing from the
@angular/http module, SystemJS knows how to load services from
the Angular HTTP library
systemjs.config.js file maps to that module name.
Before you can use the
Http client, you need to register it as a service provider with the dependency injection system.
Read about providers in the Dependency Injection page.
Register providers by importing other NgModules to the root NgModule in
Begin by importing the necessary members.
The newcomers are the
HttpModule and the
JsonpModule from the Angular HTTP library. For more information about imports and related terminology, see the MDN reference on the
To add these modules to the application, pass them to the
imports array in the root
HttpModule is necessary for making HTTP calls.
Though the JsonpModule isn't necessary for plain HTTP,
there is a JSONP demo later in this page.
Loading its module now saves time.
The Tour of Heroes HTTP client demo
The first demo is a mini-version of the tutorial's "Tour of Heroes" (ToH) application.
This version gets some heroes from the server, displays them in a list, lets the user add new heroes, and saves them to the server.
The app uses the Angular
Http client to communicate via
It works like this:
This demo has a single component, the
HeroListComponent. Here's its template:
It presents the list of heroes with an
Below the list is an input box and an Add Hero button where you can enter the names of new heroes
and add them to the database.
A template reference variable,
newHeroName, accesses the
value of the input box in the
(click) event binding.
When the user clicks the button, that value passes to the component's
addHero method and then
the event binding clears it to make it ready for a new hero name.
Below the button is an area for an error message.
The HeroListComponent class
Here's the component class:
Angular injects a
HeroService into the constructor
and the component calls that service to fetch and save data.
The component does not talk directly to the Angular
The component doesn't know or care how it gets the data.
It delegates to the
This is a golden rule: always delegate data access to a supporting service class.
Although at runtime the component requests heroes immediately after creation,
you don't call the service's
get method in the component's constructor.
Instead, call it inside the
ngOnInit lifecycle hook
and rely on Angular to call
ngOnInit when it instantiates this component.
This is a best practice. Components are easier to test and debug when their constructors are simple, and all real work (especially calling a remote server) is handled in a separate method.
addHero() methods return an
Observable of hero data that the Angular
Http client fetched from the server.
Think of an
Observable as a stream of events published by some source.
To listen for events in this stream, subscribe to the
These subscriptions specify the actions to take when the web request
produces a success event (with the hero data in the event payload) or a fail event (with the error in the payload).
With a basic understanding of the component, you're ready to look inside the
Fetch data with http.get
In many of the previous samples the app faked the interaction with the server by returning mock heroes in a service like this one:
You can revise that
HeroService to get the heroes from the server using the Angular
Http client service:
Notice that the Angular
Http client service is
injected into the
Look closely at how to call
You pass the resource URL to
get and it calls the server which returns heroes.
The server returns heroes once you've set up the in-memory web api described in the appendix below. Alternatively, you can temporarily target a JSON file by changing the endpoint URL:
get method to return a
You'd expect to chain a call to
then() and extract the heroes.
Instead you're calling a
Clearly this is not a promise.
In fact, the
http.get method returns an Observable of HTTP Responses (
Observable<Response>) from the RxJS library
map is one of the RxJS operators.
RxJS ("Reactive Extensions") is a 3rd party library, endorsed by Angular, that implements the asynchronous observable pattern.
All of the Developer Guide samples have installed the RxJS npm package and loaded via
because observables are used widely in Angular applications.
The app needs it when working with the HTTP client. Additionally, you must take a critical extra step to make RxJS observables usable.
Enable RxJS operators
The RxJS library is large. Size matters when building a production application and deploying it to mobile devices. You should include only necessary features.
Accordingly, Angular exposes a stripped down version of
Observable in the
module that lacks most of the operators such as the
map method you
called above in
It's up to you to add the operators you need.
You could add every RxJS operator with a single import statement. While that is the easiest thing to do, you'd pay a penalty in extended launch time and application size because the full library is so big.
Since this app only uses a few operators, it's better to import each
operator and static class method, one-by-one, for a custom Observable
precisely to the app's requirements. Put the
import statements in one
If you forget an operator, the TypeScript compiler warns that it's missing and you'll update this file.
The app doesn't need all of these particular operators in the
HeroService — just
The other operators are for later, in the Wiki example below.
Now continue to the next section to return to the
Process the response object
Remember that the
getHeroes() method used an
extractData helper method to map the
http.get response object to heroes:
response object doesn't hold the data in a form the app can use directly.
You must parse the response data into a JSON object.
Parse to JSON
The response data are in JSON string form.
This is not Angular's own design.
The Angular HTTP client follows the Fetch specification for the
response object returned by the
That spec defines a
Don't expect the decoded JSON to be the heroes array directly.
This server always wraps JSON results in an object with a
property. You have to unwrap it to get the heroes.
This is conventional web API behavior, driven by
Make no assumptions about the server API.
Not all servers return an object with a
Do not return the response object
getHeroes() method could have returned the HTTP response but this wouldn't
be a best practice.
The point of a data service is to hide the server interaction details from consumers.
The component that calls the
HeroService only wants heroes and is kept separate
from getting them, the code dealing with where they come from, and the response object.
http.get does not send the request just yet. This observable is
which means that the request won't go out until something subscribes to the observable.
That something is the HeroListComponent.
Always handle errors
An important part of dealing with I/O is anticipating errors by preparing to catch them and do something with them. One way to handle errors is to pass an error message back to the component for presentation to the user, but only if it says something that the user can understand and act upon.
This simple app conveys that idea, albeit imperfectly, in the way it handles a
catch operator passes the error object from
http to the
handleError method transforms the error into a developer-friendly message,
logs it to the console, and returns the message in a new, failed observable via
HeroListComponent error handling
Back in the
subscribe function has a second function parameter to handle the error message.
It sets an
errorMessage variable that's bound conditionally in the
Want to see it fail? In the
HeroService, reset the api endpoint to a bad value. Afterward, remember to restore it.
Send data to the server
So far you've seen how to retrieve data from a remote location using an HTTP service. Now you'll add the ability to create new heroes and save them in the backend.
You'll write a method for the
HeroListComponent to call, an
addHero() method, that takes
just the name of a new hero and returns an
Hero. It begins like this:
To implement it, you must know the server's API for creating heroes.
This sample's data server follows typical REST guidelines.
It expects a
at the same endpoint as
It expects the new hero data to arrive in the body of the request,
structured like a
Hero entity but without the
The body of the request should look like this:
The server generates the
id and returns the entire
of the new hero including its generated id. The hero arrives tucked inside a response object
with its own
Now that you know how the API works, implement
headers object, the
Content-Type specifies that the body represents JSON.
headers object is used to configure the
options object. The
object is a new instance of
RequestOptions, a class that allows you to specify
certain settings when instantiating a request. In this way, headers is one of the RequestOptions.
options is the third argument of the
post method, as shown above.
getHeroes(), use the
extractData() helper to extract the data
from the response.
Back in the
addHero() method subscribes to the observable returned by the service's
When the data arrive it pushes the new hero object into its
heroes array for presentation to the user.
Fall back to promises
Although the Angular
http client API returns an
Observable<Response> you can turn it into a
It's easy to do, and in simple cases, a promise-based version looks much
like the observable-based version.
While promises may be more familiar, observables have many advantages.
Here is a comparison of the
HeroService using promises versus observables,
highlighting just the parts that are different.
You can follow the promise
then(this.extractData).catch(this.handleError) pattern as in
Alternatively, you can call
toPromise(success, fail). The observable's
map callback moves to the first success parameter and its
catch callback to the second fail parameter in this pattern:
errorHandler forwards an error message as a failed promise instead of a failed
The diagnostic log to console is just one more
then in the promise chain.
You have to adjust the calling component to expect a
Promise instead of an
The only obvious difference is that you call
then on the returned promise instead of
Both methods take the same functional arguments.
The less obvious but critical difference is that these two methods return very different results.
then returns another promise. You can keep chaining more
catch calls, getting a new promise each time.
subscribe method returns a
Subscription is not another
It's the end of the line for observables. You can't call
map on it or call
Subscription object has a different purpose, signified by its primary method,
Cross-Origin Requests: Wikipedia example
You just learned how to make
XMLHttpRequests using the Angular
This is the most common approach for server communication, but it doesn't work in all scenarios.
For security reasons, web browsers block
XHR calls to a remote server whose origin is different from the origin of the web page.
The origin is the combination of URI scheme, hostname, and port number.
This is called the same-origin policy.
Some servers do not support CORS but do support an older, read-only alternative called JSONP. Wikipedia is one such server.
This Stack Overflow answer covers many details of JSONP.
Here is a simple search that shows suggestions from Wikipedia as the user types in a text box:
Wikipedia offers a modern
CORS API and a legacy
JSONP search API. This example uses the latter.
Jsonp service both extends the
Http service for JSONP and restricts you to
All other HTTP methods throw an error because JSONP is a read-only facility.
As always, wrap the interaction with an Angular data access client service inside a dedicated service, here called
The constructor expects Angular to inject its
jsonp service, which
is available because
JsonpModule is in the root
The Wikipedia "opensearch" API
expects four parameters (key/value pairs) to arrive in the request URL's query string.
The keys are
The value of the
search key is the user-supplied search term to find in Wikipedia.
The other three are the fixed values "opensearch", "json", and "JSONP_CALLBACK" respectively.
JSONP technique requires that you pass a callback function name to the server in the query string:
All of this happens under the hood.
If you're looking for articles with the word "Angular", you could construct the query string by hand and call
jsonp like this:
In more parameterized examples you could build the query string with the Angular
This time you call
jsonp with two arguments: the
wikiUrl and an options object whose
search property is the
Jsonp flattens the
params object into the same query string you saw earlier, putting the request on the wire.
Now that you have a service that can query the Wikipedia API turn to the component (template and class) that takes user input and displays search results.
The template presents an
<input> element search box to gather search terms from the user,
and calls a
search(term) method after each
search(term) method delegates to the
WikipediaService, which returns an
observable array of string results (
Instead of subscribing to the observable inside the component, as in the
the app forwards the observable result to the template (via
items) where the
ngFor handles the subscription. Read more about async pipes
in the Pipes page.
The async pipe is a good choice in read-only components where the component has no need to interact with the data.
HeroListComponent can't use the pipe because
addHero() pushes newly created heroes into the list.
A wasteful app
The wikipedia search makes too many calls to the server. It is inefficient, and potentially expensive on mobile devices with limited data plans.
1. Wait for the user to stop typing
Presently, the code calls the server after every key stroke. It should only make requests when the user stops typing . Here's how it will work after refactoring:
2. Search when the search term changes
Suppose a user enters the word angular in the search box and pauses for a while. The application issues a search request for angular.
Then the user backspaces over the last three letters, lar, and immediately re-types lar before pausing once more. The search term is still angular. The app shouldn't make another request.
3. Cope with out-of-order responses
The user enters angular, pauses, clears the search box, and enters http. The application issues two search requests, one for angular and one for http.
Which response arrives first? It's unpredictable. A load balancer could dispatch the requests to two different servers with different response times. The results from the first angular request might arrive after the later http results. The user will be confused if the angular results display to the http query.
When there are multiple requests in-flight, the app should present the responses in the original request order. That won't happen if angular results arrive last.
More fun with observables
You can address these problems and improve the app with the help of some nifty observable operators.
You could make changes to the
WikipediaService, but for a better
user experience, create a copy of the
WikiComponent instead and make it smarter.
WikiSmartComponent which uses the same template.
Create a stream of search terms
The template still binds to the search box
keyup event and passes the complete search box value
into the component's
search method after every user keystroke.
WikiSmartComponent turns the search box values into an observable stream of search terms
with the help of a
Subject which you import from the RxJS observable library:
The component creates a
searchTermStream as a
Subject of type
search method adds each new search box value to that stream via the subject's
Listen for search terms
Earlier, you passed each search term directly to the service and bound the template to the service results.
Now you listen to the stream of search terms, manipulating the stream before it reaches the
Wait for the user to stop typing for at least 300 milliseconds (debounceTime). Only changed search values make it through to the service (distinctUntilChanged).
WikipediaService returns a separate observable of string arrays (
Observable<string>) for each request.
There could be multiple requests in-flight, all awaiting the server's reply,
which means multiple observables-of-strings could arrive at any moment in any order.
(formerly known as
flatMapLatest) returns a new observable that combines these
re-arranges them in their original request order,
and delivers to subscribers only the most recent search results.
The displayed list of search results stays in sync with the user's sequence of search terms.
You added the
switchMap operators to the RxJS
rxjs-operators as described above.
Guarding against Cross-Site Request Forgery
In a cross-site request forgery (CSRF or XSRF), an attacker tricks the user into visiting a different web page with malignant code that secretly sends a malicious request to your application's web server,
The server and client application must work together to thwart this attack.
Http client does its part by applying a default
CookieXSRFStrategy automatically to all requests.
CookieXSRFStrategy supports a common anti-XSRF technique in which the server sends a randomly
generated authentication token in a cookie named
The HTTP client adds an
X-XSRF-TOKEN header with that token value to subsequent requests.
The server receives both the cookie and the header, compares them, and processes the request only if the cookie and header match.
See the XSRF topic on the Security page for more information about XSRF and Angular's
XSRFStrategy counter measures.
Override default request headers (and other request options)
Request options (such as headers) are merged into the
before the request is processed.
HttpModule provides these default options via the
You can override these defaults to suit your application needs.
by creating a custom sub-class of
that sets the default options for the application.
This sample creates a class that sets the default
Content-Type header to JSON.
It exports a constant with the necessary
RequestOptions provider to simplify registration in
Then it registers the provider in the root
Remember to include this provider during setup when unit testing the app's HTTP services.
After this change, the
header option setting in
HeroService.addHero is no longer necessary,
You can confirm that
DefaultRequestOptions is working by examing HTTP requests in the browser developer tools' network tab.
If you're short-circuiting the server call with something like the in-memory web api,
try commenting-out the
addHero header option,
set a breakpoint on the POST call, and step through the request processing
to verify the header is there.
Individual requests options, like this one, take precedence over the default
It might be wise to keep the
addHero request header setting for extra safety.
Appendix: Tour of Heroes in-memory web api
If the app only needed to retrieve data, you could get the heroes from a
You wrap the heroes array in an object with a
data property for the same reason that a data server does:
to mitigate the security risk
posed by top-level JSON arrays.
You'd set the endpoint to the JSON file like this:
The get heroes scenario would work, but since the app can't save changes to a JSON file, it needs a web API server. Because there isn't a real server for this demo, it substitutes the Angular in-memory web api simulator for the actual XHR backend service.
The in-memory web api is not part of Angular proper.
It's an optional service in its own
library installed with npm (see
See the README file for configuration options, default behaviors, and limitations.
The in-memory web API gets its data from a custom application class with a
method that returns a map whose keys are collection names and whose values
are arrays of objects in those collections.
Here's the class for this sample, based on the JSON data:
Ensure that the
HeroService endpoint refers to the web API:
Finally, redirect client HTTP requests to the in-memory web API by
InMemoryWebApiModule to the
At the same time, call its
forRoot configuration method with the
How it works
http service delegates the client/server communication tasks
to a helper service called the
Using standard Angular provider registration techniques, the
replaces the default
XHRBackend service with its own in-memory alternative.
At the same time, the
forRoot method initializes the in-memory web API with the seed data from the mock hero dataset.
forRoot method name is a strong reminder that you should only call the
while setting the metadata for the root
AppModule. Don't call it again.
Here is the final, revised version of app/app.module.ts, demonstrating these steps.
InMemoryWebApiModule after the
HttpModule to ensure that
XHRBackend provider of the
InMemoryWebApiModule supersedes all others.
See the full source code in the