I have a Rest API made with Koa with some routes, but, at the same time, it will serve my Front (made with a JS framework and its own router).
The fact is, when I access from a browser "localhost/user" I want to display the front but when I reach the same url from fetch / ajax / XMLHttpRequest I want to display a JSON result (the one gave by the Koa-router).
So I would like to enable the /user route from the API only if it's called from XHR.
I did my isXMLHttpRequest middleware like this :
module.exports = async (ctx, next) => {
if(ctx.request.get('X-Requested-With') === 'XMLHttpRequest') {
return next()
}
}
Then, in my koa-router I did something like :
const Router = require('koa-router')
const isXMLHttpRequest = require("@middlewares/isXMLHttpRequest")
const router = new Router()
const user = require("@routes/user")
router.use('/user', isXMLHttpRequest, user.routes(), user.allowedMethods())
And then, it works when I do some XHR request, I have the JSON as planned, but if I try to access the /user from the browser, the API is giving me a Not Found Error and not my front...
I was looking on how to skip the router.use function if the request isn't made in XHR, but I can't find a solution...
I think it's in the middleware else condition, I have to return something, but what can I do to skip the koa-router from giving me 404 ...
Maybe you can help me ?
OK, so if you are using the SAME routes for static and XMLHttpRequests (which is probably not the best strategy), then this could work:
const Koa = require('koa')
const Router = require('koa-router')
const app = module.exports = new Koa();
isXmlRequest = (ctx) => {
// here you could also compare e.g. "accept" header
return (ctx.request.header && ctx.request.header['x-requested-with'] === 'XMLHttpRequest');
}
// static routes
const staticRouter = new Router()
staticRouter.get('/user', (ctx, next) => {
ctx.body = 'OK from static route';
next();
});
// XMLHttpRequest routes
const xmlRouter = new Router()
xmlRouter.get('/user', (ctx, next) => {
if (isXmlRequest(ctx)) {
// serve it
ctx.body = { ok: 'from JSON/XML' }
} else {
// downstream to next handler
next();
}
});
app.use(xmlRouter.routes());
app.use(staticRouter.routes());
const server = app.listen(3000)
This is not using middleware bwcause here you can only allow downstream with next
but if there is no next, then this stops. There is no else
;-)
Just for reference