2

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

Kickaha
  • 3,680
  • 6
  • 38
  • 57

3 Answers3

2

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.

Rich Churcher
  • 7,361
  • 3
  • 37
  • 60
  • Thanks, this makes sense. I'll accept once I've had a chance to implement. – Kickaha Jan 03 '18 at 19:43
  • 1
    Turns out what I needed was to drop the line "body = bodyParser()" and add parenthesis to the body() in the router. Also didn't need ajax for my use case. I'll clarify in another answer. Thank you for being so helpful! – Kickaha Jan 04 '18 at 19:19
1

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;

}
Kickaha
  • 3,680
  • 6
  • 38
  • 57
0

@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) => {