Как перенаправить в expressjs при передаче некоторого контекста?
Я использую express для создания веб-приложения в node.js. Это упрощение того, что у меня есть:
var express = require('express');
var jade = require('jade');
var http = require("http");
var app = express();
var server = http.createServer(app);
app.get('/', function(req, res) {
// Prepare the context
res.render('home.jade', context);
});
app.post('/category', function(req, res) {
// Process the data received in req.body
res.redirect('/');
});
Моя проблема заключается в следующем:
Если я обнаружил, что данные, отправленные в /category
, не проверяются, я хотел бы передать некоторый дополнительный контекст на страницу /
. Как я могу это сделать? Перенаправление не похоже на какой-либо дополнительный параметр.
Ответы
Ответ 1
Существует несколько способов передачи данных по различным маршрутам. Самый правильный ответ - это, конечно, строки запроса. Вы должны убедиться, что значения правильно encodeURIComponent и decodeURIComponent.
app.get('/category', function(req, res) {
var string = encodeURIComponent('something that would break');
res.redirect('/?valid=' + string);
});
Вы можете заблокировать это на своем другом маршруте, получив параметры, отправленные с помощью req.query
.
app.get('/', function(req, res) {
var passedVariable = req.query.valid;
// Do something with variable
});
Для более динамичного использования вы можете использовать основной модуль url
для создания строки запроса для вас:
const url = require('url');
app.get('/category', function(req, res) {
res.redirect(url.format({
pathname:"/",
query: {
"a": 1,
"b": 2,
"valid":"your string here"
}
}));
});
Итак, если вы хотите перенаправить все переменные строки запроса req, вы можете просто сделать
res.redirect(url.format({
pathname:"/",
query:req.query,
});
});
И если вы используете Node >= 7.x, вы также можете использовать основной модуль querystring
const querystring = require('querystring');
app.get('/category', function(req, res) {
const query = querystring.stringify({
"a": 1,
"b": 2,
"valid":"your string here"
});
res.redirect('/?' + query);
});
Другой способ сделать это - установить что-то в сеансе. Вы можете прочитать, как настроить его здесь, но для установки и доступа к переменным есть что-то вроде этого:
app.get('/category', function(req, res) {
req.session.valid = true;
res.redirect('/');
});
И позже после перенаправления...
app.get('/', function(req, res) {
var passedVariable = req.session.valid;
req.session.valid = null; // resets session variable
// Do something
});
Существует также возможность использования старой функции Express, req.flash
. Для этого в новых версиях Express потребуется использовать другую библиотеку. По сути, это позволяет вам устанавливать переменные, которые будут отображаться, и reset при следующем переходе на страницу. Это удобно для показа ошибок пользователям, но опять же было удалено по умолчанию. EDIT: Найден библиотеку, которая добавляет эту функциональность.
Надеюсь, это даст вам общее представление о том, как передавать информацию в приложении Express.
Ответ 2
Самый простой способ, с помощью которого я нашел передачу данных между routeHandlers для использования next()
, не нужно связывать с перенаправлением или сеансами.
При желании вы можете просто вызвать homeCtrl(req,res)
вместо next()
и просто передать req
и res
var express = require('express');
var jade = require('jade');
var http = require("http");
var app = express();
var server = http.createServer(app);
/////////////
// Routing //
/////////////
// Move route middleware into named
// functions
function homeCtrl(req, res) {
// Prepare the context
var context = req.dataProcessed;
res.render('home.jade', context);
}
function categoryCtrl(req, res, next) {
// Process the data received in req.body
// instead of res.redirect('/');
req.dataProcessed = somethingYouDid;
return next();
// optionally - Same effect
// accept no need to define homeCtrl
// as the last piece of middleware
// return homeCtrl(req, res, next);
}
app.get('/', homeCtrl);
app.post('/category', categoryCtrl, homeCtrl);
Ответ 3
Мне нужно было найти другое решение, потому что ни одно из предложенных решений не соответствовало моим требованиям по следующим причинам:
Строки запроса. Возможно, вы не захотите использовать строки запроса, поскольку URL-адреса могут быть общими для ваших пользователей, а иногда параметры запроса не имеют смысла для другого пользователя. Например, ошибка, такая как ?error=sessionExpired
, никогда не должна отображаться другому пользователю случайно.
req.session: вы можете не захотеть использовать req.session
, потому что для этого вам нужна зависимость express-session, которая включает в себя настройку хранилища сеансов (например, MongoDB), чего вы не можете нужно вообще, или, может быть, вы уже используете специальное решение для хранения сеансов.
next(): Возможно, вы не захотите использовать next()
или next("router")
, потому что это, по сути, просто отображает вашу новую страницу под исходным URL-адресом, на самом деле это не перенаправление на новый URL-адрес, а скорее пересылка/перезапись, что может быть неприемлемо.
Так что это мое четвертое решение, которое не страдает ни от одной из предыдущих проблем. В основном это связано с использованием временного файла cookie, для которого вам необходимо сначала установить cookie-parser. Очевидно, это означает, что он будет работать только там, где включены файлы cookie и с ограниченным объемом данных.
Пример реализации:
var cookieParser = require("cookie-parser");
app.use(cookieParser());
app.get("/", function(req, res) {
var context = req.cookies["context"];
res.clearCookie("context", { httpOnly: true });
res.render("home.jade", context); // Here context is just a string, you will have to provide a valid context for your template engine
});
app.post("/category", function(req, res) {
res.cookie("context", "myContext", { httpOnly: true });
res.redirect("/");
}
Ответ 4
Вот то, что я предлагаю без использования какой-либо другой зависимости, просто узел и экспресс, используйте app.locals, вот пример:
app.get("/", function(req, res) {
var context = req.app.locals.specialContext;
req.app.locals.specialContext = null;
res.render("home.jade", context);
// or if you are using ejs
res.render("home", {context: context});
});
function middleware(req, res, next) {
req.app.locals.specialContext = * your context goes here *
res.redirect("/");
}
Ответ 5
Вы можете передавать небольшие биты данных пары ключ/значение через строку запроса:
res.redirect('/?error=denied');
И javascript на домашней странице может получить доступ к этому и соответствующим образом скорректировать его поведение.
Обратите внимание, что если вы не возражаете /category
оставаться в качестве URL-адреса в адресной строке браузера, вы можете просто визуализировать напрямую, а не перенаправлять. IMHO много раз люди используют перенаправления, потому что старые веб-фреймворки делали прямое реагирование сложным, но легко в экспресс:
app.post('/category', function(req, res) {
// Process the data received in req.body
res.render('home.jade', {error: 'denied'});
});
Как заметил @Dropped.on.Caprica, использование AJAX устраняет проблему изменения URL.
Ответ 6
Одним из решений является промежуточное программное обеспечение анализатора тела, которое передает данные в виде объекта JSON
var express = require('express');
var jade = require('jade');
var http = require("http");
const bodyParser = require('body-parser') //requiring body parser
var app = express();
var server = http.createServer(app);
app.get('/', function(req, res) {
// Prepare the context
res.render('home.jade', context);
});
app.post('/category', function(req, res) {
// Process the data received in req.body
//pass the data as an json object
res.redirect('/', { data: data });
});