Kickaha
Kickaha

Reputation: 3857

Access POST data in node using koa-body and koa-router

Making a ajax POST from a User Agent

$.ajax({
            type: 'POST',
            url: 'https://mysub.domain.dev/myroute',

            headers: {
              'X-Requested-With': 'XMLHttpRequest'
            },
            contentType: 'application/octet-stream; charset=utf-8',
            success: function(result) {
              successAction();
            },
            processData: false,
            data: myResult['myValue']
          });

With Koa2 on my server, how do I get the data myResult['myValue'] from the POST body?

const bodyParser = require('koa-body');

const router = new Router();
const body = bodyParser();


router.post('/myroute/', body, async (ctx, next) => {

const getMyValue = ctx.request.body.data.myValue;

}

I've tried various combinations. All are undefined or empty objects.

const getMyValue = ctx.request.body

Object{}

const getMyValue = ctx.request.body.data;

undefined

const getMyValue = ctx.request.body.myResult['myValue'];

undefined

Upvotes: 2

Views: 5688

Answers (3)

Ram Sambamurthy
Ram Sambamurthy

Reputation: 11

@Kickaha: you still need to enclose the bodyParser() with multipart because by default multipart:false in koa-body, instead your line should read:

router.post('/myroute/', bodyParser({multipart:true}), async (ctx, next) => {

Upvotes: 0

Kickaha
Kickaha

Reputation: 3857

Turns out ajax was unnecessary, so the client is simply...

 post('/myroute', {data: myResult[myValue] });

Then the koa-body is injected into the router without instancing it in page scope first. Note the parenthesis...

const bodyParser = require('koa-body');

const router = new Router();

router.post('/myroute/', bodyParser(), async (ctx, next) => {

const getMyValue = ctx.request.body.data;

}

Upvotes: 1

Rich Churcher
Rich Churcher

Reputation: 7654

Couple of things going on here.

First, you need to explicitly tell koa-body to look for multipart form data (it's off by default). So:

const koaBody = require('koa-body')

router.post('/myroute', koaBody({ multipart: true }),
  async (ctx, next) => {
    // ctx.request.body.fields: additional (non-file) fields
    // ctx.request.body.files: files (octet-stream) 
  })

Second, in the client you're probably going to want to set the enctype and explicitly set contentType to false. This seems counter-intuitive, but it stops jQuery from adding a ContentType header which will be missing a boundary string. Your request would look something like this:

$('#go').click(evt => {
  evt.preventDefault()

  const data = new FormData($('#uploadForm')[0])
  data.append('extra', 'fields if required')

  $.ajax({
    contentType: false,
    data,
    enctype: 'multipart/form-data',
    processData: false,
    success: result => $('#result').text(result),
    type: 'POST',
    url: '...'
  })
})

Note that the FormData in the example might not fit your use case, it was just a convenient demonstration. It's likely you can simply use data: myresult['myValue'], assuming that's a file.

Upvotes: 2

Related Questions