Angular - Request Response Workflow



The HttpClient provides several methods to start an HTTP request. All methods return an observable with an optional type variable (Observable<T>).

The observable need to be subscribed to to start the request. Once the observable is subscribed, it starts the request, passes it through a series of registered interceptors, and finally reaches the server. The response is then received from the server and published to the subscribed function.

The workflow of the request is as follows −

  • The user creates a new HttpClient instance, say HTTP through the component constructor:
constructor(private http: HttpClient) { }
  • The user calls any one of the HttpClient methods, say request() by passing the resource information:
let req = this.http.request(<action>, <url>, <body>, <option>)
  • The request() method will create an observable, say request (req) using the given resource information:
let req = this.http.request(<action>, <url>, <body>, <option>)
  • The user will subscribe a callback function to the observable using the subscribe() method:
req.subscribe((data) => console.log(data)); 
  • Once a user subscribes to the Observable, it passes the request to the registered interceptors in the order in which the interceptors are registered.

  • Once the request passes all registered interceptors, Observable will send the request to the server.

  • Observable waits for the server response, and once receives the response from the server, it returns the response to the subscribed function.

  • The subscribed function will do the necessary business logic and set the output to the components variable.

  • The component will render its template using the output of the HttpClient.

A sample request is as follows −

let req = this.http.request('GET', 'http://localhost:8000/api/expense/1')
req.subscribe(data => this.myexpense = data); 

Here,

  • The this.http is the HttpClient instance

  • The request()is the method use to create observable, when subscribed, starts the request.

  • The subscribe() is the method use to subscribe to the returned observable and to subsequently start the request and fetch the response.

  • Finally, the argument to the subscribe method is the callback function used to get the actual responses body content.

HttpClient Arguments

Arguments supported by HttpClients methods are as follows −

  • Resource URI − It is the URL / endpoint representing the resource.
  • Request body − It is the data to be sent to the server along with the request. The data can be either in query string format or JSON format.
  • Request options − It is all other data sent along with the request. It contains query strings, headers, cookies, etc.

Resource URI

All method accept url / endpoint as one of the argument. It represents the resource to be fetched from the server. In our sample application, the url starts with http://localhost:8000/ and one of the possible option is http://localhost:8000/api/expenses. This endpoint will fetch all expenses from the server and send it back to the client in json format.

Request body

All methods accept URL / endpoint as one of the arguments. It represents the resource to be fetched from the server. In our sample application, the URL starts with http://localhost:8000/, and one of the possible options is http://localhost:8000/api/expenses. This endpoint will fetch all expenses from the server and send it back to the client in JSON format −

  • Form data. MIME-type is application/x-www-form-URL-encoded

  • Form data with uploads. MIME type is multipart/form-data

  • Plain text. MIME-type is text/plain

  • JSON. MIME-type is application/json

HttpParams class

Form data can be created using the HttpParams class provided by Angular. HttpParams accepts data in query string format (key/value as key=value and each key/value separated by &). It has methods to add one or more parameters as a sequence by chaining methods together. All methods create a copy of the instance add/remove the parameter (key/value pair) in the copied instance, and return it.

The signature of the HttpParams constructor is as follows −

constructor(options: HttpParamsOptions = {} as HttpParamsOptions)

Where,

The HttpParamsOptionsobject can be created using the below properties:

  • fromString?: string
  • fromObject?: {}

The sample code to create a HttpParams object using a constructor is as follows −

/* using fromString option */
let httpParams = new HttpParams( { fromString: 'a=b*b=c' } )

/* using fromObject option */
let httpParams = new HttpParams( { fromObject: { a: "b", c: "d" } )

The methods supported by HttpParams are as follows −

  • set(): Accepts a parameter and value. Add a new parameter with the given value.

  • delete(): Accepts a parameter. Delete the given parameter.

  • has(): Accepts a parameter. Returns true/false based on the availability of the given parameter.

  • keys(): Accepts nothing. Returns all parameters.

  • get(): Accepts a parameter. Returns the first value of the given parameter.

  • getAll(): Accepts a parameter. Returns all values of the given parameter.

  • append(): Accepts a parameter. Append the value to the given parameter.

  • appendAll(): Accepts an object with multiple parameters. Append the value to all parameters.

  • toString(): Accepts nothing. Returns the object in query string format.

The sample code to create a HttpParams object is as follows −

let formData = new HttpParams();
formData = formData
   .set('item', 'Modified')
   .set('amount', 25);
console.log(formData.toString()) // item=Modified&amount=25

Request options

Irrespective of the method, options are one common argument accepted by all methods and used to represent the request options. Option is a JavaScript object (or hash) with a standard set of request data. Options can have the below entries and represent different aspects of the request and response:

  • observe
  • responseType
  • headers
  • params
  • context
  • reportProgress
  • withCredentials
  • transferCache

Let us learn one by one in the upcoming chapters:

observe

Theobserveoption is used to specify which part of the response has to be observed during the server communication and send back the data to the subscribed function.

Based on the observe option, either the full or part of the response will be returned. The possible values are events, body, and response.

events

Theeventsare used to return the events fired in the response stream from the server. It will return the response as Observable<HttpEvent<R>> type. Here, R is the type of the actual data (response body) to be returned.

let req = this.http.request<Expense>( 'GET', 'http://localhost:8000/api/expense/1', { 
   observe: 'events', 
   responseType : 'json' 
});

Here,

  • JSONis the format used to interpret the response body.
  • Expenseis the type used to convert and return the responses body. Otherwise, it will return the responses body as a generic JavaScript object.

response

The response option is used to return the complete response from the server. It will return the response as Observable<HttpResponse<R>> type. Here, R is the type of the actual data (responses body) to be returned.

let req = this.http.request<Expense>( 'GET', 'http://localhost:8000/api/expense/1', { 
   observe: 'response', 
   responseType : 'json' 
});

Here,

  • JSONis the format used to interpret the responses body.
  • Expenseis the type used to convert and return the responses body. Otherwise, it will return the responses body as a generic JavaScript object.

body

The body is used to return only the body content of the response from the server. It will return the response asObservable<HttpResponse<R>>type, Here, R is a type of the actual data (responses body) to be returned.

let req = this.http.request<Expense>( 'GET','http://localhost:8000/api/expense/1', { 
   observe: 'body', 
   responseType : 'json' 
});

Here,

  • JSONis the format used to interpret the response's body
  • Expenseis the type used to convert and return the responses body. Otherwise, it will return the response's body as a generic JavaScript object.

responseType

The responseType is used to interpret the response's body. It can have four possible values as shown below −

  • arraybuffer
  • blob
  • text
  • json

Let us understand the values and their usage one by one:

arraybuffer

The arraybuffer interprets the response's body as a generic raw binary data buffer and returns Observable. It can be used to stream audio/video content.

let req = this.http.request<Expense>( 'GET', 'http://localhost:8000/api/expense/1', { 
   observe: 'body', 
   responseType : 'arraybuffer' 
});

blob

The blob interprets the response's body as the binary format and returns Observable. It can be used to download large files.

let req = this.http.request<Expense>( 'GET', 'http://localhost:8000/api/expense/1', { 
   observe: 'body', 
   responseType : 'blob' 
});

text

The text interprets the response's body as plain text format and returns Observable. It can be used to represent text-based data.

let req = this.http.request<Expense>( 'GET', 'http://localhost:8000/api/expense/1', { 
   observe: 'body', 
   responseType : 'text' 
});

json

The JSON interprets the response's body in JSON format and returns Observable, where R is the requested type (Expense) of data. It can be used to represent the result in JSON format. It can be further encoded into any type by specifying the type variable (R) in the method as shown below −

let req = this.http.request<Expense>( 'GET', 'http://localhost:8000/api/expense/1', { 
   observe: 'body', 
   responseType : 'json' 
});

Based on the observe and responseType, Httpclient will return Observable with a different type variable. Let us check a few combinations of observe and responseType to better understand the concept.

  • observe => body and responseType => JSON

    Returns the Observable R represents the type variable.

  • observe => response and responseType => JSON

    Returns the Observable<HttpResponse>. R represents the type variable and encodes the response body.

  • observe => events and responseType => JSON

    Returns the Observable<HttpEvent>. R represents the type variable and encodes the response body.

  • observe => events and responseType => arraybuffer

    Returns the Observable<HttpEvent>. The Response body is encoded as ArrayBuffer.

  • observe => response and responseType => blob

    Returns the Observable<HttpEvent>. The Response body is encoded as ArrayBuffer.

  • observe => response and responseType => text

    Returns the Observable<HttpResponse>. The Response body is encoded as ArrayBuffer.

We can combineobserveandresponseTypeto create many more combinations as we need.

headers

The headers specify the HTTP headers. It can include a standard HTTP header as a key/value pair or can encode the data using the HttpHeaders class. A sample header as a key/value pair is as follows:

{ 'Content-type': 'application/json' }

It specifies that the request content type is JSON.

Angular provides a special class,HttpHeadersto compose header details. It accepts header information as an anonymous object and initializes it.

It has methods (set(), append(), and delete()) to add/remove one or more headers in a sequence by chaining methods together.

All methods create a copy of the instance add/remove the header information in the copied instance, and return it.

let httpHeaders = new HttpHeaders( { 'Content-Type': 'application/json' }) 

httpHeaders = httpHeaders
   .set('Accept-Language', 'en-US,en;q=0.5')
   .set('Accept-Encoding', 'gzip, deflate, br');

let options = { 'headers': httpHeaders }

let req = this.http.request<Expense>( 'GET', 'http://localhost:8000/api/expense/1', options );

req.subscribe( (data: Expense) => this.myexpense = data );

Here,

  • httpHeaders is an object used to enclose the HTTP header information to be send to the server. It was created using HttpHeaders class.
  • options is an object enhanced with header information.

The methods supported by HttpHeaders are as follows −

  • set(): Accepts a header and value. Add a new header with the given value.
  • delete(): Accepts a header. Delete the given parameter.
  • has(): Accepts a parameter. Returns true / false based on the availability of the given header.
  • keys(): Accepts nothing. Returns all parameters.
  • get(): Accepts a parameter. Returns first value of the given parameter.
  • getAll(): Accepts a header. Returns all values of the given parameter.
  • append(): Accepts a parameter. Append the value to the given header.
  • appendAll(): Accepts an object with multiple parameter. Append the value to all header.
  • toString(): Accepts nothing. Returns the object in query-string format.

params

Theparamsallow the query string to be set using the HttpParams class. Please check the Request body section for more aboutthe "HttpParams"class.

The sample code to create a HttpParams object and set it in the request is as follows −

let formData = new HttpParams();

formData = formData
   .set('item', 'Modified')
   .set('amount', 25);

console.log(formData.toString()) // item=Modified&amount=25

let req = this.http.request<Expense>('GET', 'http://localhost:8000/api/expense/1', { 
   observe: 'body', 
   responseType : 'json',
   params: formData
});

context

The Context is used to send arbitrary values as key/value pairs with type safety and without key conflict. It is used as a source of information for interceptors acting as middleware between client and server. Angular provides a special class, HttpContext to encode the context information. A sample context is as follows −

// create a key using HttpContextToken
export const IS_AUTH_ENABLED = new HttpContextToken<boolean>(() => false);

// set data for the context
let authContext = new HttpContext().set(IS_AUTH_ENABLED, true)

let req = this.http.request<Expense>('GET', 'http://localhost:8000/api/expense/1', { 
   observe: 'body', 
   responseType : 'json',
   context: authContext
});

Here,

  • HttpContextToken class is used to create the key of the context. It has the option to specify the value type as well.
  • IS_AUTH_ENABLED is the key, and its type is boolean.
  • IS_AUTH_ENABLED is set to true.

We can get the context value using the get() method by passing the token as shown below −

let contextValue = req.context.get<boolean>(IS_AUTH_ENABLED) // true

reportProgress

The reportProgress specifies whether to get the progress of the request (communication) from the server. It can be used to show the progress of large file uploads through web API.

let req = this.http.request<Expense>( 'GET', 'http://localhost:8000/api/expense/1', { 
   observe: 'events', 
   responseType : 'json',
   reportProgress: true
});

withCredentials

The withCredential specifies whether the request should be sent with outgoing credentials (cookies). It accepts a boolean value.

this.http.request<Expense>( 'GET', 'http://localhost:8000/api/expense/1', { 
   observe: 'body', 
   responseType : 'json' 
   withCredentials: true
});

transferCache

The transferCache specifies whether the request should be cached. It accepts the boolean value orHttpTransferCacheOptionsvalue. HttpTransferCacheOptions is used to encode dynamic logic to filter requests to be cached based on a custom filter function and override default cache behavior.

let req = this.http.request<Expense>( 'GET', 'http://localhost:8000/api/expense/1', { 
   observe: 'body', 
   responseType : 'json', 
   transferCache: true
});

HttpClient methods

Methods provided by the HttpClient class for client-server communication are as follows −

  • request()
  • head()
  • get()
  • post()
  • put()
  • patch()
  • delete()
  • jsonp()
  • options()

Let us learn generic request() method in this chapter and other method in subsequent chapters.

The request() method

The request()is the generic method that sends a request to the server with every possible HTTP verb like get, post, patch, etc. It has many overloads. Let us check two main overload functions, one using the Generic option and another one using the HttpRequest object.

  • Generic option − Accepts url, http verb, body content and options object.
  • HttpRequest option − Accepts HttpRequest object

HttpRequest option

Angular provides a class, HttpRequest to represent the complete HTTP request. It has the built-in option to include URL, HTTP method/verb, response type, headers, params, etc.

var httpRequest = new HttpRequest<Expense>('GET', 'https://localhost:8000/api/expense/1', { 
   responseType : 'json' 
});

Here,

  • The this.http is HttpClient instance.
  • GET method is used as HTTP verbs.
  • The endpoint (http://localhost/api/expense/1) will return the expense with an id equal to 1 from the server.
  • The responseType is set as JSON. This will return the body of the response as JSON.

The above sample request object can be used as below to send the request to the server:

var req = this.http.request<Expense>(httpRequest);

req.subscribe(data : HttpEvent<Expense> => { 
   this.myexpense = (data as HttpResponse<Expense>).body as Expense;
}

Here,

  • The request returns the HttpEvent, which is the union of multiple type as shown below −
type HttpEvent<T> = HttpSentEvent | HttpHeaderResponse | HttpResponse<T> | 
   HttpProgressEvent | HttpUserEvent<T>;
  • As we have provided responseType as JSON and set Expense as an object to return, the observable will return HttpResponse<Expense> in the body. So, we converted the returned data object into a HttpResponse<Expense> object and then got the expense from the body property.

Generic option

It accepts four arguments as shown below in the given order:

  • HTTP method / verb
  • url
  • body (optional)
  • options

A sample request is as follows −

let req = this.http.request<Expense>('GET', 'http://localhost:8000/api/expense/1', { 
   observe: 'body', 
   responseType : 'json',
});

req.subscribe(data => { this.myexpense = data });
Advertisements