HttpController.coffee 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. DocumentManager = require "./DocumentManager"
  2. ProjectManager = require "./ProjectManager"
  3. Errors = require "./Errors"
  4. logger = require "logger-sharelatex"
  5. Metrics = require "./Metrics"
  6. TWO_MEGABYTES = 2 * 1024 * 1024
  7. module.exports = HttpController =
  8. getDoc: (req, res, next = (error) ->) ->
  9. doc_id = req.params.doc_id
  10. project_id = req.params.project_id
  11. logger.log project_id: project_id, doc_id: doc_id, "getting doc via http"
  12. timer = new Metrics.Timer("http.getDoc")
  13. if req.query?.fromVersion?
  14. fromVersion = parseInt(req.query.fromVersion, 10)
  15. else
  16. fromVersion = -1
  17. DocumentManager.getDocAndRecentOpsWithLock project_id, doc_id, fromVersion, (error, lines, version, ops, ranges) ->
  18. timer.done()
  19. return next(error) if error?
  20. logger.log project_id: project_id, doc_id: doc_id, "got doc via http"
  21. if !lines? or !version?
  22. return next(new Errors.NotFoundError("document not found"))
  23. res.send JSON.stringify
  24. id: doc_id
  25. lines: lines
  26. version: version
  27. ops: ops
  28. ranges: ranges
  29. _getTotalSizeOfLines: (lines) ->
  30. size = 0
  31. for line in lines
  32. size += (line.length + 1)
  33. return size
  34. getProjectDocs: (req, res, next = (error) ->) ->
  35. project_id = req.params.project_id
  36. projectStateHash = req.query?.state
  37. # exclude is string of existing docs "id:version,id:version,..."
  38. excludeItems = req.query?.exclude?.split(',') or []
  39. logger.log project_id: project_id, exclude: excludeItems, "getting docs via http"
  40. timer = new Metrics.Timer("http.getAllDocs")
  41. excludeVersions = {}
  42. for item in excludeItems
  43. [id,version] = item?.split(':')
  44. excludeVersions[id] = version
  45. logger.log {project_id: project_id, projectStateHash: projectStateHash, excludeVersions: excludeVersions}, "excluding versions"
  46. ProjectManager.getProjectDocs project_id, projectStateHash, excludeVersions, (error, result) ->
  47. timer.done()
  48. if error instanceof Errors.ProjectStateChangedError
  49. res.send 409 # conflict
  50. else if error?
  51. return next(error)
  52. else
  53. logger.log project_id: project_id, result: ("#{doc._id}:#{doc.rev}" for doc in result), "got docs via http"
  54. res.send result
  55. setDoc: (req, res, next = (error) ->) ->
  56. doc_id = req.params.doc_id
  57. project_id = req.params.project_id
  58. {lines, source, user_id, undoing} = req.body
  59. lineSize = HttpController._getTotalSizeOfLines(lines)
  60. if lineSize > TWO_MEGABYTES
  61. logger.log {project_id, doc_id, source, lineSize, user_id}, "document too large, returning 406 response"
  62. return res.send 406
  63. logger.log {project_id, doc_id, lines, source, user_id, undoing}, "setting doc via http"
  64. timer = new Metrics.Timer("http.setDoc")
  65. DocumentManager.setDocWithLock project_id, doc_id, lines, source, user_id, undoing, (error) ->
  66. timer.done()
  67. return next(error) if error?
  68. logger.log project_id: project_id, doc_id: doc_id, "set doc via http"
  69. res.send 204 # No Content
  70. flushDocIfLoaded: (req, res, next = (error) ->) ->
  71. doc_id = req.params.doc_id
  72. project_id = req.params.project_id
  73. logger.log project_id: project_id, doc_id: doc_id, "flushing doc via http"
  74. timer = new Metrics.Timer("http.flushDoc")
  75. DocumentManager.flushDocIfLoadedWithLock project_id, doc_id, (error) ->
  76. timer.done()
  77. return next(error) if error?
  78. logger.log project_id: project_id, doc_id: doc_id, "flushed doc via http"
  79. res.send 204 # No Content
  80. flushAndDeleteDoc: (req, res, next = (error) ->) ->
  81. doc_id = req.params.doc_id
  82. project_id = req.params.project_id
  83. logger.log project_id: project_id, doc_id: doc_id, "deleting doc via http"
  84. timer = new Metrics.Timer("http.deleteDoc")
  85. DocumentManager.flushAndDeleteDocWithLock project_id, doc_id, (error) ->
  86. timer.done()
  87. return next(error) if error?
  88. logger.log project_id: project_id, doc_id: doc_id, "deleted doc via http"
  89. res.send 204 # No Content
  90. flushProject: (req, res, next = (error) ->) ->
  91. project_id = req.params.project_id
  92. logger.log project_id: project_id, "flushing project via http"
  93. timer = new Metrics.Timer("http.flushProject")
  94. ProjectManager.flushProjectWithLocks project_id, (error) ->
  95. timer.done()
  96. return next(error) if error?
  97. logger.log project_id: project_id, "flushed project via http"
  98. res.send 204 # No Content
  99. deleteProject: (req, res, next = (error) ->) ->
  100. project_id = req.params.project_id
  101. logger.log project_id: project_id, "deleting project via http"
  102. timer = new Metrics.Timer("http.deleteProject")
  103. ProjectManager.flushAndDeleteProjectWithLocks project_id, (error) ->
  104. timer.done()
  105. return next(error) if error?
  106. logger.log project_id: project_id, "deleted project via http"
  107. res.send 204 # No Content
  108. acceptChanges: (req, res, next = (error) ->) ->
  109. {project_id, doc_id} = req.params
  110. change_ids = req.body?.change_ids
  111. if !change_ids?
  112. change_ids = [ req.params.change_id ]
  113. logger.log {project_id, doc_id}, "accepting #{ change_ids.length } changes via http"
  114. timer = new Metrics.Timer("http.acceptChanges")
  115. DocumentManager.acceptChangesWithLock project_id, doc_id, change_ids, (error) ->
  116. timer.done()
  117. return next(error) if error?
  118. logger.log {project_id, doc_id}, "accepted #{ change_ids.length } changes via http"
  119. res.send 204 # No Content
  120. deleteComment: (req, res, next = (error) ->) ->
  121. {project_id, doc_id, comment_id} = req.params
  122. logger.log {project_id, doc_id, comment_id}, "deleting comment via http"
  123. timer = new Metrics.Timer("http.deleteComment")
  124. DocumentManager.deleteCommentWithLock project_id, doc_id, comment_id, (error) ->
  125. timer.done()
  126. return next(error) if error?
  127. logger.log {project_id, doc_id, comment_id}, "deleted comment via http"
  128. res.send 204 # No Content