As mentioned earlier interceptors are function. They will be called with some parameters and can return their modified values.
To better demonstrate it, let’s create each type of interceptor as examples.
Suppose we want to create a request interceptor with these requirements
Content-Type
header to application/json
value if the body
is a plain object
and called with POST
HTTP method.Accept
headers as application/json
for all requests.
|
|
Some important points from above example
frest
is the Frest
instance which call this interceptorrequest
is the original request state before it enters this interceptor TODOPromise
resolve
the Promise with new request configuration. We can also resolve it to the original request, which means there is no modification to the request.What’s the implication if we use this interceptor?
stringify
request body
to JSON string in every requestNow we’ll look at how to create a response interceptor. We’ll use the same case around json
like the request interceptor part.
Content-Type
is compatible with application/json
fetch
Response bodyUsed
is false
.
|
|
Some important points from above example
frest
same as request interceptorrequest
same as request interceptorresponse
the Frest responsePromise
.response
is an object which contains properties:
origin
the original fetch
Response instancebody
parsed value of the response body. It’s response interceptor which will fill this value.fetch
Response instance as origin
property. The body
value is the parsed JSON response.What’s the implication if we use this interceptor?
Response.body
In Frest any non OK response (status outside 2xx
) will result in a thrown error. This is useful so we can have a common place to check for error (instead of checking ok
property in fetch
response).
Let’s look at how we implement error interceptor. Since we have created request and response interceptor to deal with JSON data, we’ll also create an interceptor to parse non OK response, if any. The tasks are
Content-Type
is compatible with application/json
|
|
Some important points from above example
FrestError
Promise
FrestError
instance will have these properties
frest
same as other interceptorrequest
same as other interceptorresponse
same as response interceptorresponse
property can be undefined
, if the error happened before the request is sentbodyUsed
if we want to parse the response bodyIf we want to recover from an error, instead of rejecting the returned promise, we can resolve it with another response. Suppose we want to make another request to retry with different config
|
|
In above example, frest
an request
are the properties of FrestError
in the interceptor arg. They refer to the same Frest instance
and request config when we make the request. If the retry request is
successful, Frest will recover with the resulting response
and the error will not be thrown.
Those 3 interceptor type examples above are already implemented in the official frest-json
package. Check out the documentation of how to use it.
We can add/remove interceptors to Frest instance using either
configuration in constructor or calling add[Type]Interceptor
and
remove[Type]Interceptor
method.
To add them when creating Frest instance:
|
|
To add/remove them using methods of Frest instance:
|
|
By convention, interceptors should
have a unique identifier, assigned
in the function itself (see above examples of creating interceptors).
So we can also remove an interceptor using its id.
Suppose we want to remove jsonRequestInterceptor
created in example above, we can do it like so
|
|
As we can see in ways of adding interceptors above, the interceptors are stored as array depending on their type. When there are multiple interceptors with the same type, they’ll be executed in the order of when they’re added.
|
|
In above example, interceptor1
will be called first.
The returned request, if any, from interceptor1
will be passed down to interceptor2
. It’s the same way with interceptor3
.
This is why we must always check the bodyUsed
property of fetch
Response, in the case of response interceptor. The body
could have been
used/read in other response interceptor, by the time it arrives in our interceptor.