ffel
ffel

Reputation: 277

Http Redirect in Web Socket Connection [now better explained]

I think my original question (see below the bar) was too vague. I have made up the following silly example that shows what is my point.

package main

import (
    "fmt"
    "net/http"
    "time"
)

func main() {
    http.HandleFunc("/redir", redirHandler)
    http.HandleFunc("/", rootHandler)
    _ = http.ListenAndServe("localhost:4000", nil)
}

func redirHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "hello, this is redir which will host the foreign html page")
}

func rootHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "hello, this is root")

    // at some point "foreign webserver" sends me a complete
    // html page.
    // I want to serve this page at "/redir/", and I feel my
    // best shot is to redirect to "/redir"
    time.Sleep(2 * time.Second)

    http.Redirect(w, r, "/redir/", http.StatusFound)
}

This code does not work, as I cannot re-use w to perform the re-direct. So, is it possible to redirect in this case, for example by means of another http package call?

I hope I've made myself clear...

Thanks in advance

Chris


I am working on "my server" in the following configuration

[web browser client] -- [my server] -- [foreign webservice]

"my server" provides the following to "web browser client"

func main() {
    http.HandleFunc("/launch", launchHandler)
    http.HandleFunc("/", rootHandler)
    http.Handle("/socket", websocket.Handler(socketHandler))
    err := http.ListenAndServe(listenAddr, nil)
    if err != nil {
        log.Fatal(err)
    }
}

RootHandler writes an html page to "web browser client", and socketHandler establishes a websocket connection between "web browser client" and "my server".

Requests from "web browser client" arrive over the web socket connection and are handled by "my server", "my server" communicates with "foreign webservice" to determine the response.

Usually, "foreign webservice" gives a little bit of data which is used by "my server" to respond to "web browser client".

In some occasions, "foreign webservice" responds with a complete html page.

I am not sure how to communicate such html page to "web browser client"

My best guess so far is to execute a http.Redirect() to launchHandler such that launchHandler can write the html page as obtained from "foreign web server" to "web browser client". (It is no problem when the web socket connection is closed.)

In order to do so, I use the http.ResponseWriter, *http.Request as parameters to httpRedirect which were received in rootHandler in the first place.

This does not work and produced log message: "http: multiple response.WriteHeader calls"

Any suggestions on how to fix this? Maybe my approach to perform a http.Redirect is wrong; Maybe I should obtain an other http.ResponseWriter and/or *http.Request values.

Any help is appreciated!

Upvotes: 1

Views: 6488

Answers (1)

minikomi
minikomi

Reputation: 8503

There are a few things you need to change from the new example you've given:

  • As soon as you call fmt.Fprint, you're returning a response and thus a header (with status code 200). Check http://golang.org/pkg/net/http/#ResponseWriter

    // Changing the header after a call to WriteHeader (or Write) has no effect.

If you want a simple redirect, leave out the fmt.Fprint(w, "hello, this is root") .

  • /redir and /redir/ are different endpoints. You need to either change the URL of your handler or the redirection.
  • If you want to display a page and then redirect after downloading has happened in the background, I suggest using Javascript with a third handler, which you can call in the background from the HTML page returned from the root handler, and have a callback which redirects the user once done

For example..:

   +------------+ $.GET +---------------------+   
   | Root page  | ----> |  Background handler |  
   |            |       +---------+-----------+
   |            |                 |
   +------------+ <---Task done---+
         |
         v [redirect using JS]
    +---------------+  
    |/redir/ handler|
    +---------------+

Another option is perhaps to use an iframe to display the "foreign webpage".

Upvotes: 2

Related Questions