简体   繁体   English

Iron Router和Meteor中的服务器端路由

[英]Server side routes in Iron Router and Meteor

Forward 向前

It seems that in Meteor, we cannot call a server side route to render a file to the page without some sort of work-around from our normal workflow, from what I've read about server side routes. 似乎在Meteor中,我们无法调用服务器端路由将文件呈现到页面,而无需从我们正常的工作流程中进行某种处理,从我读到的有关服务器端路由的内容。 I hope I'm wrong about this, and there's a simple way to achieve what I'm looking to do... 我希望我对此错了,并且有一种简单的方法来实现我想要做的......

** Sorry if this is a little long, but I think in this case providing more background and context is warranted ** **对不起,如果这有点长,但我认为在这种情况下提供更多的背景和背景是有道理的**

Software/Versions 软件/版本

I'm using the latest Iron Router 1.* and Meteor 1.* and to begin, I'm just using accounts-password. 我正在使用最新的Iron Router 1. *和Meteor 1. *并开始,我只是使用帐户密码。

Background/Context 背景/上下文

I have an onBeforeAction that simply redirects the user to either the welcome page or home page base upon if the user is logged in or not: 我有一个onBeforeAction,根据用户是否登录,只需将用户重定向到欢迎页面或主页:

both/routes.js 两者/ routes.js

Router.onBeforeAction(function () {
  if (!Meteor.user() || Meteor.loggingIn())
    this.redirect('welcome.view');
  else
    this.next();
  }
  ,{except: 'welcome.view'}
);

Router.onBeforeAction(function () {
  if (Meteor.user())
    this.redirect('home.view');
  else
    this.next();
  }
  ,{only: 'welcome.view'}
);

In the same file, both/routes.js, I have a simple server side route that renders a pdf to the screen, and if I remove the onBeforeAction code, the route works (the pdf renders to the page): 在同一个文件中,两个/ routes.js,我有一个简单的服务器端路由,将pdf呈现给屏幕,如果我删除onBeforeAction代码,路由工作(pdf呈现到页面):

Router.route('/pdf-server', function() {
  var filePath = process.env.PWD + "/server/.files/users/test.pdf";
  console.log(filePath);
  var fs = Npm.require('fs');
  var data = fs.readFileSync(filePath);
  this.response.write(data);
  this.response.end();
}, {where: 'server'});

Exception thrown on Server Route 服务器路由上抛出异常

It's beside the point, but I get an exception when I add the above server side route to the file and take the route /pdf-server, while keeping the onBeforeAction code in place. 它不是重点,但是当我将上述服务器端路由添加到文件并获取路由/ pdf-server时,我得到一个例外,同时保持onBeforeAction代码到位。

Insights into the exception can be found here: SO Question on Exception 可以在此处找到对异常的见解: SO异常问题

Solution to the Exception 解决异常

The main gist of the answer in the SO Question above is "You use Meteor.user() in your Route.onBeforeAction but it has no access to this information" , and when, "your browser make a GET/POST request" [Server side route?], "to the server it doesn't have any information regarding the user's authentication state." 上面的SO问题中答案的主要要点是"You use Meteor.user() in your Route.onBeforeAction but it has no access to this information""your browser make a GET/POST request" side route?], "to the server it doesn't have any information regarding the user's authentication state."

The solution, according to the same SO answerer is to "find an alternative way to authenticate the user," and one way to do this is to use "cookies'" . 根据相同的SO回答者的解决方案是"find an alternative way to authenticate the user,"方法"find an alternative way to authenticate the user," ,其中一种方法是使用"cookies'"

So, following up on this, I found another SO answer (by the same answerer as before), where a method to set and get the cookies is outlined here: SO Cookies technique 所以,跟进这个,我找到了另一个SO答案(与之前一样的回答者),其中概述了设置和获取cookie的方法: SO Cookies技术

** So, to summarize, in order to allow for server side routes, it is suggested I use cookies instead of something like Meteor.userId() or this.userId. **因此,总而言之,为了允许服务器端路由,建议我使用cookie而不是Meteor.userId()或this.userId。 ** **

Cookie related code added 添加了Cookie相关代码

So I added the following code to my project: client/main.js 所以我将以下代码添加到我的项目中:client / main.js

Deps.autorun(function() {
    if(Accounts.loginServicesConfigured() && Meteor.userId()) {
        setCookie("meteor_userid",Meteor.userId(),30);
        setCookie("meteor_logintoken",localStorage.getItem("Meteor.loginToken"),30);
    }
}); 

In my server side route, I changed the route to this: 在我的服务器端路由中,我将路由更改为:

both/routes.js 两者/ routes.js

Router.route('/pdf-server', function() {
  //Parse cookies using get_cookies function from : https://stackoverflow.com/questions/3393854/get-and-set-a-single-cookie-with-node-js-http-server
  var userId = get_cookies(req)['meteor_usserid'];
  var loginToken = get_cookies(req)['meteor_logintoken'];
  var user = Meteor.users.findOne({_id:userId, "services.resume.loginTokens.token":loginToken});
  var loggedInUser = (user)?user.username : "Not logged in";

  var filePath = process.env.PWD + "/server/.files/users/test.pdf";
  console.log(filePath);
  var fs = Npm.require('fs');
  var data = fs.readFileSync(filePath);
  this.response.write(data);
  this.response.end();
}, {where: 'server'});

But this does not work as expected, the setCookie code is not valid for some reason. 但是这没有按预期工作,setCookie代码由于某种原因无效。

My Questions 我的问题

Question 1: Setting/getting the cookies in the manner depicted in the SO Cookies technique doesn't seem to work for me, does this technique still work in '15? 问题1:以SO Cookies技术描述的方式设置/获取cookie对我来说似乎不起作用,这项技术是否仍然适用于'15?

Question 2: Using cookies, how do I inform the server of the authentication state based on these cookies? 问题2:使用cookie,如何根据这些cookie通知服务器认证状态? Or, another way, How does adding the cookie check in my server side route "inform" the server about the user? 或者,另一种方式,如何在我的服务器端路由中添加cookie检查“通知”服务器有关用户的信息? I could check for anything in this route really; 我真的可以检查这条路线上的任何东西; I could reject any user, but somehow the server needs to "know" about the user logged in right? 我可以拒绝任何用户,但不知何故,服务器需要“知道”用户登录的权利吗?

Question 3: Is cookies the best way to go about this, or is there a simpler way to achieve the same thing? 问题3:Cookie是最好的解决方法,还是有更简单的方法来实现同样的目标?

Side Question: I've seen a few places where middle ware is used for server side routes, for example: 方问:我看过一些中间件用于服务器端路由的地方,例如:

WebApp.connectHandlers.stack.splice(...);

WebApp.connectHandlers.use(function(...) ...);

But none of these examples had security inside, will using middle ware in this way allow me to get around my problem? 但是这些例子都没有内部安全性,以这种方式使用中间件可以让我解决我的问题吗?

Your server-side routes are running the global onBeforeAction code (it's defined in a shared directory), which breaks because the server routes are simple REST endpoints which don't understand user authentication information (ie Meteor.user() doesn't work). 您的服务器端路由正在运行全局onBeforeAction代码(它在共享目录中定义),因为服务器路由是简单的REST端点,它们不了解用户身份验证信息(即Meteor.user()不起作用) 。 The solution is to wrap the client-specific onBeforeAction calls with Meteor.isClient or simply move that code under the client directory. 解决方案是使用Meteor.isClient包装特定于客户端的onBeforeAction调用,或者只是将该代码移动到client目录下。 For example: 例如:

if (Meteor.isClient) {
  Router.onBeforeAction(function () {
    if (!Meteor.user() || Meteor.loggingIn())
      this.redirect('welcome.view');
    else
      this.next();
    }
    ,{except: 'welcome.view'}
  );

  Router.onBeforeAction(function () {
    if (Meteor.user())
      this.redirect('home.view');
    else
      this.next();
    }
    ,{only: 'welcome.view'}
  );
}

Router.route('/pdf-server', function() {
  ...
}, {where: 'server'});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM