Koa-Router: пропустить маршрут, если запрос не в XHR

У меня есть Rest API, созданный с помощью Koa с некоторыми маршрутами, но в то же время он будет обслуживать мой Front (созданный с помощью JS framework и собственный роутер).

Дело в том, что когда я получаю доступ из браузера localhost/user, я хочу отобразить переднюю часть, но когда я достигаю того же URL-адреса из fetch / ajax / XMLHttpRequest, я хочу отобразить результат JSON (тот, который дал Коа-маршрутизатором).

Поэтому я хотел бы включить маршрут /user из API, только если он вызывается из XHR.

Я сделал свое промежуточное ПО isXMLHttpRequest следующим образом:

module.exports = async (ctx, next) => {
    if(ctx.request.get('X-Requested-With') === 'XMLHttpRequest') {
        return next()
    }
}

Затем в моем koa-маршрутизаторе я сделал что-то вроде:

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())

И потом, это работает, когда я делаю какой-то XHR-запрос, у меня есть JSON, как и планировалось, но если я попытаюсь получить доступ к /user из браузера, API выдаст мне ошибку «Не найдено», а не мой фронт...

Я искал, как пропустить функцию router.use, если запрос не сделан в XHR, но я не могу найти решение...

Я думаю, что это в состоянии промежуточного программного обеспечения, я должен что-то вернуть, но что я могу сделать, чтобы коа-маршрутизатор не дал мне 404 ...

Возможно ты можешь помочь мне ?


person Simon Trichereau    schedule 09.03.2021    source источник


Ответы (2)


Итак, если вы используете ОДИНАКОВЫЕ маршруты для статических и XMLHttpRequests (что, вероятно, не лучшая стратегия), то это может сработать:

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)

Это не использует промежуточное ПО, потому что здесь вы можете разрешить нисходящий поток только с next, но если следующего нет, то это останавливается. else нет ;-) Просто для справки

person Sebastian Hildebrandt    schedule 15.03.2021
comment
Спасибо за код, я проверю его позже, чтобы попробовать :) - person Simon Trichereau; 16.03.2021
comment
Да, это работает ! :) Спасибо за решение, даже если бы я предпочел пройти промежуточное ПО :) - person Simon Trichereau; 16.03.2021

Не уверен, правильно ли я понял ваш вопрос. Итак, у вас есть серверная часть, которая действует как статический веб-сервер И REST API, верно?

Я бы попробовал сделать наоборот. Используя, например, koa-static (https://www.npmjs.com/package/koa-static) СНАЧАЛА попытается обслужить ваши файлы, и если соответствующие файлы не будут найдены в вашем общем каталоге defines, будут обработаны все остальные маршруты (т.е. ваш REST API). Затем вам нужно только убедиться, что имена конечных точек не пересекаются с файлами, которые вы обслуживаете.

person Sebastian Hildebrandt    schedule 12.03.2021
comment
Да, именно поэтому я попытался объяснить ... Создание только одного веб-сервера, который обслуживает статический фронт, сделанный с помощью JS Framework и его собственного маршрутизатора, и в то же время REST API. Но передняя часть и API использовали одни и те же маршруты (например, пользовательский), поэтому я попытался отличить их с помощью XHR... Поскольку я не мог достичь того, что хотел, я, наконец, добавил префикс к своим маршрутам API следующим образом: /api/user - person Simon Trichereau; 14.03.2021