Bir bağlamı geçerken ifadelere nasıl yönlendirme yaparım?


270

Node.js'de bir web uygulaması yapmak için ekspres kullanıyorum. Bu, sahip olduğum şeyin basitleştirilmesidir:

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('/');
});

Benim sorunum şudur:

Gönderilen verilerin /categorydoğrulanmadığını tespit edersem, /sayfaya bir miktar daha bağlam vermek istiyorum . Bunu nasıl yapabilirim? Yönlendirme, herhangi bir ek parametreye izin vermiyor gibi görünüyor.


1
Ekspres 'göz atın flash: stackoverflow.com/questions/12442716/…
tymeJV

Burada terminoloji önemlidir: /sayfa yok . /Express'in hizmet verebileceği bir rota vardır ve express'in oluşturabileceği bir ana sayfa şablonu vardır. Bir yönlendirmeden sonra ana sayfa şablonunu oluşturmak için bazı verileri korumak istiyorsanız, kabul edilen cevapa rağmen, oturumlar arkadaşınızdır. Size her bir göz atma kullanıcısı için istek ve yanıtlar boyunca devam eden bir veri deposu verir, böylece /categoryişlem sırasında veri girebilir ve daha sonra /teslim sırasında orada olup olmadığını çıkarabilirsiniz .
Mike 'Pomax' Kamermans

Yanıtlar:


368

Verileri farklı rotalara aktarmanın birkaç yolu vardır. En doğru cevap elbette sorgu dizeleridir. Sen değerleri düzgün olmasını sağlamak gerekir encodeURIComponent ve decodeURIComponent .

app.get('/category', function(req, res) {
  var string = encodeURIComponent('something that would break');
  res.redirect('/?valid=' + string);
});

Bunu kullanarak gönderilen parametreleri alarak diğer rotanızda takabilirsiniz req.query.

app.get('/', function(req, res) {
  var passedVariable = req.query.valid;
  // Do something with variable
});

Daha dinamik bir yol için urlçekirdek modülü kullanarak sizin için sorgu dizesi oluşturabilirsiniz:

const url = require('url');    
app.get('/category', function(req, res) {
    res.redirect(url.format({
       pathname:"/",
       query: {
          "a": 1,
          "b": 2,
          "valid":"your string here"
        }
     }));
 });

Bu nedenle, tüm req sorgu dizesi değişkenlerini yeniden yönlendirmek istiyorsanız,

res.redirect(url.format({
       pathname:"/",
       query:req.query,
     });
 });

Düğüm> = 7.x kullanıyorsanız querystringçekirdek modülü de kullanabilirsiniz.

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);
 });

Bunu yapmanın başka bir yolu da oturumda bir şeyler ayarlamaktır. Burada nasıl ayarlanacağını okuyabilirsiniz , ancak değişkenleri ayarlamak ve bunlara erişmek aşağıdaki gibi bir şeydir:

app.get('/category', function(req, res) {
  req.session.valid = true;
  res.redirect('/');
});

Ve daha sonra yeniden yönlendirmeden sonra ...

app.get('/', function(req, res) {
  var passedVariable = req.session.valid;
  req.session.valid = null; // resets session variable
  // Do something
});

Ayrıca Express'in eski bir özelliğini kullanma seçeneği de vardır req.flash. Express'in daha yeni sürümlerinde bunu yapmak için başka bir kütüphane kullanmanızı gerektirir. Temelde, bir sonraki sayfaya gittiğinizde görünecek ve sıfırlanacak değişkenleri ayarlamanıza olanak tanır. Kullanıcılara hataları göstermek için kullanışlıdır, ancak yine varsayılan olarak kaldırılmıştır. EDIT: Bu işlevi ekleyen bir kütüphane bulundu.

Umarım bu bir Express uygulamasında nasıl bilgi aktaracağınıza dair genel bir fikir verecektir.


6
Querys, bağlamı geçmek için gerçekten iyi hissetmiyor, çünkü bu uzun bir paragraf kadar büyük veya daha fazlası olabilir. Oturumlara gelince, bu işe yarayabilir. ama bu gerçekten doğru hissettirmiyor, çünkü bu oturumların doğru amacı gibi görünmüyor ...
Enrique Moreno Tent

@ Hata ayıklayıcı, soruyu sorduğunuzu fark etmedi. Sorgu dizesi aracılığıyla kullanıcıya çok fazla bilgi iletmekten endişe ediyorsanız, doğrulama verilerini bir DB'de saklamak ve ardından ana /rotayı vurduğunuzda sorgulamak daha iyi olabilir . Başka bir seçenek de post rotayı AJAX aracılığıyla aramak ve elde edilen verileri yerel depolamada veya benzer bir şeyde saklamaktır.
AlbertEngelB

13
İyi cevap ama oturumlar sorgu dizeleri daha iyi bir yaklaşım olduğunu düşünüyorum - URL'leri şeyler maruz bırakmayın!
user2562923

2
@ user2562923 Kabul ediyorum, oturumlar veya POST'lar bağlamı iletmek için GET'lerden daha iyi. Cevap oldukça belirsizdi, bu yüzden askerin ne tür bir bilgiden geçtiğinden emin değildim.
AlbertEngelB

düğüm js, sorgu dizesini oluşturan 2 çekirdek modüle sahiptir
Fareed Alnamrouti

42

next()Yönlendirme veya oturumlarla uğraşmaya gerek kalmadan kullanmak için routeHandlers arasında veri aktarımı bulduğum en kolay yolu . İsteğe bağlı olarak sadece sizin diyebiliriz homeCtrl(req,res)yerine next()sadece geçmesine reqveres

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

4
Dostum, bu cevabı seviyorum. Orada bir delikten bana yardımcı oldu - ama gerçekten benim bağırsak req geçmek ve sonraki () için argüman olarak res için ağlıyor gibi daha fazla okuma yapmak gerekiyor.
JonRed

1
Çok iyi ve muhafazakar bir cevap! Diğer cevaplardan çok daha kolay ve çok daha güvenli.
Triforcey

2
Bu yaklaşım daha temiz görünüyor, ancak adres çubuğunu en son yolda bırakıp bırakmayacağından emin değilim ya da bitecek/
Danielo515

1
@ Danielo515 ne yazık ki / kategorilerde sona erecek, bu aslında görünümü doğrudan / kategorilerde göstermekle aynı ...
Manuel Graf

2
URL'yi olduğu gibi bırakacak farklı bir görünüm oluşturmak için yönlendiriciyi bir hizmet olarak kullandığınızı kabul etmiyorum, kodunuzu bu şekilde yapılandırmak kötü bir fikirdir, bir sonraki amaç bir sonraki ara katmana geçmektir ve genellikle iş mantığımızı yönlendiriciler mantığından
ayırın

9

Başka bir çözüm bulmak zorunda kaldım, çünkü sağlanan çözümlerin hiçbiri aşağıdaki nedenlerden dolayı gereksinimlerimi karşılamadı:

  • Sorgu dizeleri : URL'ler kullanıcılarınız tarafından paylaşılabileceğinden ve bazen sorgu parametreleri farklı bir kullanıcı için anlamlı olmadığından sorgu dizeleri kullanmak istemeyebilirsiniz. Örneğin, bir hata ?error=sessionExpiredasla başka bir kullanıcıya yanlışlıkla gösterilmemelidir.

  • req.session : Hiç kullanmanız req.sessiongerekmeyebilecek bir oturum deposu (MongoDB gibi) kurmayı da içeren açık oturum bağımlılığına ihtiyacınız olduğu için veya belki de zaten özel bir oturum deposu çözümü.

  • next () : Kullanmak istemeyebilirsiniz next()veya next("router")bu yalnızca yeni sayfanızı orijinal URL'nin altında oluşturduğundan, gerçekte yeni URL'ye, daha ileri / yeniden yazma gibi, kabul edilemeyebilecek bir yönlendirme değildir.

Bu, önceki sorunların hiçbirinden muzdarip olmayan dördüncü çözümüm. Temel olarak, öncelikle çerez ayrıştırıcısını yüklemeniz gereken geçici bir çerez kullanmayı içerir . Bu, yalnızca çerezlerin etkinleştirildiği yerlerde ve sınırlı miktarda veriyle çalışacağı anlamına gelir.

Uygulama örneği:

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("/");
}

İçin oturum deposu gerekmez express-session. Bir veritabanı, oturumların sunucu yeniden başlatmalarında kalıcı olmasını sağlar.
Mike 'Pomax' Kamermans

6

app.set ve app.get kullanın

Verileri ayarlama

router.get(
  "/facebook/callback",
  passport.authenticate("facebook"),
  (req, res) => {
    req.app.set('user', res.req.user)
    return res.redirect("/sign");
  }
);

Veri alma

router.get("/sign", (req, res) => {
  console.log('sign', req.app.get('user'))
});


2
uygulamak için kötü fikir. tüm kullanıcıyı etkileyebilir tüm req.app tüm kullanıcılar için aynıdır. bunun yerine hızlı oturumu kullanabiliriz .
ujjal das

5

İşte başka bir bağımlılık kullanmadan önerdiğim, sadece düğüm ve ekspres, app.locals kullanın, işte bir örnek:

    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("/");
    }

2
Bu kötü bir fikir gibi hissediyorum çünkü req.app.locals sadece istekte bulunanı değil, tüm kullanıcıları etkiler gibi görünüyor. Elbette verileri kullanıcıya geçer iletilmez temizleyeceksiniz, ancak zaman zaman çelişkili ve yanlış bilgiler göstereceğinizi düşünürüm. Yine de temizlemek zorunda kalırsanız, bunun yerine oturumda saklayabilirsiniz.
istif

1
aslında, yalnızca "benzersiz" kullanıcılar tarafından gönderilen isteği etkiler, 2 veya daha fazla kullanıcı "aynı anda" istek gönderse bile, her kullanıcının kendi istek nesnesi ve yerel nesnesi olur, bu şekilde tamamen güvenlidir kullanımı
Hussein Dimessi

req benzersiz bir kullanıcı içindir, ancak req.app tüm kullanıcılar içindir.
ZeroCho

Kullanım ifade-oturumu mesaj göndermek için
Ujjal das

3

Anahtar / değer çifti verilerinin küçük bitlerini sorgu dizesi üzerinden iletebilirsiniz:

res.redirect('/?error=denied');

Ve ana sayfadaki javascript buna erişebilir ve davranışını buna göre ayarlayabilir.

/categoryTarayıcı adres çubuğunda URL olarak kalmanın sakıncası yoksa , yeniden yönlendirmek yerine doğrudan oluşturabileceğinizi unutmayın. IMHO birçok kez yönlendirmeleri kullanıyor çünkü eski web çerçeveleri doğrudan yanıt vermeyi zorlaştırıyordu, ancak açıkçası kolay:

app.post('/category', function(req, res) {

  // Process the data received in req.body

  res.render('home.jade', {error: 'denied'});
});

@ Dropped.on.Caprica'nın açıkladığı gibi, AJAX kullanımı URL değiştirme endişesini ortadan kaldırır.


Başka bir cevapta söylediğim gibi, sorgu dizeleri iyi görünmüyor, çünkü henüz geçmek istediğim verilerin ne kadar büyük olduğunu bilmiyorum. Diğer çözümünüz daha uygun buldum, ancak yine de aynı URL'yi tutma niyetimi kırıyor.
Enrique Moreno Çadır

@Dbugger Muhtemelen bir AJAX POST mu kullanıyorsunuz?
AlbertEngelB

1

gerekli verileri göndermek için hızlı oturumu kullanabiliriz

uygulamayı başlattığınızda

const express = require('express');
const app = express();
const session = require('express-session');
app.use(session({secret: 'mySecret', resave: false, saveUninitialized: false}));

yeniden yönlendirmeden önce oturumun bağlamını kaydetmeniz yeterlidir

app.post('/category', function(req, res) {
    // add your context here 
req.session.context ='your context here' ;
    res.redirect('/');
});

Artık içeriği oturumun herhangi bir yerine alabilirsiniz. sadece req.session.context ile alabilirsiniz

app.get('/', function(req, res) {

    // So prepare the context
var context=req.session.context;
    res.render('home.jade', context);
});
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.