Skip to content

Commit 4e3be25

Browse files
committed
feat(api-request): check token expires and send token update request in advance
1 parent 6efb4a7 commit 4e3be25

File tree

1 file changed

+57
-25
lines changed

1 file changed

+57
-25
lines changed

lib/methods/api-request.js

Lines changed: 57 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ const apiRequest = client => {
77
const getAuth = require('./get-auth')(client)
88
// delete no more valid authentications
99
const deleteAuth = require('./delete-auth')(client)
10+
// handle access token refresh
11+
const refreshToken = require('./refresh-token')(client)
1012

1113
// count per store running request
1214
// prevent rate limit error
@@ -33,6 +35,15 @@ const apiRequest = client => {
3335
options.accessToken = accessToken
3436
}
3537

38+
// fallback dealing with out of date tokens
39+
let isRefreshingToken = false
40+
const askRefreshToken = () => {
41+
if (!isRefreshingToken) {
42+
refreshToken(storeId, myId).catch(console.error)
43+
isRefreshingToken = true
44+
}
45+
}
46+
3647
// send HTTP request
3748
let retries = 0
3849
const send = () => {
@@ -89,32 +100,41 @@ const apiRequest = client => {
89100
return retry(8500, error)
90101
}
91102

92-
if (status === 401 && authenticated && auth.row && config) {
103+
if (status === 401 && authenticated) {
93104
// authentication error
94-
// not authorized by auth scope ?
95-
// mark returned error object
96-
error.appErrorLog = true
97-
98-
// try to log error on app hidden data
99-
ecomClient.store({
100-
...options,
101-
url: '/applications/' + auth.row.application_id + '/hidden_data.json',
102-
method: 'PATCH',
103-
data: {
104-
last_api_error: {
105-
url: config.url,
106-
method: config.method,
107-
response: data
105+
if (data && data.error_code === 132 && !retries) {
106+
// "Token was valid, but expired"
107+
const delayMs = isRefreshingToken ? 2500 : 8500
108+
askRefreshToken()
109+
return retry(delayMs, error)
110+
}
111+
112+
if (auth.row && config) {
113+
// not authorized by auth scope ?
114+
// mark returned error object
115+
error.appErrorLog = true
116+
117+
// try to log error on app hidden data
118+
ecomClient.store({
119+
...options,
120+
url: '/applications/' + auth.row.application_id + '/hidden_data.json',
121+
method: 'PATCH',
122+
data: {
123+
last_api_error: {
124+
url: config.url,
125+
method: config.method,
126+
response: data
127+
}
108128
}
109-
}
110-
}).then(() => {
111-
error.appErrorLogged = true
112-
reject(error)
113-
}).catch(err => {
114-
error.appErrorLog = err
115-
reject(error)
116-
})
117-
return
129+
}).then(() => {
130+
error.appErrorLogged = true
131+
reject(error)
132+
}).catch(err => {
133+
error.appErrorLog = err
134+
reject(error)
135+
})
136+
return
137+
}
118138
}
119139
} else if (!retries) {
120140
// timeout?
@@ -132,15 +152,27 @@ const apiRequest = client => {
132152
send()
133153
} else {
134154
// control requests with delay
155+
let delayMs
135156
let delayFactor = running[storeId]
136157
if (typeof delayFactor !== 'number') {
158+
// first concurrent request with this store
137159
running[storeId] = delayFactor = 0
160+
if (auth.row && auth.row.expires) {
161+
const tokenTimestamp = new Date(auth.row.expires).getTime()
162+
if (tokenTimestamp <= Date.now() + 1000 * 60 * 10) {
163+
// send token update request in advance
164+
askRefreshToken()
165+
if (tokenTimestamp <= Date.now() + 1000 * 5) {
166+
delayMs = 6000
167+
}
168+
}
169+
}
138170
}
139171
running[storeId]++
140172
setTimeout(() => {
141173
running[storeId]--
142174
send()
143-
}, delayFactor * 200)
175+
}, delayMs || delayFactor * 200)
144176
}
145177
}
146178

0 commit comments

Comments
 (0)