Skip to content

Instantly share code, notes, and snippets.

@smashercosmo
Last active January 22, 2019 17:16
Show Gist options
  • Save smashercosmo/030137f53ad79f4b78ee5e663989c285 to your computer and use it in GitHub Desktop.
Save smashercosmo/030137f53ad79f4b78ee5e663989c285 to your computer and use it in GitHub Desktop.
const route = require('koa-route')
const request = require('request')
const got = require('got')
const {
UMBRA_APS_CLIENT_SECRET,
UMBRA_API_EXTERNALURL,
UMBRA_AUTH_URI,
} = process.env
const api = route.all('/api/(.*)', ctx => {
const { session = {} } = ctx
const { access_token: token = '', refresh_token: rtoken = '' } = session
const url = UMBRA_API_EXTERNALURL + ctx.url.replace(/^\/api/, '/api/v1')
ctx.req.headers.Authorization = `Bearer ${token}`
ctx.respond = false
let proxyReq = request(url)
const stream = ctx.req.pipe(proxyReq)
proxyReq.on('response', async response => {
if (response.statusCode === 403 && rtoken) {
try {
proxyReq.pause()
const { body: authData } = await got(`${UMBRA_AUTH_URI}/token`, {
method: 'POST',
json: true,
body: {
grant_type: 'refresh_token',
refresh_token: rtoken,
client_id: 'AdminPortalServer',
client_secret: UMBRA_APS_CLIENT_SECRET,
},
})
Object.assign(ctx.session, authData)
await ctx.session.manuallyCommit()
ctx.req.headers.Authorization = `Bearer ${authData.access_token}`
proxyReq = request(url)
ctx.req.pipe(proxyReq).pipe(ctx.res)
} catch (e) {
proxyReq.resume()
stream.pipe(ctx.res)
}
} else {
stream.pipe(ctx.res)
}
})
})
module.exports.api = api
const request = require('supertest')
const Koa = require('koa')
const bodyParser = require('koa-bodyparser')
require('dotenv').config()
process.env.UMBRA_API_EXTERNALURL = 'http://localhost:3000'
process.env.UMBRA_AUTH_URI = 'http://localhost:3000'
const { api: proxy } = require('../api')
// External API server
const api = new Koa()
api.use(bodyParser())
api.use(async (ctx, next) => {
if (ctx.url.indexOf('/api/v1/success') > -1) {
const token = ctx.get('authorization').split(' ')[1]
if (token) {
ctx.body = { success: true }
} else {
ctx.throw(403)
}
} else if (ctx.url.indexOf('/api/v1/error') > -1) {
ctx.throw(400)
} else if (ctx.url.indexOf('/token') > -1) {
if (ctx.request.body.refresh_token === 'correct_rtoken') {
ctx.body = { access_token: 'token' }
} else {
ctx.throw(400)
}
}
await next()
})
describe('api proxy', () => {
test('should response with 403 error, if fetching new token failed', async () => {
const app = new Koa()
app.use(async (ctx, next) => {
ctx.session = {}
ctx.session.refresh_token = 'wrong_rtoken'
await next()
})
app.use(proxy)
const server = api.listen(3000)
await request(app.callback())
.get('/api/success')
.expect(403) // <- возвращается 404
server.close()
})
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment