UrlAgent.mjs 2.1 KB

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