在Web Socket连接中的HTTP重定向[现在更好地解释]

huangapple go评论91阅读模式
英文:

Http Redirect in Web Socket Connection [now better explained]

问题

我认为我最初的问题(请参见下面的分隔线)太模糊了。我编写了以下愚蠢的示例,展示了我的观点。

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)
}

这段代码无法工作,因为我无法重用w来执行重定向。那么,在这种情况下是否可能进行重定向,例如通过另一个http包调用的方式?

我希望我已经表达清楚了...

提前感谢

Chris


我正在使用以下配置工作在“我的服务器”上

[web浏览器客户端] -- [我的服务器] -- [外部网络服务]

“我的服务器”向“web浏览器客户端”提供以下功能

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将一个html页面写入“web浏览器客户端”,而socketHandler在“web浏览器客户端”和“我的服务器”之间建立了一个websocket连接。

来自“web浏览器客户端”的请求通过网络套接字连接到达,并由“我的服务器”处理,“我的服务器”与“外部网络服务”通信以确定响应。

通常,“外部网络服务”提供一些数据,由“我的服务器”用于响应“web浏览器客户端”。

在某些情况下,“外部网络服务”会响应一个完整的html页面。

我不确定如何将这样的html页面传递给“web浏览器客户端”。

到目前为止,我最好的猜测是执行http.Redirect()到launchHandler,以便launchHandler可以将从“外部网络服务器”获取的html页面写入“web浏览器客户端”。 (当网络套接字连接关闭时没有问题。)

为此,我使用http.ResponseWriter,*http.Request作为参数传递给httpRedirect,这些参数最初在rootHandler中接收到。

这样做不起作用,并生成日志消息:“http: multiple response.WriteHeader calls”

有关如何解决此问题的任何建议?也许我的执行http.Redirect的方法是错误的;也许我应该获取另一个http.ResponseWriter和/或*http.Request值。

感谢任何帮助!

英文:

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!

答案1

得分: 2

你需要从你给出的新示例中更改一些内容:

  • 一旦调用了fmt.Fprint,你就会返回一个响应,从而返回一个带有状态码200的头部。请查看http://golang.org/pkg/net/http/#ResponseWriter

    // 在调用WriteHeader(或Write)之后更改头部没有效果。

如果你只想简单地重定向,可以省略fmt.Fprint(w, "hello, this is root")

  • /redir/redir/是不同的端点。你需要更改处理程序的URL或重定向。

  • 如果你想在后台下载完成后显示页面并进行重定向,我建议使用JavaScript和第三个处理程序。你可以从根处理程序返回的HTML页面中后台调用它,并在完成后有一个回调函数来重定向用户。

例如:

   +------------+ $.GET +---------------------+   
   | 根页面     | ----> |  后台处理程序       |  
   |            |       +---------+-----------+
   |            |                 |
   +------------+ <---任务完成---+
         |
         v [使用JS进行重定向]
    +---------------+  
    |/redir/ 处理程序|
    +---------------+

另一个选择可能是使用iframe来显示“外部网页”。

英文:

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".

huangapple
  • 本文由 发表于 2013年1月22日 05:18:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/14447376.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定