helapkg / hela

:icecream: Powerful software development experience and management. Enhancing @tc39 JS, @denoland and @nodejs, because we need a bit of magic. :sparkles: You can think of it as Cargo for the JavaScript ecosystem.
Mozilla Public License 2.0
331 stars 41 forks source link

Problems with koa-better-router? #74

Closed maotora closed 7 years ago

maotora commented 7 years ago

Hi,

Awesome middleware you made here!

I'm starting with koa and your middlewares seem pretty great so i'm using koa-better-router & koa-better-body together.

However things are not working as expected. I'm


import koa from 'koa';
import body from 'koa-better-body';
import Router from 'koa-rest-router';
import convert from 'koa-convert';

const app = new koa();

apiRouter.resource('users', {
    index: [
        (ctx, next) => {
            ctx.body = "list users!\n";
            return next(); 
        },
        function *(next) {
            this.body = `${this.body} and blah blah..`;
            yield next;
        }
    ],

    recent: (ctx, next) => { ctx.body = "Newly created user!\n"; return next(); },

    create: (ctx, next) => { ctx.body = "Create users!\n"; return next(); },

    edit: (ctx, next) => { ctx.body = "Edit user view!\n"; return next(); },

    update: [body,
        (ctx, next) => {
            ctx.body = "create users!\n";
            return next(); 
        },

        function *(next) {
            this.body = `And incoming data is ...`;
            this.body = `body from req ${this.body} ${this.request.fields}`;
            yield next;
        }
    ],

    remove: (ctx, next) => { ctx.body = "remove users!\n"; return next(); }
}, {map: {'new': 'recent'}, methods: {'put': 'post'}});

const basic = new Router(); //- For routes not beginning with /api/v1
basic.extend(apiRouter);

app.use(convert(body())); //- did this out of desperation
app.use(apiRouter.middleware());
app.use(basic.middleware());

This code is from chunks of your koa-better-router examples and problem comes when i use update which is using body.

If i include "body" as the beginning arg in update and post something to /users/1 i get Not Found and nothing gets run cause update controller wasn't the one called (no controller was).

    update: [body,
        (ctx, next) => {
            ctx.body = "create users!\n";
            return next(); 
        },

        function *(next) {
            this.body = `And incoming data is ...`;
            this.body = `body from req ${this.body} ${this.request.fields}`;
            yield next;
        }
    ],

If i remove the "body" from the update and call this.request.fields i get error. Update code when i remove body

    update: [
        (ctx, next) => {
            debugger;
            ctx.body = "create users!\n";
            return next(); 
        },

        function *(next) {
            this.body = `body from req ${this.request.fields}`;
            console.log(this.request);
            yield next;
        }
    ],

Error Msg when i remove body

  TypeError: Cannot convert object to primitive value
      at Object._callee2$ (/home/users/Projects/koa/test-project1/dist/index.js:70:54)
      at tryCatch (/home/users/Projects/koa/test-project1/node_modules/regenerator-runtime/runtime.js:64:40)
      at Generator.invoke [as _invoke] (/home/users/Projects/koa/test-project1/node_modules/regenerator-runtime/runtime.js:355:22)
      at Generator.prototype.(anonymous function) [as next] (/home/users/Projects/koa/test-project1/node_modules/regenerator-runtime/runtime.js:116:21)
      at onFulfilled (/home/users/Projects/koa/test-project1/node_modules/co/index.js:65:19)
      at /home/users/Projects/koa/test-project1/node_modules/co/index.js:54:5
      at Object.co (/home/users/Projects/koa/test-project1/node_modules/co/index.js:50:10)
      at converted (/home/users/Projects/koa/test-project1/node_modules/koa-convert/index.js:17:15)
      at dispatch (/home/users/Projects/koa/test-project1/node_modules/koa-compose/index.js:44:32)
      at next (/home/users/Projects/koa/test-project1/node_modules/koa-compose/index.js:45:18)

Please help.

tunnckoCore commented 7 years ago

Hi there, sorry for confusing. I can't believe that people face issues and misunderstand some things, with this great readmes. Anyway :laughing:

First, you missed to put what apiRouter (I know what it is, just note). Second, you don't need to create two routers - basic and apiRouter. Third, body is not called, it should be body(). And fourth, you don't need to add both middlewares to the Koa app - I've seen you add both basic.middleware() and apiRouter.middleware().

And finally, I believe I put somewhere working example.

edit: Yea, see the recipes of koa-better-router - recipes/adding-a-route

maotora commented 7 years ago

@tunnckoCore ooh man 🗡 You are awesome!

Thank you!

tunnckoCore commented 7 years ago

Haha, thanks :dagger: Hope they help.

maotora commented 7 years ago

@tunnckoCore i'm passing over some examples, and regarding your comment "Third, body is not called, it should be body()".

What did you mean? As in you meant in the app.use(body()) or in the update: [body, ...] controller?

tunnckoCore commented 7 years ago

in the controller should be body() too. Because it returns a middleware function only when is called.

maotora commented 7 years ago

@tunnckoCore solved it today.. hehe

  1. I imported body as
import body from 'koa-better-body';
  1. I removed body from update controller in koa-better-router.
api.resource('users', {
    update: //- From here.
        (ctx, next) => {
            ctx.body = "create users!\n";
            console.log('your data ', ctx.request.fields);
            return next(); 
    }
});
  1. I called the body middleware before router middleware.
    app.use(convert(body({
    multipart: true,
    })));

and this solved everything.

All other tries (including body in update controller, not calling body in middleware etc..) had some failures in one way or another.

Thank you for this middleware man :)

tunnckoCore commented 7 years ago

It's not cool in that way. Because it will be called in requests that not need body parsing.

Also you dont need koa-convert if you including it in controller. We use that package internally.

One note on

from update controller

it's not "update controller", it's "update method" from users controller.

What's so hard in that

import bodyParser from 'koa-better-body'

api.resource('users', {
  update: [
    bodyParser({ some: 'options' }),
    (ctx, next) => {
      ctx.body = "create users!\n"
      return next()
    },

    function * (next) {
      this.body = `And incoming data is ...`
      this.body = `body from req ${this.body} ${this.request.fields}`
      yield next
    }
  ]
})