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. |
Beta Was this translation helpful? Give feedback.
-
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 |
Beta Was this translation helpful? Give feedback.
-
I am pretty sure you need custom session storage providers.
There should be a solution for the common choices:
Additional notes:
|
Beta Was this translation helpful? Give feedback.
-
I like https://github.com/gorilla/securecookie a lot for cookie management |
Beta Was this translation helpful? Give feedback.
-
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() {
// ...
} |
Beta Was this translation helpful? Give feedback.
-
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
Session
struct inside your application'ssession
package:And inside
session/session.go
:By defining a
Session
insession/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
Session
data will now be persistent for each device across requests using an encrypted HTTP cookie. Whenever you update the fields inside theSession
struct, 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 session
something)Extending Sessions
Within the session package, you can extend the session by building types that depend on the Session. Types like
User
below. These types can be initialized using functions that support automatic Dependency Injection.You can then depend on the
session.User
from 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
session
package 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
Session
struct in thesession
package: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
CanEdit
in place, now when someone logs in, we can use theCanEdit
boolean to decide whether or not they can edit or update the blog post:Open Questions
web/session/session.go
?LastVisited
by 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
Beta Was this translation helpful? Give feedback.
All reactions