英文:
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".
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论