RFC: HTTP Session Support (draft) #56
Replies: 5 comments 1 reply
I personally don't think so. I'd rather keep the "bones" there and not do anything opinionated like like load user into the Session by default like Django does. Some routes don't need any data, so they shouldn't be given data by default. |
I would put it in its own package to keep functionality separate, but I would keep it as close to top level as possible to prevent a user from creating a circular dependency cycle as much as possible. With sessions being important in large scale web apps, I could see users wanting to pass that struct around, and if they're not careful, creating such a dependency cycle |
I am pretty sure you need custom session storage providers.
There should be a solution for the common choices:
Additional notes:
|
|
I like https://github.com/gorilla/securecookie a lot for cookie management |
|
Heads up: I'd like to revisit this a bit now that generics are becoming more ubiquitous. I could see the custom data being wrapped by types offered by Bud. func Signout(session *bud.Session[session.Data]) {
session.Destroy()
}In type Session struct {
// Custom user session data
}Then in type Session[Data] struct {
Data Data
// private state...
id string
}
func (s *Session) Destroy() {
// ...
} |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
HTTP Sessions
HTTP is a stateless protocol on it's own – you can't tell who made which request. Sessions are built on top of HTTP to map requests to devices. This mapping helps you provide Authentication and Authorization.
Enabling HTTP Session Support
You can add sessions to your application by defining a
Sessionstruct inside your application'ssessionpackage:And inside
session/session.go:By defining a
Sessioninsession/session.go, you've enabled session management. The session cookie will now be sent in the response from all yourcontroller/routes, regardless of whether your actions use the session.With the session now defined, the
Sessiondata will now be persistent for each device across requests using an encrypted HTTP cookie. Whenever you update the fields inside theSessionstruct, you'll see the updated data in subsequent requests.(TODO: Screenshot of the Browser Storage tab)
You can now use this session in your controllers:
Scaffolding Sessions
(TODO: there should also be a
bud new sessionsomething)Extending Sessions
Within the session package, you can extend the session by building types that depend on the Session. Types like
Userbelow. These types can be initialized using functions that support automatic Dependency Injection.You can then depend on the
session.Userfrom your controllers:This helps cut down on the boilerplate. Instead of loading dependent data in each controller, you can define that logic once in the
sessionpackage and share those types across your controllers.Authentication
Now that we've defined a user session, we can use that session in a controller. To demonstrate this, let's implement login and logout actions. To do this, I'll create a session controller, but the name of the controller doesn't matter:
Here's what the session controller might look like:
Visitors
Sessions are broader than signup, login and logout. Sessions simply tie requests to a device. A user doesn't need to be logged in for sessions to be useful.
To see this in action, let's add a property that applies to everyone, even visitors:
(TODO: cleanup this example now that we've explained Extending the Session above.)
In the code above, we first check if the request is from a first-time visitor, otherwise we take the difference between now and the last time they visited the website.
Authorization
While authentication helps you map a request to a user, authorization defines what a user is allowed to do. For example, for a blog, every reader can read a blog post, but only editors can edit a blog post.
We can implement authorization easily by expanding the
Sessionstruct in thesessionpackage:All fields are persisted across requests for a given device. So if you set the CanEdit field on one request, you'll see that field on the set on the next request.
TODO: show authentication example setting CanEdit during login
With
CanEditin place, now when someone logs in, we can use theCanEditboolean to decide whether or not they can edit or update the blog post:Open Questions
web/session/session.go?LastVisitedby default? See Laravel's docs below to see what I mean by the framework bringing some of its own session fields. Generic support will make this so much easier now to have a custom payload data within a framework-provided session wrapper.Resources
All reactions