Parcourir la source

Merge pull request #15895 from overleaf/jpa-latexqc-fetch-backend

[latexqc] migrate backend from axios to fetch

GitOrigin-RevId: 6dc1a9ca0aa96da01229fec96d3c4b34750f4aa2
Jakob Ackermann il y a 2 ans
Parent
commit
7a87bf4288

+ 30 - 0
libraries/fetch-utils/index.js

@@ -80,6 +80,35 @@ async function fetchNothing(url, opts = {}) {
   return response
 }
 
+/**
+ * Make a request and extract the redirect from the response.
+ *
+ * @param {string | URL} url - request URL
+ * @param {object} opts - fetch options
+ * @return {Promise<string>}
+ * @throws {RequestFailedError} if the response has a non redirect status code or missing Location header
+ */
+async function fetchRedirect(url, opts = {}) {
+  const { fetchOpts } = parseOpts(opts)
+  fetchOpts.redirect = 'manual'
+  const response = await performRequest(url, fetchOpts)
+  if (response.status < 300 || response.status >= 400) {
+    const body = await maybeGetResponseBody(response)
+    throw new RequestFailedError(url, opts, response, body)
+  }
+  const location = response.headers.get('Location')
+  if (!location) {
+    const body = await maybeGetResponseBody(response)
+    throw new RequestFailedError(url, opts, response, body).withCause(
+      new OError('missing Location response header on 3xx response', {
+        headers: Object.fromEntries(response.headers.entries()),
+      })
+    )
+  }
+  await discardResponseBody(response)
+  return location
+}
+
 /**
  * Make a request and return a string.
  *
@@ -222,6 +251,7 @@ module.exports = {
   fetchStream,
   fetchStreamWithResponse,
   fetchNothing,
+  fetchRedirect,
   fetchString,
   fetchStringWithResponse,
   RequestFailedError,

+ 31 - 0
libraries/fetch-utils/test/unit/FetchUtilsTests.js

@@ -7,6 +7,7 @@ const {
   fetchJson,
   fetchStream,
   fetchNothing,
+  fetchRedirect,
   fetchString,
   RequestFailedError,
 } = require('../..')
@@ -205,6 +206,36 @@ describe('fetch-utils', function () {
       await expectRequestAborted(this.server.lastReq)
     })
   })
+
+  describe('fetchRedirect', function () {
+    it('returns the immediate redirect', async function () {
+      const body = await fetchRedirect(this.url('/redirect/1'))
+      expect(body).to.equal(this.url('/redirect/2'))
+    })
+
+    it('rejects status 200', async function () {
+      await expect(fetchRedirect(this.url('/hello'))).to.be.rejectedWith(
+        RequestFailedError
+      )
+      await expectRequestAborted(this.server.lastReq)
+    })
+
+    it('rejects empty redirect', async function () {
+      await expect(fetchRedirect(this.url('/redirect/empty-location')))
+        .to.be.rejectedWith(RequestFailedError)
+        .and.eventually.have.property('cause')
+        .and.to.have.property('message')
+        .to.equal('missing Location response header on 3xx response')
+      await expectRequestAborted(this.server.lastReq)
+    })
+
+    it('handles errors', async function () {
+      await expect(fetchRedirect(this.url('/500'))).to.be.rejectedWith(
+        RequestFailedError
+      )
+      await expectRequestAborted(this.server.lastReq)
+    })
+  })
 })
 
 async function streamToString(stream) {

+ 12 - 0
libraries/fetch-utils/test/unit/helpers/TestServer.js

@@ -73,6 +73,18 @@ class TestServer {
     // Never returns
 
     this.app.post('/hang', (req, res) => {})
+
+    // Redirect
+
+    this.app.get('/redirect/1', (req, res) => {
+      res.redirect('/redirect/2')
+    })
+    this.app.get('/redirect/2', (req, res) => {
+      res.send('body after redirect')
+    })
+    this.app.get('/redirect/empty-location', (req, res) => {
+      res.sendStatus(302)
+    })
   }
 
   start(port) {

+ 2 - 0
package-lock.json

@@ -41413,6 +41413,7 @@
       "version": "0.0.1",
       "license": "MIT",
       "dependencies": {
+        "@overleaf/fetch-utils": "*",
         "aws-sdk": "^2.1174.0",
         "axios": "^0.21.2",
         "body-parser": "^1.19.2",
@@ -67341,6 +67342,7 @@
         "@babel/preset-env": "^7.23.2",
         "@babel/preset-react": "^7.22.15",
         "@babel/register": "^7.22.15",
+        "@overleaf/fetch-utils": "*",
         "aws-sdk": "^2.1174.0",
         "axios": "^0.21.2",
         "babel-loader": "^9.1.3",