Koa.js and streaming. How do you handle errors?
Asked Answered
R

1

7

Does anybody works with koa.js and streams?

Consider this example

const fs = require('fs');
const Koa = require('koa');

const app = new Koa();

app.use(async (ctx) => {
  ctx.body = fs.createReadStream('really-large-file');
});

app.listen(4000);

If user aborts request I'm getting either

  Error: read ECONNRESET
      at _errnoException (util.js:1024:11)
      at TCP.onread (net.js:618:25)

or

  Error: write EPIPE
      at _errnoException (util.js:1024:11)
      at WriteWrap.afterWrite [as oncomplete] (net.js:870:14)

What is the proper way to handle this type of errors?

P.S. I have no errors after request aborts with express

const fs = require('fs');
const express = require('express');

const app = express();

app.get('/', (req, res) => {
  fs.createReadStream('really-large-file').pipe(res);
});

app.listen(4000);

P.P.S. I've tried

app.use(async (ctx) => {
  fs.createReadStream('really-large-file').pipe(ctx.res);
  ctx.respond = false;
});

But it had no effect.

Regression answered 28/10, 2017 at 11:13 Comment(0)
L
-2

Use a gloabel error handler. see https://github.com/koajs/koa/wiki/Error-Handling

const fs = require('fs');
const Koa = require('koa');

const app = new Koa();


app.use(async (ctx, next) => {
  try {
    await next();
  } catch (err) {
    ctx.status = err.status || 500;
    ctx.body = err.message;
    ctx.app.emit('error', err, ctx);
  }
});

app.use(async (ctx) => {
  ctx.body = await openFile();
});

function openFile(){
  return new Promise((resolve,reject)=>{
    var stream = fs.createReadStream("really-large-file")
    var data
    stream.on("error",err=>reject(err))
    stream.on("data",chunk=>data+=chunk)
    stream.on("end",()=>resolve(data))
  })
}

app.listen(4000);
Logistics answered 29/10, 2017 at 3:47 Comment(4)
Unfortunately this handler does not catch ECONNRESET errors.Regression
sorry, i was not paying attention... a (readable)Stream is not awaitable (which you didn't try ;-) ) and so you can not catch errors there. you have to promisify your file loading to get it to work... updated the answer acordingly...Logistics
The problem with this is that you pass file contents into memory and then resolve it into the response body. This is not how you should implement streaming. I can just read file contents with readFileSync and pass it to the body.Regression
By resolving the data only at the end of the read stream... this unstreams a streamBianco

© 2022 - 2024 — McMap. All rights reserved.