Отправка двоичного файла в Express приводит к ECONNABORTED - PullRequest
0 голосов
/ 08 апреля 2020

В настоящее время я работаю над некоторыми тестами для бэкэнда, и я постоянно спотыкаюсь, что один конкретный тест иногда проходит, а иногда - нет. Ошибка происходит в моей безопасности, чтобы отклонить запрос, если какой-то конкретный заголовок отсутствует. Таким образом, в моем тесте приложение выглядит примерно так:

beforeEach(() => {
    app = express();
    const router = express.Router();
    router.post('/media/upload',      
      addSpies,
      PostMediaGuard(sinon.stub().resolves(true)),
      multer(getMulterOptions()).fields([{ name: 'File', maxCount: 1 }]),
      upload
    ); 

    app.use('/', router);
  });

Теперь добавьте шпионов, просто добавьте шпионов в мой запрос, res и next и продолжайте. Ошибка происходит в моем PostMediaGuard. Здесь я проверю наличие заголовка и отклоню его, если он не

PostMediaGuard

if(typeof(req.headers['x-some-header']) !== 'string')
      return res.status(400).end('No valid RealmId in Header. Please set X-RealmId');

    if(!await _userMayUploadMediaFile(
      req.headers['x-some-header'],
      req.headers.authorization as string,
      req.user
    ))
      return res.status(403).end(`Not allowed to upload media`);

next();

Теперь для теста я просто сделаю запрос на мой приложение, использующее супертест. и запрос выглядит следующим образом

Test

await request(app)      
        .post('/media/upload')      
        .attach('File', path.join(__dirname, '../../test/media/dummy.jpg'));   

Теперь, если я отлаживаю, все работает нормально, и я нажму на строку, чтобы установить статус 400 и завершить запрос в PostMediaGuard. Иногда после этого тест выполняется очень хорошо, а иногда я получаю ECONNABORTED со следующим стеком

: «Ошибка: записать ECONNABORTED
в afterWriteDispatched (internal / stream_base_commons. js : 150: 25)
при записи Generi c (внутренняя / stream_base_commons. js: 141: 3)
при Socket._writeGeneri c (net. js: 770: 11)
в Socket._write (net. js: 782: 8)
в doWrite (_stream_writable. js: 431: 12)
в writeOrBuffer (_stream_writable. js: 415: 5 )
в Socket.Writable.write (_stream_writable. js: 305: 11)
в ClientRequest._writeRaw (_http_outgoing. js: 295: 17)
в ClientRequest._send (_http_outgoing. js: 271: 15)
в ClientRequest.end (_http_outgoing. js: 732: 10)
в Transform.onend (_stream_readable. js: 691: 10)
в Object.onceWrapper (события. js: 299: 28)
в Transform.emit (события. js: 210: 5)
в endReadableNT (_stream_readable. js: 1183: 12)
в processT icksAndRejected (internal / process / task_queues. js: 80: 21) "

Теперь я предполагаю, что в фоновом режиме происходит некоторая потоковая передача из-за файла, отправляемого в форме данные запроса, и я пытаюсь завершить запрос до того, как это будет завершено. Однако я не начал ничего обрабатывать данные, такие как создание потока чтения или попытки сохранить его в базе данных. (потому что дело в том, что я не буду этого делать, если требуемый заголовок отсутствует). Практически все ответы, которые я нашел на этот топи c, были получены из-за того, что некоторые асинхронные потоковые методы были запущены и пытались завершить запрос до того, как он был завершен. Но так как я еще не начал их, я не знаю, где я не прав

Есть идеи, в чем может быть проблема?

1 Ответ

0 голосов
/ 08 апреля 2020

Теперь это похоже на проблему с супертестом (проблема на GitHub)

Однако, по крайней мере, есть обходной путь, чтобы заставить его работать, установив соединение, чтобы оно оставалось живым в заголовке .

Если вы посмотрите на мой пример запроса в вопросе, измените его на что-то вроде этого

await request(app)      
        .post('/media/upload')      
        .attach('File', path.join(__dirname, '../../test/media/dummy.jpg'))
        .set('Connection', 'keep-alive'); 

Теперь я все еще не могу понять, что происходит с супертестом. Эта проблема гласит, что при запросе данных формы может быть вызван двойной обратный вызов, так что это может быть связано с этим.

На данный момент я не понимаю причину root, но я обновлю здесь, как только узнаю. По крайней мере, есть обходной путь, чтобы заставить это работать на данный момент.

...