I am trying to do a simple login. I followed a tutorial on Udemy. It went through rendering templates with a render function. I decided I wanted to handle templates differently and not have a render function and changed everything around. But I did not touch the PostLoginHandler. Since I made this change my post for "/login" has stopped working. I get "400 bad request" and I can't figure out why. I'll include the code that I think is important. I will say that I think it has something to do with the request, and/or CRSF token the tutorial added that I have not used since the changes. I am not using template.Must(template.ParseGlob("./templates/*.tmpl")) for handling templates.
Also, I'm sorry about the long post, I wasn't sure what info would be needed. Thank you in advance for any responses.
Old render function.
func RenderTemplate(w http.ResponseWriter, r *http.Request, t string, pd *models.PageData) {
var tmpl *template.Template
var err error
_, inMap := tmplCache[t]
if !inMap {
err = makeTemplateCache(t)
if err != nil {
fmt.Println(err)
} else {
fmt.Println("Template in cache")
}
}
tmpl = tmplCache[t]
pd = AddCSRFData(pd, r)
err = tmpl.Execute(w, pd)
if err != nil {
fmt.Println(err)
}
}
routes
mux := chi.NewRouter()
mux.Use(middleware.Recoverer)
mux.Use(NoSurf)
mux.Use(SetupSession)
mux.Post("/login", handlers.Repo.PostLoginHandler)
It's not even getting to the PostLoginHandler, but the code is
func (m *Repository) PostLoginHandler(w http.ResponseWriter, r *http.Request) {
log.Println("here")
//strMap := make(map[string]string)
_ = m.App.Session.RenewToken(r.Context())
err := r.ParseForm()
if err != nil {
log.Fatal(err)
}
email := r.Form.Get("email")
password := r.Form.Get("password")
form := forms.New(r.PostForm)
form.HasRequired("email", "password")
form.IsEmail("email")
if !form.Valid() {
err := m.App.UITemplates.ExecuteTemplate(w, "login.page.tmpl", &models.PageData{Form: form})
if err != nil {
return
}
//render.RenderTemplate(w, r, "login.page.tmpl", &models.PageData{Form: form})
return
}
id, _, err := m.DB.AuthenticateUser(email, password)
if err != nil {
m.App.Session.Put(r.Context(), "error", "Invalid Email OR Password")
http.Redirect(w, r, "/login", http.StatusSeeOther)
return
}
m.App.Session.Put(r.Context(), "user_id", id)
m.App.Session.Put(r.Context(), "flash", "Valid Login")
http.Redirect(w, r, "/", http.StatusSeeOther)
//render.RenderTemplate(w, r, "page.page.tmpl", &models.PageData{StrMap: strMap})
}
and lastly, the HTML is a simple form
<form method="post" action="/login">
{{/*<input type="hidden" name="csrf_token" value="{{.CSRFToken}}">*/}}
<h1 class="h3 mb-3 fw-normal">Please sign in</h1>
<div class="form-floating">
<input type="email" class="form-control" id="email" name="email" placeholder="[email protected]">
<label for="email">Email address</label>
</div>
<div class="form-floating">
<input type="password" class="form-control" id="password" name="password" placeholder="Password">
<label for="password">Password</label>
</div>
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me"> Remember me
</label>
</div>
<button class="w-100 btn btn-lg btn-primary" type="submit">Sign in</button>
</form>
400 bad requestis getting withNosurfmiddleware.Firstly, you should un-comment this in your template. As this is required for crsf validation.
Secondly, you should ensure that the
CSRFTokencorrectly passed into the template. I hope this is updating withinAddCSRFDatafunction.By default the package is not logging anything when an error happened. But it is possible to override the
failure handlerto see what exact reason caused the400 bad request.See the sample code
Hoping this will help you to resolve your problem.