diff --git a/routes/_actions/followRequests.js b/routes/_actions/followRequests.js index 42427cb..a57214a 100644 --- a/routes/_actions/followRequests.js +++ b/routes/_actions/followRequests.js @@ -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' export async function getFollowRequests (instanceName, accessToken) { 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) { 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) { 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}) } diff --git a/routes/_api/block.js b/routes/_api/block.js index 772444f..6fd39d3 100644 --- a/routes/_api/block.js +++ b/routes/_api/block.js @@ -1,12 +1,12 @@ import { auth, basename } from './utils' -import { postWithTimeout } from '../_utils/ajax' +import { post, WRITE_TIMEOUT } from '../_utils/ajax' export async function blockAccount (instanceName, accessToken, accountId) { 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) { let url = `${basename(instanceName)}/api/v1/accounts/${accountId}/unblock` - return postWithTimeout(url, null, auth(accessToken)) + return post(url, null, auth(accessToken), {timeout: WRITE_TIMEOUT}) } diff --git a/routes/_api/blockedAndMuted.js b/routes/_api/blockedAndMuted.js index f9b9d02..8c01cd8 100644 --- a/routes/_api/blockedAndMuted.js +++ b/routes/_api/blockedAndMuted.js @@ -1,14 +1,14 @@ -import { getWithTimeout, paramsString } from '../_utils/ajax' +import { DEFAULT_TIMEOUT, get, paramsString } from '../_utils/ajax' import { auth, basename } from './utils' export async function getBlockedAccounts (instanceName, accessToken, limit = 80) { let url = `${basename(instanceName)}/api/v1/blocks` url += '?' + paramsString({ limit }) - return getWithTimeout(url, auth(accessToken)) + return get(url, auth(accessToken), {timeout: DEFAULT_TIMEOUT}) } export async function getMutedAccounts (instanceName, accessToken, limit = 80) { let url = `${basename(instanceName)}/api/v1/mutes` url += '?' + paramsString({ limit }) - return getWithTimeout(url, auth(accessToken)) + return get(url, auth(accessToken), {timeout: DEFAULT_TIMEOUT}) } diff --git a/routes/_api/delete.js b/routes/_api/delete.js index b952634..ca52782 100644 --- a/routes/_api/delete.js +++ b/routes/_api/delete.js @@ -1,7 +1,7 @@ import { auth, basename } from './utils' -import { deleteWithTimeout } from '../_utils/ajax' +import { del, WRITE_TIMEOUT } from '../_utils/ajax' export async function deleteStatus (instanceName, accessToken, statusId) { let url = `${basename(instanceName)}/api/v1/statuses/${statusId}` - return deleteWithTimeout(url, auth(accessToken)) + return del(url, auth(accessToken), {timeout: WRITE_TIMEOUT}) } diff --git a/routes/_api/emoji.js b/routes/_api/emoji.js index c848ed5..a63866f 100644 --- a/routes/_api/emoji.js +++ b/routes/_api/emoji.js @@ -1,7 +1,7 @@ import { basename } from './utils' -import { getWithTimeout } from '../_utils/ajax' +import { DEFAULT_TIMEOUT, get } from '../_utils/ajax' export async function getCustomEmoji (instanceName) { let url = `${basename(instanceName)}/api/v1/custom_emojis` - return getWithTimeout(url) + return get(url, null, {timeout: DEFAULT_TIMEOUT}) } diff --git a/routes/_api/favorite.js b/routes/_api/favorite.js index 8aade27..baffb5d 100644 --- a/routes/_api/favorite.js +++ b/routes/_api/favorite.js @@ -1,12 +1,12 @@ -import { post } from '../_utils/ajax' +import { post, WRITE_TIMEOUT } from '../_utils/ajax' import { basename, auth } from './utils' export async function favoriteStatus (instanceName, accessToken, statusId) { 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) { let url = `${basename(instanceName)}/api/v1/statuses/${statusId}/unfavourite` - return post(url, null, auth(accessToken)) + return post(url, null, auth(accessToken), {timeout: WRITE_TIMEOUT}) } diff --git a/routes/_api/follow.js b/routes/_api/follow.js index 8aae944..ffad5dd 100644 --- a/routes/_api/follow.js +++ b/routes/_api/follow.js @@ -1,12 +1,12 @@ -import { postWithTimeout } from '../_utils/ajax' +import { post, WRITE_TIMEOUT } from '../_utils/ajax' import { auth, basename } from './utils' export async function followAccount (instanceName, accessToken, accountId) { 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) { let url = `${basename(instanceName)}/api/v1/accounts/${accountId}/unfollow` - return postWithTimeout(url, null, auth(accessToken)) + return post(url, null, auth(accessToken), {timeout: WRITE_TIMEOUT}) } diff --git a/routes/_api/followsAndFollowers.js b/routes/_api/followsAndFollowers.js index 607e5ce..aa3f72a 100644 --- a/routes/_api/followsAndFollowers.js +++ b/routes/_api/followsAndFollowers.js @@ -1,14 +1,14 @@ -import { getWithTimeout, paramsString } from '../_utils/ajax' +import { get, paramsString, DEFAULT_TIMEOUT } from '../_utils/ajax' import { auth, basename } from './utils' export async function getFollows (instanceName, accessToken, accountId, limit = 80) { let url = `${basename(instanceName)}/api/v1/accounts/${accountId}/following` 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) { let url = `${basename(instanceName)}/api/v1/accounts/${accountId}/followers` url += '?' + paramsString({ limit }) - return getWithTimeout(url, auth(accessToken)) + return get(url, auth(accessToken), {timeout: DEFAULT_TIMEOUT}) } diff --git a/routes/_api/instance.js b/routes/_api/instance.js index e87d76a..a62d680 100644 --- a/routes/_api/instance.js +++ b/routes/_api/instance.js @@ -1,7 +1,7 @@ -import { getWithTimeout } from '../_utils/ajax' +import { get, DEFAULT_TIMEOUT } from '../_utils/ajax' import { basename } from './utils' export function getInstanceInfo (instanceName) { let url = `${basename(instanceName)}/api/v1/instance` - return getWithTimeout(url) + return get(url, null, {timeout: DEFAULT_TIMEOUT}) } diff --git a/routes/_api/lists.js b/routes/_api/lists.js index 0674024..5cc5c01 100644 --- a/routes/_api/lists.js +++ b/routes/_api/lists.js @@ -1,7 +1,7 @@ -import { getWithTimeout } from '../_utils/ajax' +import { get, DEFAULT_TIMEOUT } from '../_utils/ajax' import { auth, basename } from './utils' export function getLists (instanceName, accessToken) { let url = `${basename(instanceName)}/api/v1/lists` - return getWithTimeout(url, auth(accessToken)) + return get(url, auth(accessToken), {timeout: DEFAULT_TIMEOUT}) } diff --git a/routes/_api/media.js b/routes/_api/media.js index aefc22f..e4cd3e9 100644 --- a/routes/_api/media.js +++ b/routes/_api/media.js @@ -1,5 +1,5 @@ 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) { let formData = new FormData() @@ -8,10 +8,10 @@ export async function uploadMedia (instanceName, accessToken, file, description) formData.append('description', description) } 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) { let url = `${basename(instanceName)}/api/v1/media/${mediaId}` - return putWithTimeout(url, {description}, auth(accessToken)) + return put(url, {description}, auth(accessToken), {timeout: WRITE_TIMEOUT}) } diff --git a/routes/_api/mute.js b/routes/_api/mute.js index 9acb76a..22893de 100644 --- a/routes/_api/mute.js +++ b/routes/_api/mute.js @@ -1,12 +1,12 @@ import { auth, basename } from './utils' -import { postWithTimeout } from '../_utils/ajax' +import { post, WRITE_TIMEOUT } from '../_utils/ajax' export async function muteAccount (instanceName, accessToken, accountId) { 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) { let url = `${basename(instanceName)}/api/v1/accounts/${accountId}/unmute` - return postWithTimeout(url, null, auth(accessToken)) + return post(url, null, auth(accessToken), {timeout: WRITE_TIMEOUT}) } diff --git a/routes/_api/muteConversation.js b/routes/_api/muteConversation.js index a006e73..57160f0 100644 --- a/routes/_api/muteConversation.js +++ b/routes/_api/muteConversation.js @@ -1,12 +1,12 @@ import { auth, basename } from './utils' -import { postWithTimeout } from '../_utils/ajax' +import { post, WRITE_TIMEOUT } from '../_utils/ajax' export async function muteConversation (instanceName, accessToken, statusId) { 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) { let url = `${basename(instanceName)}/api/v1/statuses/${statusId}/unmute` - return postWithTimeout(url, null, auth(accessToken)) + return post(url, null, auth(accessToken), {timeout: WRITE_TIMEOUT}) } diff --git a/routes/_api/oauth.js b/routes/_api/oauth.js index ece24f1..341da2a 100644 --- a/routes/_api/oauth.js +++ b/routes/_api/oauth.js @@ -1,4 +1,4 @@ -import { postWithTimeout, paramsString } from '../_utils/ajax' +import { post, paramsString, WRITE_TIMEOUT } from '../_utils/ajax' import { basename } from './utils' const WEBSITE = 'https://pinafore.social' @@ -7,12 +7,12 @@ const CLIENT_NAME = 'Pinafore' export function registerApplication (instanceName, redirectUri) { const url = `${basename(instanceName)}/api/v1/apps` - return postWithTimeout(url, { + return post(url, { client_name: CLIENT_NAME, redirect_uris: redirectUri, scopes: SCOPES, website: WEBSITE - }) + }, null, {timeout: WRITE_TIMEOUT}) } export function generateAuthLink (instanceName, clientId, redirectUri) { @@ -27,11 +27,11 @@ export function generateAuthLink (instanceName, clientId, redirectUri) { export function getAccessTokenFromAuthCode (instanceName, clientId, clientSecret, code, redirectUri) { let url = `${basename(instanceName)}/oauth/token` - return postWithTimeout(url, { + return post(url, { client_id: clientId, client_secret: clientSecret, redirect_uri: redirectUri, grant_type: 'authorization_code', code: code - }) + }, null, {timeout: WRITE_TIMEOUT}) } diff --git a/routes/_api/pin.js b/routes/_api/pin.js index 21269b8..9226694 100644 --- a/routes/_api/pin.js +++ b/routes/_api/pin.js @@ -1,12 +1,12 @@ -import { postWithTimeout } from '../_utils/ajax' +import { post, WRITE_TIMEOUT } from '../_utils/ajax' import { auth, basename } from './utils' export async function pinStatus (instanceName, accessToken, statusId) { 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) { let url = `${basename(instanceName)}/api/v1/statuses/${statusId}/unpin` - return postWithTimeout(url, null, auth(accessToken)) + return post(url, null, auth(accessToken), {timeout: WRITE_TIMEOUT}) } diff --git a/routes/_api/pinnedStatuses.js b/routes/_api/pinnedStatuses.js index c1f17af..1ccc367 100644 --- a/routes/_api/pinnedStatuses.js +++ b/routes/_api/pinnedStatuses.js @@ -1,4 +1,4 @@ -import { getWithTimeout, paramsString } from '../_utils/ajax' +import { get, paramsString, DEFAULT_TIMEOUT } from '../_utils/ajax' import { auth, basename } from './utils' export async function getPinnedStatuses (instanceName, accessToken, accountId) { @@ -7,5 +7,5 @@ export async function getPinnedStatuses (instanceName, accessToken, accountId) { limit: 40, pinned: true }) - return getWithTimeout(url, auth(accessToken)) + return get(url, auth(accessToken), {timeout: DEFAULT_TIMEOUT}) } diff --git a/routes/_api/reblogsAndFavs.js b/routes/_api/reblogsAndFavs.js index 451da79..9f35898 100644 --- a/routes/_api/reblogsAndFavs.js +++ b/routes/_api/reblogsAndFavs.js @@ -1,14 +1,14 @@ -import { getWithTimeout, paramsString } from '../_utils/ajax' +import { get, paramsString, DEFAULT_TIMEOUT } from '../_utils/ajax' import { auth, basename } from './utils' export async function getReblogs (instanceName, accessToken, statusId, limit = 80) { let url = `${basename(instanceName)}/api/v1/statuses/${statusId}/reblogged_by` 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) { let url = `${basename(instanceName)}/api/v1/statuses/${statusId}/favourited_by` url += '?' + paramsString({ limit }) - return getWithTimeout(url, auth(accessToken)) + return get(url, auth(accessToken), {timeout: DEFAULT_TIMEOUT}) } diff --git a/routes/_api/requests.js b/routes/_api/requests.js index 394729e..3284490 100644 --- a/routes/_api/requests.js +++ b/routes/_api/requests.js @@ -1,12 +1,12 @@ -import { postWithTimeout } from '../_utils/ajax' +import { post, WRITE_TIMEOUT } from '../_utils/ajax' import { auth, basename } from './utils' export async function approveFollowRequest (instanceName, accessToken, accountId) { 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) { 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}) } diff --git a/routes/_api/search.js b/routes/_api/search.js index 1163773..4b0cf81 100644 --- a/routes/_api/search.js +++ b/routes/_api/search.js @@ -1,4 +1,4 @@ -import { getWithTimeout, paramsString } from '../_utils/ajax' +import { get, paramsString, DEFAULT_TIMEOUT } from '../_utils/ajax' import { auth, basename } from './utils' export function search (instanceName, accessToken, query) { @@ -6,5 +6,5 @@ export function search (instanceName, accessToken, query) { q: query, resolve: true }) - return getWithTimeout(url, auth(accessToken)) + return get(url, auth(accessToken), {timeout: DEFAULT_TIMEOUT}) } diff --git a/routes/_api/statuses.js b/routes/_api/statuses.js index cd02c81..430df44 100644 --- a/routes/_api/statuses.js +++ b/routes/_api/statuses.js @@ -1,5 +1,5 @@ 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, 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}) } diff --git a/routes/_api/timelines.js b/routes/_api/timelines.js index 3111027..dfc5a6f 100644 --- a/routes/_api/timelines.js +++ b/routes/_api/timelines.js @@ -1,4 +1,4 @@ -import { getWithTimeout, paramsString } from '../_utils/ajax' +import { get, paramsString, DEFAULT_TIMEOUT } from '../_utils/ajax' import { auth, basename } from './utils' 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 let statusUrl = `${basename(instanceName)}/api/v1/statuses/${timeline.split('/').slice(-1)[0]}` return Promise.all([ - getWithTimeout(url, auth(accessToken)), - getWithTimeout(statusUrl, auth(accessToken)) + get(url, auth(accessToken), {timeout: DEFAULT_TIMEOUT}), + get(statusUrl, auth(accessToken), {timeout: DEFAULT_TIMEOUT}) ]).then(res => { 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}) } diff --git a/routes/_api/user.js b/routes/_api/user.js index c3078ec..ce7b2ee 100644 --- a/routes/_api/user.js +++ b/routes/_api/user.js @@ -1,19 +1,19 @@ -import { getWithTimeout, paramsString } from '../_utils/ajax' +import { get, paramsString, DEFAULT_TIMEOUT } from '../_utils/ajax' import { auth, basename } from './utils' export function getVerifyCredentials (instanceName, accessToken) { 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) { 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) { let url = `${basename(instanceName)}/api/v1/accounts/relationships` url += '?' + paramsString({id: accountId}) - let res = await getWithTimeout(url, auth(accessToken)) + let res = await get(url, auth(accessToken), {timeout: DEFAULT_TIMEOUT}) return res[0] } diff --git a/routes/_utils/ajax.js b/routes/_utils/ajax.js index 81ca1de..837a59e 100644 --- a/routes/_utils/ajax.js +++ b/routes/_utils/ajax.js @@ -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) => { - fetch(url, options).then(resolve, reject) - setTimeout(() => reject(new Error(`Timed out after ${TIMEOUT / 1000} seconds`)), TIMEOUT) + fetch(url, fetchOptions).then(resolve, reject) + setTimeout(() => reject(new Error(`Timed out after ${timeout / 1000} seconds`)), timeout) }) } -function makeOpts (method, headers) { +function makeFetchOptions (method, headers) { return { method, headers: Object.assign(headers || {}, { @@ -27,67 +29,43 @@ async function throwErrorIfInvalidResponse (response) { throw new Error('Request failed: ' + response.status) } -async function _fetch (url, options, timeout) { - let fetchFunc = timeout ? fetchWithTimeout : fetch - let response = await fetchFunc(url, options) +async function _fetch (url, fetchOptions, options) { + let response + if (options && options.timeout) { + response = await fetchWithTimeout(url, fetchOptions, options.timeout) + } else { + response = await fetch(url, fetchOptions) + } return throwErrorIfInvalidResponse(response) } -async function _putOrPost (url, body, headers, timeout, method) { - let opts = makeOpts(method, headers) +async function _putOrPost (method, url, body, headers, options) { + let fetchOptions = makeFetchOptions(method, headers) if (body) { if (body instanceof FormData) { - opts.body = body + fetchOptions.body = body } else { - opts.body = JSON.stringify(body) - opts.headers['Content-Type'] = 'application/json' + fetchOptions.body = JSON.stringify(body) + fetchOptions.headers['Content-Type'] = 'application/json' } } - return _fetch(url, opts, timeout) + return _fetch(url, fetchOptions, options) } -async function _post (url, body, headers, timeout) { - return _putOrPost(url, body, headers, timeout, 'POST') +export async function put (url, body, headers, options) { + return _putOrPost('PUT', url, body, headers, options) } -async function _put (url, body, headers, timeout) { - return _putOrPost(url, body, headers, timeout, 'PUT') +export async function post (url, body, headers, options) { + return _putOrPost('POST', url, body, headers, options) } -async function _get (url, headers, timeout) { - return _fetch(url, makeOpts('GET', headers), timeout) +export async function get (url, headers, options) { + return _fetch(url, makeFetchOptions('GET', headers), options) } -async function _delete (url, headers, timeout) { - return _fetch(url, makeOpts('DELETE', headers), timeout) -} - -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 async function del (url, headers, options) { + return _fetch(url, makeFetchOptions('DELETE', headers), options) } export function paramsString (paramsObject) {