fetchFromCompileDomain.ts 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. import { isNetworkError } from '../../../utils/isNetworkError'
  2. import getMeta from '../../../utils/meta'
  3. import OError from '@overleaf/o-error'
  4. import { postJSON } from '../../../infrastructure/fetch-json'
  5. let useFallbackDomainUntil = performance.now()
  6. const ONE_HOUR_IN_MS = 1000 * 60 * 60
  7. export async function fetchFromCompileDomain(url: string, init: RequestInit) {
  8. const userContentDomain = getMeta('ol-compilesUserContentDomain')
  9. let isUserContentDomain =
  10. userContentDomain &&
  11. new URL(url).hostname === new URL(userContentDomain).hostname
  12. if (useFallbackDomainUntil > performance.now()) {
  13. isUserContentDomain = false
  14. url = withFallbackCompileDomain(url)
  15. }
  16. try {
  17. return await fetch(url, init)
  18. } catch (err) {
  19. if (isNetworkError(err) && isUserContentDomain) {
  20. try {
  21. const res = await fetch(withFallbackCompileDomain(url), init)
  22. // Only switch to the fallback when fetch does not throw there as well.
  23. if (useFallbackDomainUntil < performance.now()) {
  24. useFallbackDomainUntil = performance.now() + ONE_HOUR_IN_MS
  25. recordFallbackUsage()
  26. }
  27. return res
  28. } catch (err2: any) {
  29. throw OError.tag(err2, 'fallback request failed', {
  30. errUserContentDomain: err,
  31. })
  32. }
  33. }
  34. throw err
  35. }
  36. }
  37. function withFallbackCompileDomain(url: string) {
  38. const u = new URL(url)
  39. u.hostname = new URL(getMeta('ol-fallbackCompileDomain')).hostname
  40. return u.href
  41. }
  42. function recordFallbackUsage() {
  43. setTimeout(() => {
  44. postJSON('/record-user-content-domain-fallback-usage').catch(() => {})
  45. }, 1_000)
  46. }