2

What is the recommended (general) approach for implementing interceptor's logic in Aurelia?

Aurelia doc states following for fetch interceptor's request method:

request [method] takes the Request that will be passed to window.fetch() after interceptors run. It should return the same Request, or create a new one. It can also return a Response to short-circuit the call to fetch() and complete the request immediately. Errors thrown in request interceptors will be handled by requestError interceptors.

Having this in mind, let's consider 3 sample use cases:

  1. Add some information to the request that is being made i.e. route where this request was initiated.

    request(requestMessage) {
        requestMessage.urlHash = window.location.hash;
    
        return requestMessage;
    }
    

    a) Is it a good approach to add some data to the requestMessage config object - mutate current config and return it?

    b) Maybe it is better to return a new object containing config, so requestMessage is immutable? Something like the code below. I guess, fetch isn't going to work with this object passed through instead of requestMessage itself.

    return { 
        request: requestMessage,
        urlHash: window.location.hash,
        someOtherData: data
    };
    
  2. Reject request before it is being created i.e. user token expired, so there is no need to perform a request, that will fail on API side and just reject the request.

    request(requestMessage) {
        if (authenticationService.isTokenExpired()) {
            requestMessage.tokenExpired = true;
    
            // We can use reject or throw here
            // Let's be explicit and return promises as applying interceptors logic
            // is based on promise chaining
            return Promise.reject(requestMessage); 
        }
    
        return Promise.resolve(requestMessage);
    }
    

    a) In this case, the same questions as above, is it recommended to modify requestMessage to add some data to the rejected request? Maybe we should return a custom Error here in the rejected promise, something like new TokenExpiredError(requestMessage)?

    b) Is it good to return different object in rejected promise? For example:

    return Promise.reject({
        request: requestMessage,
        error: new TokenExpiredError('User token expired!')
    }); 
    
  3. Similar use case as in point 1, but let's consider response interceptor method. The logic would be to block request that was made on a different route (hash fragment) and was resolved in current route - basically resolved after navigating to the new route.

    response(responseMessage) {
        const currentUrlHash = window.location.hash;
        const requestMessage = responseMessage.requestMessage;
    
        if (requestMessage.urlHash !== currentUrlHash) {
            responseMessage.blockedRequest = true;
    
            return Promise.reject(responseMessage);
        }
    
        return Promise.resolve(responseMessage);
    }
    

    a) How to handle this case, where we use information set before the request was made?

    b) Where to put that kind of data?

    c) How to handle blocking, maybe rejecting custom Error would be enough, like new BlokedReuqestError(responseMessage) ?

Last one thing, how returning custom object from interceptor's method (not request nor response message) can affect default interceptor added using standard configuration - rejectErrorResponses ?

Thanks in advance for any advice and suggestions :)

matthery
  • 31
  • 3

0 Answers0