컨텍스트를 전달하는 동안 expressjs로 리디렉션하려면 어떻게해야합니까?


269

node.js에서 웹 앱을 만들기 위해 express를 사용하고 있습니다. 이것은 내가 가진 것의 단순화입니다.

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
Express '를 확인하십시오 flash: stackoverflow.com/questions/12442716/…
tymeJV

용어는 여기서 중요합니다. /페이지 가 없습니다 . /특급 서비스 가 가능한 경로 가 있으며 , 특급 서비스가 렌더링 할 수있는 홈페이지 템플릿이 있습니다. 리디렉션 후 홈페이지 템플릿을 렌더링하기 위해 일부 데이터를 유지하려면 허용 된 대답에도 불구하고 세션은 친구입니다. 개별 브라우징 사용자에 대한 요청 및 응답 걸쳐 지속되는 데이터 저장소를 제공 하므로 /category처리 중에 데이터를 넣은 다음 처리 중에 데이터 를 가져갈 수 /있습니다.
Mike 'Pomax'Kamermans

답변:


366

다른 경로로 데이터를 전달하는 몇 가지 방법이 있습니다. 물론 정답은 쿼리 문자열입니다. 값이 올바르게 encodeURIComponentdecodeURIComponent 인지 확인해야합니다 .

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

따라서 모든 요청 쿼리 문자열 변수를 리디렉션하려면 간단하게 수행 할 수 있습니다

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에서 그렇게하려면 다른 라이브러리를 사용해야합니다. 기본적으로 다음에 페이지로 이동할 때 표시되고 재설정되는 변수를 설정할 수 있습니다. 사용자에게 오류를 표시하는 데 편리하지만 기본적으로 제거되었습니다. 편집하다: 이 기능을 추가하는 라이브러리를 찾았습니다.

잘하면 Express 응용 프로그램에서 정보를 전달하는 방법에 대한 일반적인 아이디어를 얻을 수 있기를 바랍니다.


6
쿼리는 컨텍스트를 전달하는 것이 옳다고 느끼지 않습니다. 긴 단락이나 그 이상일 수 있기 때문입니다. 세션에 관해서는 효과가있을 수 있습니다. 그러나 이것이 세션의 올바른 목적으로 보이지 않기 때문에 실제로는 기분이 좋지 않습니다 ...
Enrique Moreno Tent

@Dbugger Oops, 당신이 질문을했는지 몰랐습니다. querystring을 통해 사용자에게 너무 많은 정보를 전달하는 것이 걱정되는 경우 유효성 검사 데이터를 DB에 저장 한 다음 기본 /경로에 도달했을 때 쿼리하는 것이 좋습니다 . 다른 옵션은 AJAX를 통해 포스트 라우트를 호출하고 결과 데이터를 로컬 스토리지 또는 이와 유사한 것으로 저장하는 것입니다.
AlbertEngelB

13
좋은 대답이지만 세션은 쿼리 문자열보다 더 나은 방법이라고 생각합니다. URL에 내용을 노출시키지 마십시오!
user2562923

2
@ user2562923 동의합니다. 세션이나 POST는 GET보다 컨텍스트를 전달하는 것보다 낫습니다. 그 대답은 꽤 모호해서 어떤 사람이 어떤 정보를 전달했는지 확신 할 수 없었습니다.
AlbertEngelB

노드 js에는 쿼리 문자열을 생성하는 2 개의 핵심 모듈이 있습니다.
Fareed Alnamrouti

42

경로 처리기 사이에 데이터를 전달 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);

4
버디, 나는이 대답을 좋아한다. 내 구멍이 빠져 나갔습니다.하지만 내 직감이 next ()의 인수로 req와 res를 전달하기 위해 울고 있기 때문에 더 많은 독서를해야합니다.
JonRed

1
매우 훌륭하고 보수적 인 답변! 다른 답변보다 훨씬 쉽고 안전합니다.
Triforcey

2
이 접근 방식은 깔끔한 것으로 보이지만 주소 표시 줄을 최신 경로로 유지할지 또는 종료 될지 확실하지 않습니다./
Danielo515

1
@ Danielo515 불행히도 / categories에서 끝날 것입니다. 그래서 이것은 실제로 / categories에서 직접 뷰를 렌더링하는 것과 같습니다 ...
Manuel Graf

2
URL을 그대로 두는 지연 된보기를 렌더링하기 위해 서비스로 라우터를 사용한다는 것에 동의하지 않습니다. 다음과 같은 목적으로 코드를 구성하는 것은 좋지 않습니다. 다음의 목적은 다음 미들웨어로 이동합니다. 비즈니스 로직을 라우터 로직과 분리
Fareed Alnamrouti

9

제공된 솔루션 중 어느 것도 실제로 내 요구 사항을 충족시키지 못했기 때문에 다른 솔루션을 찾아야했습니다.

  • 쿼리 문자열 : 사용자가 URL을 공유 할 수 있고 때로는 쿼리 매개 변수가 다른 사용자에게 적합하지 않기 때문에 쿼리 문자열을 사용하지 않을 수 있습니다. 예를 들어 ?error=sessionExpired실수로 다른 사용자 에게 오류 가 표시되어서는 안됩니다.

  • req.session : 세션 저장소 (예 : MongoDB) 설정이 포함되어 있거나 세션이 필요하지 않거나 이미 사용자 정의를 사용중인 req.session경우 명시적인 세션 종속성이 필요하므로 사용하지 않을 수 있습니다. 세션 저장소 솔루션.

  • next () : 사용하고 싶지 next()않거나 next("router")원래 URL 아래에 새 페이지를 렌더링하기 때문에 실제로는 앞으로 / 다시 쓰기와 같이 새 URL로 리디렉션되지 않으므로 받아 들일 수 없습니다.

따라서 이것은 이전 문제로 고통받지 않는 네 번째 솔루션입니다. 기본적으로 쿠키 파서 를 먼저 설치 해야하는 임시 쿠키를 사용합니다. . 분명히 이것은 쿠키가 활성화되어 있고 제한된 양의 데이터로만 작동한다는 것을 의미합니다.

구현 예 :

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

에 세션 저장소가 필요하지 않습니다 express-session. 데이터베이스는 서버를 다시 시작해도 세션이 지속되도록합니다.
Mike '

6

app.set & app.get 사용

데이터 설정

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

데이터 얻기

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

2
그것을 구현하는 나쁜 생각. 모든 사용자에게 영향을 줄 수 있습니다. 모든 req.app는 모든 사용자에게 동일합니다. 대신에 익스프레스 세션을 사용할 수 있습니다 .
ujjal das

5

다음은 다른 의존성을 사용하지 않고 제안하는 것입니다. 노드와 표현 만 사용하고 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("/");
    }

2
req.app.locals는 요청을 한 사용자뿐만 아니라 모든 사용자에게 영향을 미치는 것처럼 보이기 때문에 이것이 나쁜 생각이라고 생각합니다. 사용자에게 데이터가 전달되 자마자 데이터가 지워지 겠지만 때때로 충돌하고 잘못된 정보가 표시되는 것으로 생각합니다. 그리고 어쨌든 그것을 지워야한다면 대신 세션에 저장할 수도 있습니다.
스태커

1
실제로는 "동일한"사용자가 보낸 요청에 영향을 미칩니다. 2 명 이상의 사용자가 "동일한 시간"에 요청을 보내더라도 각 사용자는 자신의 요청 개체와 해당 로컬 개체를 갖게됩니다. 사용
Hussein Dimessi

req는 고유 한 사용자를위한 것이지만 req.app는 모든 사용자를위한 것입니다.
ZeroCho

빠른 세션 을 사용 하여 메시지 보내기
ujjal das

3

쿼리 문자열을 통해 작은 비트의 키 / 값 쌍 데이터를 전달할 수 있습니다.

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

그리고 홈 페이지의 자바 스크립트는 그에 액세스하고 그에 따라 동작을 조정할 수 있습니다.

/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 변경 문제가 제거됩니다.


다른 대답에서 말했듯이 쿼리 문자열은 좋지 않은 것처럼 보입니다. 전달하려는 데이터의 크기가 아직 큰지 알지 못하기 때문입니다. 다른 해결책은 내가 찾은 것보다 더 평범하지만 여전히 동일한 URL을 유지하려는 의도를 깨뜨립니다.
Enrique Moreno Tent

@Dbugger AJAX POST를 사용 하시겠습니까?
AlbertEngelB

1

익스프레스 세션 을 사용 하여 필요한 데이터를 보낼 수 있습니다

앱을 초기화 할 때

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

리디렉션하기 전에 세션의 컨텍스트를 저장하십시오.

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

이제 세션의 어느 곳에서나 컨텍스트를 얻을 수 있습니다. req.session.context로 얻을 수 있습니다.

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

    // So prepare the context
var context=req.session.context;
    res.render('home.jade', context);
});
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.