-2

I would like to style Errors in my Go Web Application.

Currently I am handling errors like the following example:

if !ok {
    http.Error(w, "Username and/or password do not match", http.StatusForbidden)
    return
}

However this causes the error message to be displayed in the browser as simple text. I would like to style my errors with HTML & CSS, but it seems bad practice to simply ignore the http.Error method and use:

TPL := template.Must(template.ParseGlob("templates/*.gohtml"))
if !ok {
    TPL.ExecuteTemplate(w, "usernamePasswordMismatch.gohtml", nil)
}

Can someone recommend a way to properly handle my error, with the http.Error method or something similar, and still style my Error page with HTML & CSS?

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Peter
  • 119
  • 12
  • This is often called "message flashing". Typically what you do is have a cookie that you can push messages onto (usually with a severity, e.g. info, warning, error, etc). Then using javascript you get the messages from the cookie and clear it. For example, you could have an element `
    ` that, on page load, you insert messages into based on the cookie.
    – Jessie Sep 06 '19 at 14:54
  • The more proper way is to bind the messages to your request that you can access in the template, but the cookie method is more universal. – Jessie Sep 06 '19 at 14:55
  • @Jesse can you expand on your second comment? How do you bind the messages to your request, and how do you access this in a template? Can you provide some pseudo-code example as an answer? – Peter Sep 06 '19 at 14:58
  • 2
    Just treat it like a normal page; make a template with a replacement for your message and ignore `http.Error()`. That method is convenience for people not concerned with formatting. – RickyA Sep 06 '19 at 15:01
  • simple template replacement -> https://gowebexamples.com/templates/ – RickyA Sep 06 '19 at 15:05
  • Ok I will go with the second method. Thank you all. – Peter Sep 06 '19 at 15:08
  • In the second method, you should `w.WriteHeader(http.StatusForbidden)` before executing the template. – Charlie Tumahai Sep 06 '19 at 15:13

1 Answers1

0

Before executing the template, you can manually write the http status code with w.WriteHeader you want returned:

TPL := template.Must(template.ParseGlob("templates/*.gohtml"))
if !ok {
    w.WriteHeader(http.StatusForbidden)
    TPL.ExecuteTemplate(w, "usernamePasswordMismatch.gohtml", nil)
}

You want to call WriteHeader before writing the actual data or else the ResponseWriter will automatically use StatusOK as the response:

// If WriteHeader has not yet been called, Write calls
// WriteHeader(http.StatusOK) before writing the data.
xgord
  • 4,606
  • 6
  • 30
  • 51
  • This doesn't address the question. – Jessie Sep 06 '19 at 18:51
  • @xgord Yes this addresses the question. Cerise Limon in the comments above wrote it also. Appreciate it. I can't upvote because of my reputation. – Peter Sep 06 '19 at 18:59
  • @Jesse how does it not answer the question? the OP wanted to return an http error status but also render a template. – xgord Sep 06 '19 at 19:53
  • @Peter ah, so Cerise Limon did. Didn't even notice that comment. Glad you figured out your problem. – xgord Sep 06 '19 at 19:54