10-4 Interceptors Explained
Key Concepts
- Request Interceptors
- Response Interceptors
- Error Interceptors
- Transforming Requests
- Transforming Responses
- Caching Responses
- Authentication Handling
- Logging Requests and Responses
- Modifying Headers
- Retry Mechanisms
1. Request Interceptors
Request interceptors are functions that intercept HTTP requests before they are sent to the server. They can modify the request configuration, add headers, or perform other preprocessing tasks.
Example:
app.factory('requestInterceptor', function() { return { request: function(config) { config.headers['Authorization'] = 'Bearer ' + getToken(); return config; } }; });
Imagine request interceptors as bouncers at a club. They check (intercept) each guest (request) before allowing them to enter (be sent to the server), ensuring they meet the required criteria (headers, authentication).
2. Response Interceptors
Response interceptors are functions that intercept HTTP responses before they are passed to the application. They can modify the response data, handle errors, or perform other post-processing tasks.
Example:
app.factory('responseInterceptor', function($q) { return { response: function(response) { response.data = transformResponseData(response.data); return response; } }; });
Think of response interceptors as quality control inspectors. They examine (intercept) each product (response) before it reaches the customer (application), ensuring it meets the required standards (data transformation, error handling).
3. Error Interceptors
Error interceptors are functions that intercept HTTP errors. They can handle specific error codes, retry failed requests, or display custom error messages.
Example:
app.factory('errorInterceptor', function($q) { return { responseError: function(rejection) { if (rejection.status === 401) { redirectToLogin(); } return $q.reject(rejection); } }; });
Consider error interceptors as first responders. They quickly address (intercept) any issues (errors) that arise, ensuring the situation is handled appropriately (error handling, redirection).
4. Transforming Requests
Transforming requests involves modifying the request data before it is sent to the server. This can include encoding data, adding timestamps, or converting formats.
Example:
app.factory('transformRequestInterceptor', function() { return { request: function(config) { if (config.method === 'POST') { config.data = encodeData(config.data); } return config; } }; });
Imagine transforming requests as a chef preparing ingredients. Each ingredient (request data) is carefully prepared (transformed) before being used in the recipe (sent to the server).
5. Transforming Responses
Transforming responses involves modifying the response data before it is passed to the application. This can include decoding data, parsing JSON, or formatting the output.
Example:
app.factory('transformResponseInterceptor', function() { return { response: function(response) { if (response.config.url.endsWith('.json')) { response.data = parseJson(response.data); } return response; } }; });
Think of transforming responses as a translator. The translator converts (transforms) the language (response data) from one form (JSON) to another (parsed data) so that it can be understood by the recipient (application).
6. Caching Responses
Caching responses involves storing the results of HTTP requests so that they can be reused without making additional server calls. This can improve performance and reduce server load.
Example:
app.factory('cacheInterceptor', function($cacheFactory) { var cache = $cacheFactory('httpCache'); return { request: function(config) { var cachedResponse = cache.get(config.url); if (cachedResponse) { return cachedResponse; } return config; }, response: function(response) { cache.put(response.config.url, response); return response; } }; });
Consider caching responses as a library. The library stores (caches) books (responses) so that they can be quickly retrieved (reused) without needing to go to the bookstore (server) each time.
7. Authentication Handling
Authentication handling involves adding authentication tokens to requests or redirecting users to a login page if their session expires.
Example:
app.factory('authInterceptor', function($q, $location) { return { request: function(config) { config.headers['Authorization'] = 'Bearer ' + getToken(); return config; }, responseError: function(rejection) { if (rejection.status === 401) { $location.path('/login'); } return $q.reject(rejection); } }; });
Imagine authentication handling as a security guard. The guard ensures that each visitor (request) has the proper credentials (authentication token) and directs them to the correct location (login page) if they do not.
8. Logging Requests and Responses
Logging requests and responses involves recording the details of HTTP transactions for debugging and monitoring purposes.
Example:
app.factory('logInterceptor', function($log) { return { request: function(config) { $log.info('Request:', config); return config; }, response: function(response) { $log.info('Response:', response); return response; } }; });
Think of logging requests and responses as a diary. The diary records (logs) each event (request and response) so that they can be reviewed (debugged) later.
9. Modifying Headers
Modifying headers involves adding, removing, or updating HTTP headers to meet specific requirements or security policies.
Example:
app.factory('headerInterceptor', function() { return { request: function(config) { config.headers['X-Custom-Header'] = 'CustomValue'; delete config.headers['Authorization']; return config; } }; });
Consider modifying headers as a tailor. The tailor adjusts (modifies) the clothing (headers) to fit the wearer (request) perfectly.
10. Retry Mechanisms
Retry mechanisms involve automatically retrying failed HTTP requests. This can improve the reliability of your application by handling transient errors.
Example:
app.factory('retryInterceptor', function($q, $timeout) { return { responseError: function(rejection) { if (rejection.status === 503) { return $timeout(function() { return $http(rejection.config); }, 1000); } return $q.reject(rejection); } }; });
Imagine retry mechanisms as a persistent salesperson. When a customer (server) is not available (error), the salesperson tries again (retries) later to make the sale (complete the request).