The Web apps in this monorepo make HTTP requests and require uniform consistency in how they are executed and handled.
This monorepo demonstrates the same app written with Angular and with Svelte. Each app uses HTTP interceptors. The Angular app uses HttpClient and its interceptors while the Svelte app uses Axios and its interceptors.
by John Papa
Clone this repository
git clone https://github.com/johnpapa/http-interceptors.git tour
cd tour
Choose your app
cd angular-app
# or
cd svelte-app
Install the npm packages
npm install
Run the app
npm run full-stack
There are several apps in this repository.
Folder | Description |
---|---|
angular-http-hard-way | Angular app using HttpClient directly. Adds headers, invokes a busy/progress indicator, and handles authentication errors without interceptors. |
angular-app | Angular app using Http Interceptors. |
svelte-app | Svelte app using Axios Interceptors. |
Here is a list of the features in each app (other than the angular-http-hard-way app)
movies
movies
is readonly to all (no sign in required)Sequence is super important with interceptors. They flow in sequence for requests, and then in the opposite order for responses.
The flow for Axios Interceptors and for Angulars Http Interceptors is different.
Angular's interceptors flow in the order you provide them. If you provide interceptors A, then B, then C, then requests will flow in A->B->C and responses will flow out C->B->A.
// Requests will flow in A->B->C and responses will flow out C->B->A.
export const httpInterceptorProviders = [
/**
* Log Http:
* This logs all HTTP traffic.
* Do this first so it can log the Http call happening in and out (last).
*/
addInterceptor(LogHttpInterceptor),
/**
* ReadOnly:
* This makes sure that HTTP POST, PUT and DELETE are not allowed if the
* user does not have permission. If they do not, then it cancels the request.
* Do this early, before we add headers, get busy, or execute the request.
*/
addInterceptor(ReadOnlyInterceptor),
/**
SSL:
* Ensure SSL by making calls that use http instead use https.
*/
addInterceptor(EnsureSSLInterceptor),
/**
* Auth:
* Add the authentication headers.
*/
addInterceptor(AuthInterceptor),
/**
* CSRF:
* Add the CSRF headers.
*/
addInterceptor(CSRFInterceptor),
/**
* Log headers:
* Log all headers.
* Must come after the headers are stuffed and before the request is made.
*/
addInterceptor(LogHeadersInterceptor),
/**
* Busy:
* Enable and increment the count of HTTP requests, which can be used to show a busy indicator.
* Also decrement the count when responses are received, to eventually turn off the busy indicator.
* This must happen once it is certain a request will be made,
* and right after the response is received.
*/
addInterceptor(BusyInterceptor),
/**
* Transform Response:
* Transform the response, making it easier to consume.
* This could happen anywhere in this particular stream,
* as it operates on the response.
*/
addInterceptor(TransformInterceptor),
];
function addInterceptor<T>(interceptor: T) {
return {
provide: HTTP_INTERCEPTORS,
useClass: interceptor,
multi: true,
};
}
Axios's interceptors flow in the reverse of the order you provide them. If you provide interceptors A, then B, then C, then requests will flow in C->B->A and responses will flow out A->B->C.
Therefore, it is important to add them in the reverse of the order you want them to execute.
... but ...
This might make the code confusing to read, since we think of the order that we add them as being how they are applied. So we:
export function applyHttpInterceptors() {
globalHeaders();
const interceptors = [
/**
* Log Http:
* This logs all HTTP traffic.
* Do this first so it can log the Http call happening in and out (last).
*/
logHttpInterceptor,
/**
* ReadOnly:
* This makes sure that HTTP POST, PUT and DELETE are not allowed if the
* user does not have permission. If they do not, then it cancels the request.
* Do this early, before we add headers, get busy, or execute the request.
*/
readOnlyInterceptor,
/**
SSL:
* Ensure SSL by making calls that use http instead use https.
*/
ensureSSLInterceptor,
/**
* Auth:
* Add the authentication headers.
*/
authInterceptor,
/**
* CSRF:
* Add the CSRF headers.
*/
csrfInterceptor,
/**
* Log headers:
* Log all headers.
* Must come after the headers are stuffed and before the request is made.
*/
logHeadersInterceptor,
/**
* Busy:
* Enable and increment the count of HTTP requests, which can be used to show a busy indicator.
* Also decrement the count when responses are received, to eventually turn off the busy indicator.
* This must happen once it is certain a request will be made,
* and right after the response is received.
*/
busyInterceptor,
/**
* Transform Response:
* Transform the response, making it easier to consume.
* This could happen anywhere in this particular stream,
* as it operates on the response.
*/
transformInterceptor,
];
interceptors.reverse().forEach((f) => f());
}