0

As mentioned im trying to do multiple post requests on a koa server with supertest. As you can see in the code below. When the script is executed via

DEBUG=koa* mocha --harmony_destructuring --sort --require co-mocha --timeout 0 "test.js"

it just hangs when dispatching for the second post request. The second connection to the server is somehow kept open forever (see leaked-handles debug output). GET requests handle fine. I found out that it somehow works if I do either one of those:

  • do not send post data i.e disable ".send(data)" (which is not an option obviously)
  • remove "yield next" in the post route (I don't want that)
  • introduce a middleware after the routes are attached that does not yield (see "<--- HERE" in the code)

I would really like to understand why that is and what I am doing wrong here, since i think introducing that whacky do-not-yield-middleware-workaround is just bad.

    'use strict';

    require('leaked-handles').set({
        fullStack: true,
        timeout: 5000,
        debugSockets: true
    });

    var http = require('http');
    var app = require('koa')();
    var router = require('koa-router');
    var body = require('koa-body')();
    var compose = require('koa-compose');

    var www = function () {
        var r = router();
        r.get('/test', function * (next) {
            this.body = 200;
            yield next;
        });
        r.post('/test', body, function * (next) {
            console.log(this.request.body);
            this.body = {status: 200};
            yield next;
        });

        app.use(compose([
            r.routes(),
            r.allowedMethods()
        ]));

        // app.use(function * last (next) {/* do not yield */}); // <----

        var server = http.createServer(app.callback());
        return server;
    };


    var supertest = require('supertest');
    var expect = require('chai').expect;

    describe('testing server', () => {

        var agent, server;
        var data = {test: 123};

        beforeEach(function () {
            server = www();
            agent = supertest(server.listen());
        });

        afterEach(function (done) {
            server.close(done);
        });

        describe('get', () => {
            it('returns ok', (done) => {
                agent.get('/test').expect(200, done);
            });
            it('returns ok', (done) => {
                agent.get('/test').expect(200, done);
            });
        });

        describe('post 1', () => {
            it('returns ok', (done) => {
                agent.post('/test')
                     .send(data)
                     .expect(200, done);
            });
        });

        describe('post 2', () => {
            it('returns ok', (done) => {
                agent.post('/test')
                     .send(data)
                     .expect(200, done);
            });
        });

    });
λuser
  • 893
  • 8
  • 14
cdx
  • 99
  • 8
  • What's the purpose of `yield next` in this case? Did you notice that the second `GET` test triggers the `r.get()` route handler twice (so there are 3 calls to `r.get()` being made in total), which seems strange. – robertklep Jul 06 '16 at 21:07
  • I'm not sure if i understand the question correctly, but yield next calls the next middleware in the chain, so one yould have a logger in the end or use it for benchmarking porposes therefor i want to stick to having yield next in all of my routes. Regarding the GET requests no i didnt notice that, and im also not sure why that is, but ill invesitgate. – cdx Jul 06 '16 at 23:40
  • oh my ... i found it: in "var app = require('koa')();" is the cause of the error, the function should be called inside the "www" function i.e splitting it up into "var koa = require('koa');" and then in www "var app = koa();" i guess i have to answer my own question now? – cdx Jul 07 '16 at 00:31
  • Yeah you should ;) – robertklep Jul 07 '16 at 06:17

1 Answers1

0

Ok, as mentioned in the comment above, i found out whats the problem. its basically this line:

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

koa itself has to be instantiated within the www function i.e.

    var koa = require('koa');
    ...
    var www = function () {
        var app = koa();
        ...
    }
    ...

Although I'm still not sure what actually causes the behavior, this fixes it properly.

cdx
  • 99
  • 8