add more fine-grained request timeouts (#387)

* add more fine-grained request timeouts

fixes #381

* tweak timeout
This commit is contained in:
Nolan Lawson 2018-06-13 07:38:36 -07:00 committed by GitHub
parent a0d3a89180
commit 5f4e869eeb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 92 additions and 114 deletions

View File

@ -1,17 +1,17 @@
import { getWithTimeout, postWithTimeout } from '../_utils/ajax' import { DEFAULT_TIMEOUT, get, post, WRITE_TIMEOUT } from '../_utils/ajax'
import { auth, basename } from '../_api/utils' import { auth, basename } from '../_api/utils'
export async function getFollowRequests (instanceName, accessToken) { export async function getFollowRequests (instanceName, accessToken) {
let url = `${basename(instanceName)}/api/v1/follow_requests` let url = `${basename(instanceName)}/api/v1/follow_requests`
return getWithTimeout(url, auth(accessToken)) return get(url, auth(accessToken), {timeout: DEFAULT_TIMEOUT})
} }
export async function authorizeFollowRequest (instanceName, accessToken, id) { export async function authorizeFollowRequest (instanceName, accessToken, id) {
let url = `${basename(instanceName)}/api/v1/follow_requests/${id}/authorize` let url = `${basename(instanceName)}/api/v1/follow_requests/${id}/authorize`
return postWithTimeout(url, null, auth(accessToken)) return post(url, null, auth(accessToken), {timeout: WRITE_TIMEOUT})
} }
export async function rejectFollowRequest (instanceName, accessToken, id) { export async function rejectFollowRequest (instanceName, accessToken, id) {
let url = `${basename(instanceName)}/api/v1/follow_requests/${id}/reject` let url = `${basename(instanceName)}/api/v1/follow_requests/${id}/reject`
return postWithTimeout(url, null, auth(accessToken)) return post(url, null, auth(accessToken), {timeout: WRITE_TIMEOUT})
} }

View File

@ -1,12 +1,12 @@
import { auth, basename } from './utils' import { auth, basename } from './utils'
import { postWithTimeout } from '../_utils/ajax' import { post, WRITE_TIMEOUT } from '../_utils/ajax'
export async function blockAccount (instanceName, accessToken, accountId) { export async function blockAccount (instanceName, accessToken, accountId) {
let url = `${basename(instanceName)}/api/v1/accounts/${accountId}/block` let url = `${basename(instanceName)}/api/v1/accounts/${accountId}/block`
return postWithTimeout(url, null, auth(accessToken)) return post(url, null, auth(accessToken), {timeout: WRITE_TIMEOUT})
} }
export async function unblockAccount (instanceName, accessToken, accountId) { export async function unblockAccount (instanceName, accessToken, accountId) {
let url = `${basename(instanceName)}/api/v1/accounts/${accountId}/unblock` let url = `${basename(instanceName)}/api/v1/accounts/${accountId}/unblock`
return postWithTimeout(url, null, auth(accessToken)) return post(url, null, auth(accessToken), {timeout: WRITE_TIMEOUT})
} }

View File

@ -1,14 +1,14 @@
import { getWithTimeout, paramsString } from '../_utils/ajax' import { DEFAULT_TIMEOUT, get, paramsString } from '../_utils/ajax'
import { auth, basename } from './utils' import { auth, basename } from './utils'
export async function getBlockedAccounts (instanceName, accessToken, limit = 80) { export async function getBlockedAccounts (instanceName, accessToken, limit = 80) {
let url = `${basename(instanceName)}/api/v1/blocks` let url = `${basename(instanceName)}/api/v1/blocks`
url += '?' + paramsString({ limit }) url += '?' + paramsString({ limit })
return getWithTimeout(url, auth(accessToken)) return get(url, auth(accessToken), {timeout: DEFAULT_TIMEOUT})
} }
export async function getMutedAccounts (instanceName, accessToken, limit = 80) { export async function getMutedAccounts (instanceName, accessToken, limit = 80) {
let url = `${basename(instanceName)}/api/v1/mutes` let url = `${basename(instanceName)}/api/v1/mutes`
url += '?' + paramsString({ limit }) url += '?' + paramsString({ limit })
return getWithTimeout(url, auth(accessToken)) return get(url, auth(accessToken), {timeout: DEFAULT_TIMEOUT})
} }

View File

@ -1,7 +1,7 @@
import { auth, basename } from './utils' import { auth, basename } from './utils'
import { deleteWithTimeout } from '../_utils/ajax' import { del, WRITE_TIMEOUT } from '../_utils/ajax'
export async function deleteStatus (instanceName, accessToken, statusId) { export async function deleteStatus (instanceName, accessToken, statusId) {
let url = `${basename(instanceName)}/api/v1/statuses/${statusId}` let url = `${basename(instanceName)}/api/v1/statuses/${statusId}`
return deleteWithTimeout(url, auth(accessToken)) return del(url, auth(accessToken), {timeout: WRITE_TIMEOUT})
} }

View File

@ -1,7 +1,7 @@
import { basename } from './utils' import { basename } from './utils'
import { getWithTimeout } from '../_utils/ajax' import { DEFAULT_TIMEOUT, get } from '../_utils/ajax'
export async function getCustomEmoji (instanceName) { export async function getCustomEmoji (instanceName) {
let url = `${basename(instanceName)}/api/v1/custom_emojis` let url = `${basename(instanceName)}/api/v1/custom_emojis`
return getWithTimeout(url) return get(url, null, {timeout: DEFAULT_TIMEOUT})
} }

View File

@ -1,12 +1,12 @@
import { post } from '../_utils/ajax' import { post, WRITE_TIMEOUT } from '../_utils/ajax'
import { basename, auth } from './utils' import { basename, auth } from './utils'
export async function favoriteStatus (instanceName, accessToken, statusId) { export async function favoriteStatus (instanceName, accessToken, statusId) {
let url = `${basename(instanceName)}/api/v1/statuses/${statusId}/favourite` let url = `${basename(instanceName)}/api/v1/statuses/${statusId}/favourite`
return post(url, null, auth(accessToken)) return post(url, null, auth(accessToken), {timeout: WRITE_TIMEOUT})
} }
export async function unfavoriteStatus (instanceName, accessToken, statusId) { export async function unfavoriteStatus (instanceName, accessToken, statusId) {
let url = `${basename(instanceName)}/api/v1/statuses/${statusId}/unfavourite` let url = `${basename(instanceName)}/api/v1/statuses/${statusId}/unfavourite`
return post(url, null, auth(accessToken)) return post(url, null, auth(accessToken), {timeout: WRITE_TIMEOUT})
} }

View File

@ -1,12 +1,12 @@
import { postWithTimeout } from '../_utils/ajax' import { post, WRITE_TIMEOUT } from '../_utils/ajax'
import { auth, basename } from './utils' import { auth, basename } from './utils'
export async function followAccount (instanceName, accessToken, accountId) { export async function followAccount (instanceName, accessToken, accountId) {
let url = `${basename(instanceName)}/api/v1/accounts/${accountId}/follow` let url = `${basename(instanceName)}/api/v1/accounts/${accountId}/follow`
return postWithTimeout(url, null, auth(accessToken)) return post(url, null, auth(accessToken), {timeout: WRITE_TIMEOUT})
} }
export async function unfollowAccount (instanceName, accessToken, accountId) { export async function unfollowAccount (instanceName, accessToken, accountId) {
let url = `${basename(instanceName)}/api/v1/accounts/${accountId}/unfollow` let url = `${basename(instanceName)}/api/v1/accounts/${accountId}/unfollow`
return postWithTimeout(url, null, auth(accessToken)) return post(url, null, auth(accessToken), {timeout: WRITE_TIMEOUT})
} }

View File

@ -1,14 +1,14 @@
import { getWithTimeout, paramsString } from '../_utils/ajax' import { get, paramsString, DEFAULT_TIMEOUT } from '../_utils/ajax'
import { auth, basename } from './utils' import { auth, basename } from './utils'
export async function getFollows (instanceName, accessToken, accountId, limit = 80) { export async function getFollows (instanceName, accessToken, accountId, limit = 80) {
let url = `${basename(instanceName)}/api/v1/accounts/${accountId}/following` let url = `${basename(instanceName)}/api/v1/accounts/${accountId}/following`
url += '?' + paramsString({ limit }) url += '?' + paramsString({ limit })
return getWithTimeout(url, auth(accessToken)) return get(url, auth(accessToken), {timeout: DEFAULT_TIMEOUT})
} }
export async function getFollowers (instanceName, accessToken, accountId, limit = 80) { export async function getFollowers (instanceName, accessToken, accountId, limit = 80) {
let url = `${basename(instanceName)}/api/v1/accounts/${accountId}/followers` let url = `${basename(instanceName)}/api/v1/accounts/${accountId}/followers`
url += '?' + paramsString({ limit }) url += '?' + paramsString({ limit })
return getWithTimeout(url, auth(accessToken)) return get(url, auth(accessToken), {timeout: DEFAULT_TIMEOUT})
} }

View File

@ -1,7 +1,7 @@
import { getWithTimeout } from '../_utils/ajax' import { get, DEFAULT_TIMEOUT } from '../_utils/ajax'
import { basename } from './utils' import { basename } from './utils'
export function getInstanceInfo (instanceName) { export function getInstanceInfo (instanceName) {
let url = `${basename(instanceName)}/api/v1/instance` let url = `${basename(instanceName)}/api/v1/instance`
return getWithTimeout(url) return get(url, null, {timeout: DEFAULT_TIMEOUT})
} }

View File

@ -1,7 +1,7 @@
import { getWithTimeout } from '../_utils/ajax' import { get, DEFAULT_TIMEOUT } from '../_utils/ajax'
import { auth, basename } from './utils' import { auth, basename } from './utils'
export function getLists (instanceName, accessToken) { export function getLists (instanceName, accessToken) {
let url = `${basename(instanceName)}/api/v1/lists` let url = `${basename(instanceName)}/api/v1/lists`
return getWithTimeout(url, auth(accessToken)) return get(url, auth(accessToken), {timeout: DEFAULT_TIMEOUT})
} }

View File

@ -1,5 +1,5 @@
import { auth, basename } from './utils' import { auth, basename } from './utils'
import { postWithTimeout, putWithTimeout } from '../_utils/ajax' import { post, put, MEDIA_WRITE_TIMEOUT, WRITE_TIMEOUT } from '../_utils/ajax'
export async function uploadMedia (instanceName, accessToken, file, description) { export async function uploadMedia (instanceName, accessToken, file, description) {
let formData = new FormData() let formData = new FormData()
@ -8,10 +8,10 @@ export async function uploadMedia (instanceName, accessToken, file, description)
formData.append('description', description) formData.append('description', description)
} }
let url = `${basename(instanceName)}/api/v1/media` let url = `${basename(instanceName)}/api/v1/media`
return postWithTimeout(url, formData, auth(accessToken)) return post(url, formData, auth(accessToken), {timeout: MEDIA_WRITE_TIMEOUT})
} }
export async function putMediaDescription (instanceName, accessToken, mediaId, description) { export async function putMediaDescription (instanceName, accessToken, mediaId, description) {
let url = `${basename(instanceName)}/api/v1/media/${mediaId}` let url = `${basename(instanceName)}/api/v1/media/${mediaId}`
return putWithTimeout(url, {description}, auth(accessToken)) return put(url, {description}, auth(accessToken), {timeout: WRITE_TIMEOUT})
} }

View File

@ -1,12 +1,12 @@
import { auth, basename } from './utils' import { auth, basename } from './utils'
import { postWithTimeout } from '../_utils/ajax' import { post, WRITE_TIMEOUT } from '../_utils/ajax'
export async function muteAccount (instanceName, accessToken, accountId) { export async function muteAccount (instanceName, accessToken, accountId) {
let url = `${basename(instanceName)}/api/v1/accounts/${accountId}/mute` let url = `${basename(instanceName)}/api/v1/accounts/${accountId}/mute`
return postWithTimeout(url, null, auth(accessToken)) return post(url, null, auth(accessToken), {timeout: WRITE_TIMEOUT})
} }
export async function unmuteAccount (instanceName, accessToken, accountId) { export async function unmuteAccount (instanceName, accessToken, accountId) {
let url = `${basename(instanceName)}/api/v1/accounts/${accountId}/unmute` let url = `${basename(instanceName)}/api/v1/accounts/${accountId}/unmute`
return postWithTimeout(url, null, auth(accessToken)) return post(url, null, auth(accessToken), {timeout: WRITE_TIMEOUT})
} }

View File

@ -1,12 +1,12 @@
import { auth, basename } from './utils' import { auth, basename } from './utils'
import { postWithTimeout } from '../_utils/ajax' import { post, WRITE_TIMEOUT } from '../_utils/ajax'
export async function muteConversation (instanceName, accessToken, statusId) { export async function muteConversation (instanceName, accessToken, statusId) {
let url = `${basename(instanceName)}/api/v1/statuses/${statusId}/mute` let url = `${basename(instanceName)}/api/v1/statuses/${statusId}/mute`
return postWithTimeout(url, null, auth(accessToken)) return post(url, null, auth(accessToken), {timeout: WRITE_TIMEOUT})
} }
export async function unmuteConversation (instanceName, accessToken, statusId) { export async function unmuteConversation (instanceName, accessToken, statusId) {
let url = `${basename(instanceName)}/api/v1/statuses/${statusId}/unmute` let url = `${basename(instanceName)}/api/v1/statuses/${statusId}/unmute`
return postWithTimeout(url, null, auth(accessToken)) return post(url, null, auth(accessToken), {timeout: WRITE_TIMEOUT})
} }

View File

@ -1,4 +1,4 @@
import { postWithTimeout, paramsString } from '../_utils/ajax' import { post, paramsString, WRITE_TIMEOUT } from '../_utils/ajax'
import { basename } from './utils' import { basename } from './utils'
const WEBSITE = 'https://pinafore.social' const WEBSITE = 'https://pinafore.social'
@ -7,12 +7,12 @@ const CLIENT_NAME = 'Pinafore'
export function registerApplication (instanceName, redirectUri) { export function registerApplication (instanceName, redirectUri) {
const url = `${basename(instanceName)}/api/v1/apps` const url = `${basename(instanceName)}/api/v1/apps`
return postWithTimeout(url, { return post(url, {
client_name: CLIENT_NAME, client_name: CLIENT_NAME,
redirect_uris: redirectUri, redirect_uris: redirectUri,
scopes: SCOPES, scopes: SCOPES,
website: WEBSITE website: WEBSITE
}) }, null, {timeout: WRITE_TIMEOUT})
} }
export function generateAuthLink (instanceName, clientId, redirectUri) { export function generateAuthLink (instanceName, clientId, redirectUri) {
@ -27,11 +27,11 @@ export function generateAuthLink (instanceName, clientId, redirectUri) {
export function getAccessTokenFromAuthCode (instanceName, clientId, clientSecret, code, redirectUri) { export function getAccessTokenFromAuthCode (instanceName, clientId, clientSecret, code, redirectUri) {
let url = `${basename(instanceName)}/oauth/token` let url = `${basename(instanceName)}/oauth/token`
return postWithTimeout(url, { return post(url, {
client_id: clientId, client_id: clientId,
client_secret: clientSecret, client_secret: clientSecret,
redirect_uri: redirectUri, redirect_uri: redirectUri,
grant_type: 'authorization_code', grant_type: 'authorization_code',
code: code code: code
}) }, null, {timeout: WRITE_TIMEOUT})
} }

View File

@ -1,12 +1,12 @@
import { postWithTimeout } from '../_utils/ajax' import { post, WRITE_TIMEOUT } from '../_utils/ajax'
import { auth, basename } from './utils' import { auth, basename } from './utils'
export async function pinStatus (instanceName, accessToken, statusId) { export async function pinStatus (instanceName, accessToken, statusId) {
let url = `${basename(instanceName)}/api/v1/statuses/${statusId}/pin` let url = `${basename(instanceName)}/api/v1/statuses/${statusId}/pin`
return postWithTimeout(url, null, auth(accessToken)) return post(url, null, auth(accessToken), {timeout: WRITE_TIMEOUT})
} }
export async function unpinStatus (instanceName, accessToken, statusId) { export async function unpinStatus (instanceName, accessToken, statusId) {
let url = `${basename(instanceName)}/api/v1/statuses/${statusId}/unpin` let url = `${basename(instanceName)}/api/v1/statuses/${statusId}/unpin`
return postWithTimeout(url, null, auth(accessToken)) return post(url, null, auth(accessToken), {timeout: WRITE_TIMEOUT})
} }

View File

@ -1,4 +1,4 @@
import { getWithTimeout, paramsString } from '../_utils/ajax' import { get, paramsString, DEFAULT_TIMEOUT } from '../_utils/ajax'
import { auth, basename } from './utils' import { auth, basename } from './utils'
export async function getPinnedStatuses (instanceName, accessToken, accountId) { export async function getPinnedStatuses (instanceName, accessToken, accountId) {
@ -7,5 +7,5 @@ export async function getPinnedStatuses (instanceName, accessToken, accountId) {
limit: 40, limit: 40,
pinned: true pinned: true
}) })
return getWithTimeout(url, auth(accessToken)) return get(url, auth(accessToken), {timeout: DEFAULT_TIMEOUT})
} }

View File

@ -1,14 +1,14 @@
import { getWithTimeout, paramsString } from '../_utils/ajax' import { get, paramsString, DEFAULT_TIMEOUT } from '../_utils/ajax'
import { auth, basename } from './utils' import { auth, basename } from './utils'
export async function getReblogs (instanceName, accessToken, statusId, limit = 80) { export async function getReblogs (instanceName, accessToken, statusId, limit = 80) {
let url = `${basename(instanceName)}/api/v1/statuses/${statusId}/reblogged_by` let url = `${basename(instanceName)}/api/v1/statuses/${statusId}/reblogged_by`
url += '?' + paramsString({ limit }) url += '?' + paramsString({ limit })
return getWithTimeout(url, auth(accessToken)) return get(url, auth(accessToken), {timeout: DEFAULT_TIMEOUT})
} }
export async function getFavorites (instanceName, accessToken, statusId, limit = 80) { export async function getFavorites (instanceName, accessToken, statusId, limit = 80) {
let url = `${basename(instanceName)}/api/v1/statuses/${statusId}/favourited_by` let url = `${basename(instanceName)}/api/v1/statuses/${statusId}/favourited_by`
url += '?' + paramsString({ limit }) url += '?' + paramsString({ limit })
return getWithTimeout(url, auth(accessToken)) return get(url, auth(accessToken), {timeout: DEFAULT_TIMEOUT})
} }

View File

@ -1,12 +1,12 @@
import { postWithTimeout } from '../_utils/ajax' import { post, WRITE_TIMEOUT } from '../_utils/ajax'
import { auth, basename } from './utils' import { auth, basename } from './utils'
export async function approveFollowRequest (instanceName, accessToken, accountId) { export async function approveFollowRequest (instanceName, accessToken, accountId) {
let url = `${basename(instanceName)}/api/v1/follow_requests/${accountId}/authorize` let url = `${basename(instanceName)}/api/v1/follow_requests/${accountId}/authorize`
return postWithTimeout(url, null, auth(accessToken)) return post(url, null, auth(accessToken), {timeout: WRITE_TIMEOUT})
} }
export async function rejectFollowRequest (instanceName, accessToken, accountId) { export async function rejectFollowRequest (instanceName, accessToken, accountId) {
let url = `${basename(instanceName)}/api/v1/follow_requests/${accountId}/reject` let url = `${basename(instanceName)}/api/v1/follow_requests/${accountId}/reject`
return postWithTimeout(url, null, auth(accessToken)) return post(url, null, auth(accessToken), {timeout: WRITE_TIMEOUT})
} }

View File

@ -1,4 +1,4 @@
import { getWithTimeout, paramsString } from '../_utils/ajax' import { get, paramsString, DEFAULT_TIMEOUT } from '../_utils/ajax'
import { auth, basename } from './utils' import { auth, basename } from './utils'
export function search (instanceName, accessToken, query) { export function search (instanceName, accessToken, query) {
@ -6,5 +6,5 @@ export function search (instanceName, accessToken, query) {
q: query, q: query,
resolve: true resolve: true
}) })
return getWithTimeout(url, auth(accessToken)) return get(url, auth(accessToken), {timeout: DEFAULT_TIMEOUT})
} }

View File

@ -1,5 +1,5 @@
import { auth, basename } from './utils' import { auth, basename } from './utils'
import { postWithTimeout } from '../_utils/ajax' import { post, WRITE_TIMEOUT } from '../_utils/ajax'
export async function postStatus (instanceName, accessToken, text, inReplyToId, mediaIds, export async function postStatus (instanceName, accessToken, text, inReplyToId, mediaIds,
sensitive, spoilerText, visibility) { sensitive, spoilerText, visibility) {
@ -21,5 +21,5 @@ export async function postStatus (instanceName, accessToken, text, inReplyToId,
} }
} }
return postWithTimeout(url, body, auth(accessToken)) return post(url, body, auth(accessToken), {timeout: WRITE_TIMEOUT})
} }

View File

@ -1,4 +1,4 @@
import { getWithTimeout, paramsString } from '../_utils/ajax' import { get, paramsString, DEFAULT_TIMEOUT } from '../_utils/ajax'
import { auth, basename } from './utils' import { auth, basename } from './utils'
function getTimelineUrlPath (timeline) { function getTimelineUrlPath (timeline) {
@ -57,12 +57,12 @@ export function getTimeline (instanceName, accessToken, timeline, maxId, since)
// special case - this is a list of descendents and ancestors // special case - this is a list of descendents and ancestors
let statusUrl = `${basename(instanceName)}/api/v1/statuses/${timeline.split('/').slice(-1)[0]}` let statusUrl = `${basename(instanceName)}/api/v1/statuses/${timeline.split('/').slice(-1)[0]}`
return Promise.all([ return Promise.all([
getWithTimeout(url, auth(accessToken)), get(url, auth(accessToken), {timeout: DEFAULT_TIMEOUT}),
getWithTimeout(statusUrl, auth(accessToken)) get(statusUrl, auth(accessToken), {timeout: DEFAULT_TIMEOUT})
]).then(res => { ]).then(res => {
return [].concat(res[0].ancestors).concat([res[1]]).concat(res[0].descendants) return [].concat(res[0].ancestors).concat([res[1]]).concat(res[0].descendants)
}) })
} }
return getWithTimeout(url, auth(accessToken)) return get(url, auth(accessToken), {timeout: DEFAULT_TIMEOUT})
} }

View File

@ -1,19 +1,19 @@
import { getWithTimeout, paramsString } from '../_utils/ajax' import { get, paramsString, DEFAULT_TIMEOUT } from '../_utils/ajax'
import { auth, basename } from './utils' import { auth, basename } from './utils'
export function getVerifyCredentials (instanceName, accessToken) { export function getVerifyCredentials (instanceName, accessToken) {
let url = `${basename(instanceName)}/api/v1/accounts/verify_credentials` let url = `${basename(instanceName)}/api/v1/accounts/verify_credentials`
return getWithTimeout(url, auth(accessToken)) return get(url, auth(accessToken), {timeout: DEFAULT_TIMEOUT})
} }
export function getAccount (instanceName, accessToken, accountId) { export function getAccount (instanceName, accessToken, accountId) {
let url = `${basename(instanceName)}/api/v1/accounts/${accountId}` let url = `${basename(instanceName)}/api/v1/accounts/${accountId}`
return getWithTimeout(url, auth(accessToken)) return get(url, auth(accessToken), {timeout: DEFAULT_TIMEOUT})
} }
export async function getRelationship (instanceName, accessToken, accountId) { export async function getRelationship (instanceName, accessToken, accountId) {
let url = `${basename(instanceName)}/api/v1/accounts/relationships` let url = `${basename(instanceName)}/api/v1/accounts/relationships`
url += '?' + paramsString({id: accountId}) url += '?' + paramsString({id: accountId})
let res = await getWithTimeout(url, auth(accessToken)) let res = await get(url, auth(accessToken), {timeout: DEFAULT_TIMEOUT})
return res[0] return res[0]
} }

View File

@ -1,13 +1,15 @@
const TIMEOUT = process.browser ? 60000 : 120000 export const DEFAULT_TIMEOUT = 20000
export const MEDIA_WRITE_TIMEOUT = 90000 // media uploads can take awhile
export const WRITE_TIMEOUT = 45000 // allow more time if the user did a write action
function fetchWithTimeout (url, options) { function fetchWithTimeout (url, fetchOptions, timeout) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
fetch(url, options).then(resolve, reject) fetch(url, fetchOptions).then(resolve, reject)
setTimeout(() => reject(new Error(`Timed out after ${TIMEOUT / 1000} seconds`)), TIMEOUT) setTimeout(() => reject(new Error(`Timed out after ${timeout / 1000} seconds`)), timeout)
}) })
} }
function makeOpts (method, headers) { function makeFetchOptions (method, headers) {
return { return {
method, method,
headers: Object.assign(headers || {}, { headers: Object.assign(headers || {}, {
@ -27,67 +29,43 @@ async function throwErrorIfInvalidResponse (response) {
throw new Error('Request failed: ' + response.status) throw new Error('Request failed: ' + response.status)
} }
async function _fetch (url, options, timeout) { async function _fetch (url, fetchOptions, options) {
let fetchFunc = timeout ? fetchWithTimeout : fetch let response
let response = await fetchFunc(url, options) if (options && options.timeout) {
response = await fetchWithTimeout(url, fetchOptions, options.timeout)
} else {
response = await fetch(url, fetchOptions)
}
return throwErrorIfInvalidResponse(response) return throwErrorIfInvalidResponse(response)
} }
async function _putOrPost (url, body, headers, timeout, method) { async function _putOrPost (method, url, body, headers, options) {
let opts = makeOpts(method, headers) let fetchOptions = makeFetchOptions(method, headers)
if (body) { if (body) {
if (body instanceof FormData) { if (body instanceof FormData) {
opts.body = body fetchOptions.body = body
} else { } else {
opts.body = JSON.stringify(body) fetchOptions.body = JSON.stringify(body)
opts.headers['Content-Type'] = 'application/json' fetchOptions.headers['Content-Type'] = 'application/json'
} }
} }
return _fetch(url, opts, timeout) return _fetch(url, fetchOptions, options)
} }
async function _post (url, body, headers, timeout) { export async function put (url, body, headers, options) {
return _putOrPost(url, body, headers, timeout, 'POST') return _putOrPost('PUT', url, body, headers, options)
} }
async function _put (url, body, headers, timeout) { export async function post (url, body, headers, options) {
return _putOrPost(url, body, headers, timeout, 'PUT') return _putOrPost('POST', url, body, headers, options)
} }
async function _get (url, headers, timeout) { export async function get (url, headers, options) {
return _fetch(url, makeOpts('GET', headers), timeout) return _fetch(url, makeFetchOptions('GET', headers), options)
} }
async function _delete (url, headers, timeout) { export async function del (url, headers, options) {
return _fetch(url, makeOpts('DELETE', headers), timeout) return _fetch(url, makeFetchOptions('DELETE', headers), options)
}
export async function put (url, body, headers) {
return _put(url, body, headers, false)
}
export async function putWithTimeout (url, body, headers) {
return _put(url, body, headers, true)
}
export async function post (url, body, headers) {
return _post(url, body, headers, false)
}
export async function postWithTimeout (url, body, headers) {
return _post(url, body, headers, true)
}
export async function getWithTimeout (url, headers) {
return _get(url, headers, true)
}
export async function get (url, headers) {
return _get(url, headers, false)
}
export async function deleteWithTimeout (url, headers) {
return _delete(url, headers, true)
} }
export function paramsString (paramsObject) { export function paramsString (paramsObject) {