Medardas
Medardas

Reputation: 540

Purest request in KOA

I probably don't understand something about JS, but I'm having an issue writing Purest response to the page body. Like here:

var koa = require('koa')
  , session = require('koa-session')
  , mount = require('koa-mount')
  , koaqs = require('koa-qs')
  , accesslog = require('koa-accesslog')
  , router = require('koa-router')()
  , app = koa();

var Grant = require('grant-koa')
  , grant = new Grant(require('./config.json'))

app.keys = ['grant']
app.use(accesslog())
   .use(session(app))
   .use(mount(grant))
   .use(router.routes())
   .use(router.allowedMethods());
koaqs(app)

router.get('/handle_facebook_callback', function *(next) {
  getProfile(this.query.access_token);
	
})

var config = {
  "facebook": {
    "https://graph.facebook.com": {
      "__domain": {
        "auth": {
          "auth": {"bearer": "[0]"}
        }
      },
      "{endpoint}": {
        "__path": {
          "alias": "__default"
        }
      }
    }
  }
}

var request = require('request')
  , purest = require('purest')({request})
  , facebook = purest({provider: 'facebook', config})

function getProfile(access_token, responseToBody){
	facebook.get('me')
            .auth(access_token)
			.request(function (err, res, body) {
				this.body=JSON.stringify(body,null,2);
  })
}


if (!module.parent) app.listen(3000);
console.log('oh!GG is running on http://localhost:3000/');

I would assume in facebook.request function "this.body=JSON.stringify(body,null,2);" part should write the response into the body, however it doesn't. What exactly is the issue here?

Upvotes: 0

Views: 204

Answers (1)

danneu
danneu

Reputation: 9454

The route (a generator) isn't waiting for getProfile to finish. You need yield.

Right now in your snippet, it executes getProfile, which returns immediately to the generator, the generator finishes, Koa sees that you haven't set this.body, so it defaults to a 404 response.

Once the callback in getProfile finally fires at some later point, the response has already been sent and you get the error.

The general solution for getting a callback-style function to work with Koa (i.e. making it so you can yield it) is to wrap it in a Promise:

function getProfile (access_token) {
  return new Promise(function (resolve, reject) {
    facebook.get('me')
      .auth(access_token)
      .request(function (err, res, body) {
        if (err) return reject(err)
        resolve(body)
      })
  })
}

router.get('/handle_facebook_callback', function * (next) {
  const profile = yield getProfile(this.query.access_token)
  this.type = 'application/json'
  this.body = JSON.stringify(profile, null, 2)
})

getProfile now returns a Promise which you can yield.

Also, notice that I changed it so that getProfile resolves with the profile object, and the Koa handler is the one that stitches together this.body and the JSON.

This is generally how you want to do things in Koa so that all of your response mutation happens inside the handler in one place.

Upvotes: 3

Related Questions