Stop middleware pipeline execution in KOA

5.1k views Asked by At

I would like to ask if there is a way to stop the execution of the middleware pipeline in KOA?

In the example below, I have a middleware that would somehow validate something. How could I re-code my middleware to stop the execution when validation fails?

var koa = require('koa');
var router = require('koa-router')();
var app = koa();

app.use(router.routes());

// middleware
app.use(function *(next){
  var valid = false;
  if (!valid){
    console.log('entered validation')
    this.body = "error"
    return this.body; // how to stop the execution in here
  }
});

// route
router.get('/', function *(next){
  yield next;
  this.body = "should not enter here";
});


app.listen(3000);

I could actually change my route to this:

router.get('/', function *(next){
  yield next;
  if(this.body !== "error")
    this.body = "should not enter here";
});

But is there a better way? Or I'm missing something?

This is just an example, in reality my middleware might put a property in the body (this.body.hasErrors = true) and the route would read from that.

Again, how could I stop the execution in my middleware, so that my routes would not be executed? In Express I think you could do a response.end (not sure about this though).

1

There are 1 answers

3
James Moore On BEST ANSWER

Middleware is executed in the sequence you add them to the app.
You can choose to either yield to downstream middleware or send a response early (errors etc). So the key to stoping middleware flow is to not yield.

app.use(function *(next){
  // yield to downstream middleware if desired
  if(doValidation(this)){
    yield next;
  }
  // or respond in this middleware 
  else{
    this.throw(403, 'Validation Error');
  }
});

app.use(function *(next){
  // this is added second so it is downstream to the first generator function
  // and can only reached if upstream middleware yields      
  this.body = 'Made it to the downstream middleware'
});

Edit for clarity:

below I've modified your original example to make it work the way I think you are intending.

var koa = require('koa');
var router = require('koa-router')();
var app = koa();

// move route handlers below middleware
//app.use(router.routes());

// middleware
app.use(function *(next){
  var valid = false;
  if (!valid){
    console.log('entered validation')
    this.body = "error"
    // return this.body; // how to stop the execution in here
  }
  else{
    yield next;
  }
});

// route
router.get('/', function *(next){
  // based on your example I don't think you want to yield here
  // as this seems to be a returning middleware
  // yield next;
  this.body = "should not enter here";
});

// add routes here
app.use(router.routes());

app.listen(3000);