gorilla/context和gorilla/sessions有什么不同之处?

huangapple go评论93阅读模式
英文:

How is gorilla/context different from gorilla/sessions?

问题

我理解你想要翻译的内容是关于使用PHP和gorilla/sessions设置和获取会话的代码部分。以下是翻译的结果:

我使用PHP获取会话,之前的代码如下:

<?php
session_start();
$_SESSION["key"] = "val";
echo $_SESSION["key"];
?>

在服务器端设置一个或多个键及其对应的值,并能够在会话过期之前检索或覆盖它。

使用gorilla/sessions的情况如下:

var (
    sessionStore  *sessions.CookieStore
    sessionSecret []byte = make([]byte, 64)
    session       *sessions.Session
)

func init() {
    sessionSecret = []byte("12345678901234567890123456789012")
    sessionStore = sessions.NewCookieStore(sessionSecret)
    session = sessions.NewSession(sessionStore, "session_name")
}

func SetSessionHandler(w http.ResponseWriter, r *http.Request) {
    session, _ = sessionStore.Get(r, "session_name")
    session.Values["key"] = "val"
    session.Save(r, w)
}

func GetSessionHandler(w http.ResponseWriter, r *http.Request) {
    session, _ = sessionStore.Get(r, "session_name")
    fmt.FPrintln(session.Values["key"])
}

现在我不明白gorilla/context的作用是什么。我知道什么是上下文,但是我不知道它在整个架构中的作用。它说它与当前请求绑定。Stack Overflow 上的另一个问题说“在这种情况下,仅使用gorilla/context就足够了”。

但是如果它是与请求绑定的...语法错误,无法计算。如果一只鸭子能浮在水上,那么女巫就是由木头做成的。因为鸭子也能浮在水上,如果她的重量与鸭子相同,那么她一定是女巫。或者类似于这样的情况 gorilla/context和gorilla/sessions有什么不同之处?

当它与请求绑定时,作为一个中间件“管理器”,它如何有用?我无法全局设置它。你可以给出一个使用gorilla/sessions和gorilla/context的示例吗?

英文:

I get sessions, coming from PHP I used to

&lt;?php
session_start();
$_SESSION[&quot;key&quot;] = &quot;val&quot;;
echo $_SESSION[&quot;key&quot;];
?&gt;

Set one or more keys and their values serverside and be able to retrieve or overwrite it until the session expires.

The same with gorilla/sessions

var(
  	sessionStore  *sessions.CookieStore
   	sessionSecret []byte = make([]byte, 64)
   	session       *sessions.Session
)

func init(){
	sessionSecret = []byte(&quot;12345678901234567890123456789012&quot;)
	sessionStore = sessions.NewCookieStore(sessionSecret)
	session = sessions.NewSession(sessionStore, &quot;session_name&quot;)
}

func SetSessionHandler(w http.ResponseWriter, r *http.Request) {
    session, _ = sessionStore.Get(r, &quot;session_name&quot;)
	session.Values[&quot;key&quot;] = &quot;val&quot;
	session.Save(r, w)
}

func GetSessionHandler(w http.ResponseWriter, r *http.Request) {
    session, _ = sessionStore.Get(r, &quot;session_name&quot;)
    fmt.FPrintln(session.Values[&quot;key&quot;])
}

Now I don't get what the point of gorilla/context is.
I know what a context is but... I don't know how it fits in the big picture.
It says that it's bound to the current request. Another question here on stackoverflow said that "simply using gorilla/context should suffice" in the context of https://stackoverflow.com/questions/19784687/writing-per-handler-middleware.

But if it's request bound... err.. syntax error, does not compute. If a duck floats on water then witches are made from wood. And because ducks also float on water if her weight is the same as that of a duck she must be a witch. Or something like that gorilla/context和gorilla/sessions有什么不同之处?

And how could this be useful as a middleware "manager" when it's request-bound, I can't set it globally. Could you perhaps show an example of how a gorilla/sessions could be used with gorilla/context?

答案1

得分: 10

作为提出另一个问题的人:

  • gorilla/context 允许您在请求中存储数据。如果您有一些中间件在继续处理请求之前对请求进行一些预处理(例如反CSRF),您可能希望在请求中存储一个令牌,以便处理程序可以将其传递给模板。gorilla/context 文档对此有很好的解释

> ... 路由器可以设置从 URL 提取的变量,然后应用程序处理程序可以访问这些值,或者可以用于存储会话值以在请求结束时保存。还有其他几种常见用途。

  • 您可能还希望将数据存储在会话中:表单提交的错误消息、用户 ID 或该访问者的 CSRF 令牌的“规范”版本可能会存储在这里。如果您尝试将错误消息存储在请求上下文中,然后重定向用户,您将丢失它(那是一个新的请求)。

那么为什么要使用上下文而不是会话?它更轻量级,并且允许您将应用程序的部分(通常是 HTTP 中间件!)解耦。

示例:

  1. 请求进来
  2. CSRF 中间件检查会话中是否存在现有的 CSRF 令牌。不存在,则设置一个新的令牌。
  3. 它还通过请求上下文将这个新令牌传递给渲染表单的处理程序,以便它可以在模板中渲染它(否则您将不得不再次从会话中获取令牌,这是浪费的努力)
  4. 请求完成。
  5. 表单提交的新请求
  6. 令牌仍然存在于会话中,因此我们可以将其与表单提交的令牌进行比较。
  7. 如果检查通过,我们继续处理表单
  8. 如果不通过,我们可以在会话中保存一个错误(闪存消息;即在读取后被删除的消息)并进行重定向。
  9. 这个重定向是一个新的请求,因此我们无法通过请求上下文传递错误消息。
英文:

As the person who asked that other question:

  • gorilla/context allows you to store data in the request. If you have some middleware that does some pre-processing on a request before deciding to continue (i.e. anti-CSRF), you might want to store a token in the request so your handler can pass it to the template. The gorilla/context documentation explains it well:

> ... a router can set variables extracted from the URL and later application handlers can access those values, or it can be used to store sessions values to be saved at the end of a request. There are several others common uses.

  • You may also want to store data in the session: error messages from form submissions, a user ID, or the 'canonical' version of the CSRF token for that visitor will likely be stored here. If you try to store an error message in the request context, and then re-direct the user, you'll lose it (that's a new request).

So why would you use context over sessions? It's lighter, and allows you to de-couple parts of your application (often, HTTP middleware!) from each other.

Example:

  1. Request comes in
  2. CSRF middleware checks the session for an existing CSRF token. Does not exist, so it sets one.
  3. It also passes this new token (via the request context!) to the handler that renders your form, so it can render it in the template (otherwise you would have to pull the token from the session again, which is wasted effort)
  4. Request is done.
  5. New request on form submission
  6. The token still persists in the session, so we can compare it to the submitted token from the form.
  7. If it checks out, we proceed to process the form
  8. If not, we can save an error in the session (a flash message; i.e. one that is erased after reading) and re-direct.
  9. This re-direction is a new request, and therefore we can't pass the error message via the request context here.

答案2

得分: 0

一个例子。

我正在编写这个多社区论坛软件。
现在我有一个gorilla/mux路由器,为主域名提供不同的内容,另一个路由器为子域名.domain.tld提供经过筛选的不同内容。

上下文在这里非常有用,否则你会一遍又一遍地重复自己。所以,如果我知道对于子域名路由器,每个请求都需要进行字符串操作来找出子域名,并检查它是否存在于数据库中,我可以在这里(在上下文中)为每个请求执行此操作,然后将子域名存储在上下文变量中。
同样,如果设置了论坛的类别slug、论坛slug或者主题slug,将其传递给处理程序,在“上下文”中保留需要进行的处理,并在处理程序中减少代码量。

因此,上下文的优势在于保持代码的DRY(Don't Repeat Yourself)。

就像elihrar所写的,他的CSRF令牌的例子。如果你知道每个请求都需要检查CSRF令牌-不要在每个需要执行此操作的处理程序中重复此检查,而是编写一个上下文包装器(/http.Handler),并为每个请求执行此操作。

英文:

An example.

I'm writing this multi-community-forum software.
Now I have a gorilla/mux router that serves different content for the main domain and another router that serves different content filtered by subdomain.domain.tld.

Context is very useful here, else you would repeat yourself over and over again. So if I know that for the subdomain router every request would do string operations to find out the subdomain name and check if it exists in the database I could just do this here (in context) for every request and then store the subdomain name in a context variable.
And likewise if a forum's category slug or forum slug or a thread slug is set pass it to the handler, keep the processing that needs to be done in "context" and have less code in your handlers.

So the advantage of context is essentially to keep code DRY.

Like elihrar wrote, his example of a CSRF token. If you know that you need to check for the CSRF token on each request - don't duplicate this check in every handler that needs to do this, instead write a context wrapper ( / http.Handler) and do this for every request.

huangapple
  • 本文由 发表于 2013年12月6日 11:21:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/20415340.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定