How is gorilla/context different from gorilla/sessions?
Asked Answered
P

2

9

I get sessions, coming from PHP I used to

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

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

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

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?

Pipestone answered 6/12, 2013 at 3:21 Comment(1)
If you look at Be ego (another web framework for Go). The context is pretty much a wrapper for everything, request details, response, parameter values, header values etc.. and basically everything you might need to know about the request issuer.Betz
F
10

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.
Few answered 6/12, 2013 at 3:30 Comment(3)
Aah in the scope of the requests's context (3.). So request comes in, middleware sets temporary (keyword) value, handler reads value from gorilla/context... but in 6. you write that it persists in the session, do you store the token in the session? ... I forgot to mention that I'm not doing server-side template rendering but RESTful JSON requests (angular). I'd like to write an auth middleware (for starters) that checks if the user is (set or) valid on every request that is not serving static files and then the handler should decide if it returns success or error.Pipestone
Storing things in the request context can exist entirely independent of session storage. Your auth middleware might check a header and/or make a DB call to see if that user is valid, and you might save their ID in the context so your handler can send it back in the response (or something like that).Few
thank you. I know we shouldn't post thank yous but I don't care. Thanks for taking the time to explain itPipestone
P
0

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.

Pipestone answered 17/2, 2014 at 16:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.