0

I have a very weird output ... let me post my code first then I will explain:

Under main function I declared

manageMux.HandleFunc("/info", info)

first I log in and redirect from "/login" to page "/":

func login(w http.ResponseWriter, r *http.Request) {
    if r.Method == "GET" {
        t, err := template.ParseFiles("manage/login.html")
        checkError(err)
        t.Execute(w, nil)
    } else { //POST
        r.ParseForm()
        //do some authentications here
        http.Redirect(w, r, "/", http.StatusFound)
    }
}

Then I redirect to another page "/info" from current page "/" (which has only buttons):

func manage(w http.ResponseWriter, r *http.Request) {
    t, err := template.ParseFiles("manage/manage.html")
    checkError(err)
    t.Execute(w, nil)
    r.ParseForm()
    if r.Form["Button"] != nil { //to get only POST actions from buttons
        if r.Form["Button"][0] == "Log" {
            http.Redirect(w, r, "/info", http.StatusFound)
        } 
    }
}

At last, I made a template and would like to show on client side:

const tpl=`stuff inside`

type InfoDefault struct {
    //stuff inside
}

func info(w http.ResponseWriter, r *http.Request) {
    info := InfoDefault{
        //stuff inside
    }

    t, err := template.New("info").Parse(tpl)
    checkError(err)
    err = t.Execute(os.Stdout, info)
    checkError(err)
}

Now, the weird thing is, when I click the button on page "/", I got the error "http: multiple response.WriteHeader calls". At the same time a link called "found" shows up on the bottom of my page (weird!), and when I click the link "found", I got all my parsed template printed on the server side instead of webpage.

Does anyone know why...? And how to fix the error and print stuff on client webpage? Thank you!!!

Kyle
  • 831
  • 1
  • 9
  • 17
  • On a side note, you're parsing all your templates inside your handlers. That can be a drag on performance. http://stackoverflow.com/questions/28451675/it-takes-too-much-time-when-using-template-package-to-generate-a-dynamic-web-p – nosequeldeebee Nov 20 '16 at 00:29

2 Answers2

1

As JimB already pointed out: your server gets confused because there are different status codes associated with both writing to http.ResponseWriter and the redirect. You can't do both at the same time.

I would actually like to expand more on how you can carry data over to the next page (assuming you are redirecting).

Headers You can write some information to the request object and receive it on the destination page. Example:

func myHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("My-Awesome-Header", "Rocks")
    ...
}

Session: You are talking about access control as far as I can see, and I think persisting user data is better done through a session. Example: you can use a database or a session handler like https://github.com/gorilla/sessions. Check out this thread: Best practice with sessions (gorilla/sessions).

Cookies: I'm not sure what kind of front-end you are using, but storing non-sensitive data on the cookie could be an option? Nothing beats this one (it has real choc-chip cookies in the examples ;-) ): https://astaxie.gitbooks.io/build-web-application-with-golang/content/en/06.1.html.

Community
  • 1
  • 1
Sthe
  • 2,575
  • 2
  • 31
  • 48
0

In your manage handler, you're executing the template which will write to the http.ResponseWriter and trigger an http.StatusOK (200) status code. You can't redirect after that, since that requires sending a different response code.

If you need to redirect, do it before executing the template.

JimB
  • 104,193
  • 13
  • 262
  • 255
  • Possible to jump to another page without using redirect and still carrying user identifications? If no then are there any response codes I can use to redirect? thx – Kyle Feb 08 '16 at 18:33
  • @Kyle: Headers will be preserved with a redirect; is that what you mean by "carrying user identifications". A redirect *is* a response code, plus the `Location` header, so I don't know what you mean by the second question at all. – JimB Feb 08 '16 at 18:45