UrlAgent.mjs 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import logger from '@overleaf/logger'
  2. import urlValidator from 'valid-url'
  3. import { InvalidUrlError, UrlFetchFailedError } from './LinkedFilesErrors.js'
  4. import LinkedFilesHandler from './LinkedFilesHandler.js'
  5. import UrlHelper from '../Helpers/UrlHelper.js'
  6. import { fetchStream, RequestFailedError } from '@overleaf/fetch-utils'
  7. import { callbackify } from '@overleaf/promise-utils'
  8. import { FileTooLargeError } from '../Errors/Errors.js'
  9. async function createLinkedFile(
  10. projectId,
  11. linkedFileData,
  12. name,
  13. parentFolderId,
  14. userId
  15. ) {
  16. logger.info(
  17. { projectId, userId, url: linkedFileData.url },
  18. 'create linked file'
  19. )
  20. linkedFileData = _sanitizeData(linkedFileData)
  21. const fetchUrl = _getUrl(projectId, linkedFileData, userId)
  22. try {
  23. const readStream = await fetchStream(fetchUrl)
  24. const file = await LinkedFilesHandler.promises.importFromStream(
  25. projectId,
  26. readStream,
  27. linkedFileData,
  28. name,
  29. parentFolderId,
  30. userId
  31. )
  32. return file._id
  33. } catch (error) {
  34. if (error instanceof RequestFailedError && /too large/.test(error.body)) {
  35. throw new FileTooLargeError('file too large', {
  36. url: linkedFileData.url,
  37. }).withCause(error)
  38. }
  39. throw new UrlFetchFailedError('url fetch failed', {
  40. url: linkedFileData.url,
  41. }).withCause(error)
  42. }
  43. }
  44. async function refreshLinkedFile(
  45. projectId,
  46. linkedFileData,
  47. name,
  48. parentFolderId,
  49. userId
  50. ) {
  51. return await createLinkedFile(
  52. projectId,
  53. linkedFileData,
  54. name,
  55. parentFolderId,
  56. userId
  57. )
  58. }
  59. function _sanitizeData(data) {
  60. return {
  61. provider: data.provider,
  62. url: UrlHelper.prependHttpIfNeeded(data.url),
  63. importedAt: data.importedAt,
  64. }
  65. }
  66. function _getUrl(projectId, data, currentUserId) {
  67. let { url } = data
  68. if (!urlValidator.isWebUri(url)) {
  69. throw new InvalidUrlError(`invalid url: ${url}`)
  70. }
  71. url = UrlHelper.wrapUrlWithProxy(url)
  72. return url
  73. }
  74. export default {
  75. createLinkedFile: callbackify(createLinkedFile),
  76. refreshLinkedFile: callbackify(refreshLinkedFile),
  77. promises: { createLinkedFile, refreshLinkedFile },
  78. }