1
+ import isFunction from 'lodash/isFunction' ;
1
2
import {
2
3
ERROR_INVALID_CONFIG ,
3
4
} from './const' ;
@@ -6,26 +7,70 @@ import TokenExpiredException from './services/TokenExpiredException';
6
7
import RetryCountExceededException from './services/RetryCountExceededException' ;
7
8
import AccessTokenProvider from './AccessTokenProvider' ;
8
9
10
+ /**
11
+ * Prepares signed request object which can be used for renewing access token
12
+ *
13
+ * @callback createAccessTokenRequest
14
+ * @param {string } refreshToken Refresh token used to sign the request
15
+ * @returns {Request } Signed request object which can be used to get access token
16
+ */
17
+
18
+ /**
19
+ * Parses access token from access token response object
20
+ *
21
+ * @callback parseAccessToken
22
+ * @param {Response } response Response object with access token
23
+ * @returns {string } Access token parsed from response
24
+ */
25
+
26
+ /**
27
+ * Checks whether interceptor will intercept this request or just let it pass through
28
+ *
29
+ * @callback shouldIntercept
30
+ * @param {Request } request Request object
31
+ * @returns {bool } A value indicating whether this request should be intercepted
32
+ */
33
+
34
+ /**
35
+ * Checks whether provided response invalidates current access token
36
+ *
37
+ * @callback shouldInvalidateAccessToken
38
+ * @param {Response } response Response object
39
+ * @returns {bool } A value indicating whether token should be invalidated
40
+ */
41
+
42
+ /**
43
+ * Adds authorization for intercepted requests
44
+ *
45
+ * @callback authorizeRequest
46
+ * @param {Request } request Request object being intercepted
47
+ * @param {string } accessToken Current access token
48
+ * @returns {Request } Authorized request object
49
+ */
50
+
51
+ const getDefaultConfig = ( ) => ( {
52
+ fetchRetryCount : 1 ,
53
+ createAccessTokenRequest : null ,
54
+ shouldIntercept : ( ) => false ,
55
+ shouldInvalidateAccessToken : ( ) => false ,
56
+ isResponseUnauthorized : http . isResponseUnauthorized ,
57
+ parseAccessToken : null ,
58
+ authorizeRequest : null ,
59
+ onAccessTokenChange : null ,
60
+ onResponse : null ,
61
+ } ) ;
62
+
9
63
/**
10
64
* Provides a default implementation for intercepting fetch requests. It will try to resolve
11
65
* unauthorized responses by renewing the access token and repeating the initial request.
12
66
*/
13
- export default class FetchInterceptor {
67
+ class FetchInterceptor {
14
68
constructor ( fetch ) {
15
69
// stores reference to vanilla fetch method
16
70
this . fetch = fetch ;
71
+ this . accessTokenProvider = new AccessTokenProvider ( this . fetch ) ;
17
72
18
- this . config = {
19
- fetchRetryCount : 1 ,
20
- createAccessTokenRequest : null ,
21
- shouldIntercept : ( ) => true ,
22
- shouldInvalidateAccessToken : ( ) => false ,
23
- isResponseUnauthorized : http . isResponseUnauthorized ,
24
- parseAccessToken : null ,
25
- authorizeRequest : null ,
26
- onAccessTokenChange : null ,
27
- onResponse : null ,
28
- } ;
73
+ this . config = getDefaultConfig ( ) ;
29
74
30
75
this . intercept = this . intercept . bind ( this ) ;
31
76
@@ -48,37 +93,28 @@ export default class FetchInterceptor {
48
93
* Configures fetch interceptor with given config object. All required properties can optionally
49
94
* return a promise which will be resolved by fetch interceptor automatically.
50
95
*
51
- * @param config
52
- *
53
- * (Required) Prepare fetch request for renewing new access token
54
- * createAccessTokenRequest: (refreshToken) => request,
55
- *
56
- * (Required) Parses access token from access token response
57
- * parseAccessToken: (response) => accessToken,
58
- *
59
- * (Required) Defines whether interceptor will intercept this request or just let it pass through
60
- * shouldIntercept: (request) => boolean,
61
- *
62
- * (Required) Defines whether access token will be invalidated after this response
63
- * shouldInvalidateAccessToken: (response) => boolean,
64
- *
65
- * (Required) Adds authorization for intercepted requests
66
- * authorizeRequest: (request, accessToken) => authorizedRequest,
67
- *
68
- * Checks if response should be considered unauthorized (by default only 401 responses are
69
- * considered unauthorized. Override this method if you need to trigger token renewal for
70
- * other response statuses.
71
- * isResponseUnauthorized: (response) => boolean,
72
- *
73
- * Number of retries after initial request was unauthorized
74
- * fetchRetryCount: 1,
75
- *
76
- * Event invoked when access token has changed
77
- * onAccessTokenChange: null,
78
- *
79
- * Event invoked when response is resolved
80
- * onResponse: null,
81
- *
96
+ * @param {object } config
97
+ * @param {createAccessTokenRequest } config.createAccessTokenRequest
98
+ * Prepare fetch request for renewing new access token
99
+ * @param {parseAccessToken } config.parseAccessToken
100
+ * Parses access token from access token response
101
+ * @param {shouldIntercept } config.shouldIntercept
102
+ * Defines whether interceptor will intercept this request or just let it pass through
103
+ * @param {shouldInvalidateAccessToken } config.shouldInvalidateAccessToken
104
+ * Defines whether access token will be invalidated after this response
105
+ * @param {authorizeRequest } config.authorizeRequest
106
+ * Adds authorization for intercepted requests
107
+ * @param {function } [config.isResponseUnauthorized=null]
108
+ * Checks if response should be considered unauthorized (by default only 401 responses are
109
+ * considered unauthorized. Override this method if you need to trigger token renewal for
110
+ * other response statuses.
111
+ * @param {number } [config.fetchRetryCount=1]
112
+ * Number of retries after initial request was unauthorized
113
+ * @param {number } [config.onAccessTokenChange=null]
114
+ * Event invoked when access token has changed
115
+ * @param {number } [config.onResponse=null]
116
+ * Event invoked when response is resolved
117
+ * </pre>
82
118
*/
83
119
configure ( config ) {
84
120
this . config = { ...this . config , ...config } ;
@@ -87,13 +123,13 @@ export default class FetchInterceptor {
87
123
throw new Error ( ERROR_INVALID_CONFIG ) ;
88
124
}
89
125
90
- this . accessTokenProvider = new AccessTokenProvider ( this . fetch , this . config ) ;
126
+ this . accessTokenProvider . configure ( this . config ) ;
91
127
}
92
128
93
129
/**
94
130
* Authorizes fetch interceptor with given refresh token
95
- * @param refreshToken
96
- * @param accessToken
131
+ * @param { string } refreshToken Refresh token
132
+ * @param { string } accessToken Access token
97
133
*/
98
134
authorize ( refreshToken , accessToken ) {
99
135
this . accessTokenProvider . authorize ( refreshToken , accessToken ) ;
@@ -114,6 +150,15 @@ export default class FetchInterceptor {
114
150
this . accessTokenProvider . clear ( ) ;
115
151
}
116
152
153
+ /**
154
+ * Clears current authorization and restores default configuration, e.g. interceptor
155
+ * will stop intercepting requests.
156
+ */
157
+ unload ( ) {
158
+ this . clear ( ) ;
159
+ this . config = getDefaultConfig ( ) ;
160
+ }
161
+
117
162
/**
118
163
* Main intercept method, you should chain this inside wrapped fetch call
119
164
* @param args Args initially provided to fetch method
@@ -124,10 +169,11 @@ export default class FetchInterceptor {
124
169
}
125
170
126
171
isConfigValid ( ) {
127
- return this . config . shouldIntercept &&
128
- this . config . authorizeRequest &&
129
- this . config . createAccessTokenRequest &&
130
- this . config . parseAccessToken ;
172
+ return this . config . shouldIntercept && isFunction ( this . config . shouldIntercept ) &&
173
+ this . config . authorizeRequest && isFunction ( this . config . authorizeRequest ) &&
174
+ this . config . isResponseUnauthorized && isFunction ( this . config . isResponseUnauthorized ) &&
175
+ this . config . createAccessTokenRequest && isFunction ( this . config . createAccessTokenRequest ) &&
176
+ this . config . parseAccessToken && isFunction ( this . config . parseAccessToken ) ;
131
177
}
132
178
133
179
resolveIntercept ( resolve , reject , ...args ) {
@@ -357,3 +403,5 @@ export default class FetchInterceptor {
357
403
throw new Error ( error ) ;
358
404
}
359
405
}
406
+
407
+ export default FetchInterceptor ;
0 commit comments