Reputation: 395
I'm developing a control panel and had hired some people to build it for me. They all bailed and I'm left having to cleanup the spaghetti.
What I need to do is this:
Just a simple login process. Problem is that when the login succeeds, the console enters into this redirect loop as you can see below:
[GIN] 2023/02/21 - 15:43:32 | 301 | 1.224601041s | ::1 | POST "/login"
[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 301 with 200
[GIN] 2023/02/21 - 15:43:33 | 200 | 787.3905ms | ::1 | GET "/dashboard"
[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 301 with 200
[GIN] 2023/02/21 - 15:43:33 | 200 | 197.989875ms | ::1 | GET "/login"
[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 301 with 200
[GIN] 2023/02/21 - 15:43:34 | 200 | 817.293166ms | ::1 | GET "/dashboard"
[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 301 with 200
[GIN] 2023/02/21 - 15:43:34 | 200 | 206.107791ms | ::1 | GET "/login"
[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 301 with 200
[GIN] 2023/02/21 - 15:43:35 | 200 | 792.954375ms | ::1 | GET "/dashboard"
[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 301 with 200
[GIN] 2023/02/21 - 15:43:35 | 200 | 201.972708ms | ::1 | GET "/login"
[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 301 with 200
[GIN] 2023/02/21 - 15:43:36 | 200 | 840.773625ms | ::1 | GET "/dashboard"
[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 301 with 200
[GIN] 2023/02/21 - 15:43:36 | 200 | 198.680125ms | ::1 | GET "/login"
[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 301 with 200
[GIN] 2023/02/21 - 15:43:37 | 200 | 897.679708ms | ::1 | GET "/dashboard"
[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 301 with 200
[GIN] 2023/02/21 - 15:43:37 | 200 | 200.759917ms | ::1 | GET "/login"
[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 301 with 200
[GIN] 2023/02/21 - 15:43:38 | 200 | 795.39975ms | ::1 | GET "/dashboard"
[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 301 with 200
[GIN] 2023/02/21 - 15:43:38 | 200 | 196.538ms | ::1 | GET "/login"
[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 301 with 200
[GIN] 2023/02/21 - 15:43:39 | 200 | 844.680709ms | ::1 | GET "/dashboard"
[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 301 with 200
[GIN] 2023/02/21 - 15:43:39 | 200 | 180.598084ms | ::1 | GET "/login"
[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 301 with 200
[GIN] 2023/02/21 - 15:43:40 | 200 | 814.666208ms | ::1 | GET "/dashboard"
[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 301 with 200
[GIN] 2023/02/21 - 15:43:40 | 200 | 210.281ms | ::1 | GET "/login"
Now, since I'm picking up the slack of old devs, I'm still studying/new to Golang and Gin so bare with me...
From what I understand, main()
is configuring the routes, middleware, loading templates then running the engine.
main.go
func main() {
//gin.SetMode(gin.ReleaseMode) // uncomment for production
// Startup Tasks
startup()
logging.LogInfo("Ran Startup Tasks...")
// Configure Engine
hostPort := fmt.Sprintf(
"%s:%d",
dataManagers.LoadConfig().Bshost,
dataManagers.LoadConfig().Bsport)
webEngine := gin.Default()
webEngine.SetTrustedProxies([]string{hostPort})
logging.LogInfo("Configured Engine...")
// Load Middleware
store := cookie.NewStore([]byte(randstr.String(64)))
webEngine.Use(sessions.Sessions("session", store))
webEngine.Use(errorHandler.ErrorsHandler500())
logging.LogInfo("Loaded Middleware...")
// Configure Routes
pubRoutes := webEngine.Group("/")
privRoutes := webEngine.Group("/")
routes.PublicRoutes(pubRoutes)
privRoutes.Use(middleware.AuthRequired)
routes.PrivateRoutes(privRoutes)
logging.LogInfo("Configured Routes...")
// Non Routables
webEngine.NoRoute(errorHandler.ErrorsHandler404())
logging.LogInfo("Configured Non-Routables...")
// Load Template Files
LoadTemplates(webEngine)
logging.LogInfo("Loaded Templates...")
// Start the Gin Engine
err := webEngine.Run(hostPort)
logging.LogInfo("...BlockSuite-WebUI Loaded")
logging.Catch(err)
}
When /
is accessed, I'm redirected to /login
which brings up the login form.
I submit the form with valid credentials and it redirects me to /dashboard
. I don't know if redirect is the correct thing to do after a successful sign-in, that is what the original dev did and it worked fine.
routes.go
func PublicRoutes(webEngine *gin.RouterGroup) {
webEngine.GET("/login", entry.LoginGetHandler)
webEngine.POST("/login", entry.LoginPostHandler)
webEngine.GET("/", other.IndexGetHandler())
}
func PrivateRoutes(webEngine *gin.RouterGroup) {
dashboardRoutes := webEngine.Group("/dashboard")
{
dashboardRoutes.GET("/", dashboard.DashboardGetHandler)
}
}
login.go
func LoginGetHandler(context *gin.Context) {
user := utility.GetUserSession(context).Get("userEmail")
if user != nil {
context.Redirect(http.StatusMovedPermanently, "/dashboard")
}
context.HTML(http.StatusOK, "login.html", gin.H{
"siteKey": dataManagers.GetRecaptchaSettings().SiteKey,
"enabled": dataManagers.GetRecaptchaSettings().Enabled,
"content": "",
"success": "",
"serverLogo": brand.GetBrandLogo(),
"title": "Welcome back",
})
}
func LoginPostHandler(context *gin.Context) {
user := utility.GetUserSession(context).Get("userEmail")
if user != nil {
context.Redirect(http.StatusMovedPermanently, "/dashboard")
//return
}
userEmail := utility.Sanitize(context.PostForm("email"))
password := utility.Sanitize(context.PostForm("password"))
rememberme := utility.Sanitize(context.PostForm("rememberme"))
//captcha := context.PostForm("g-recaptcha-response")
if !utility.IsEmailValid(userEmail) {
context.HTML(http.StatusBadRequest, "login.html", gin.H{"content": "Please enter a valid email address"})
return
}
/*if helpers2.RecaptchaCheck(captcha) || dataManagers.GetConfig().SiteKey != "" {
// success
} else {
if dataManagers.GetConfig().Enabled {
context.HTML(http.StatusBadRequest, "login.html", gin.H{"content": "Please verify captcha"})
return
}
}*/
if utility.EmptyUserPass(userEmail, password) {
context.HTML(http.StatusBadRequest, "login.html", gin.H{"content": "Email and password cannot be empty"})
return
}
if utility.CheckForWhiteSpaces(userEmail, password) != nil {
context.HTML(http.StatusBadRequest, "login.html", gin.H{"content": "Username and password can't contain spaces"})
return
}
if !utility.CheckUserPass(userEmail, password) {
context.HTML(http.StatusUnauthorized, "login.html", gin.H{"content": "Incorrect username or password"})
return
}
utility.NewUserSession(context, userEmail)
if rememberme == "yes" {
utility.SetSessionAge(context)
}
context.Redirect(http.StatusMovedPermanently, "/dashboard")
}
And then, the /dashboard
page is supposed to be loaded.
dashboard.go
func DashboardGetHandler(context *gin.Context) {
user := utility.GetUserSession(context).Get("userEmail")
db := dataManagers.GetDB()
if user == nil {
context.Redirect(http.StatusMovedPermanently, "/login")
}
[...]
context.HTML(http.StatusOK, "dashboard.html", gin.H{
"info": info,
"imageUrl": utility.GetImage(user),
"serverLogo": brand.GetBrandIcon(),
"title": "Dashboard",
"serverName": dataManagers.GetServerInfo().Servername,
})
}
(In the dashboard.go
code, I omitted the code that pulls data into the dashboard as it is long and don't think it is that necessary.)
http.StatusOK
and no dice.func DashboardGetHandler() gin.HandlerFunc {
return func(context *gin.Context) {
[...]
}
}
I'm completely out of ideas and don't know where to go from here. Thanks!
Upvotes: 0
Views: 1802
Reputation: 395
Thanks everyone that pitched in to help. I got with the previous dev and he helped me figure out what was wrong.
In his code, he had created a middleware func that, for some reason, checked the session again. That piece of code was checking old vars that did not exist in the session cookies. Because of that, I was getting kicked back to the login screen.
So, all I did was remove that middleware since I was handling that in login.go anyways.
Upvotes: 0