视频流导航,在golang中的反向代理

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

navigation in video stream, reverse proxy in golang

问题

我正在测试Go语言中的反向代理。主要是通过底层的nginx播放视频并从其他后端服务器流式传输视频。

问题是在浏览视频时。例如,当通过代理使用vlc播放时,视频开始正常播放,但在尝试导航时停止播放。但是,如果我直接从nginx播放此视频,则可以正常播放。

我期望在导航时播放器会使用Range: N-头创建新的连接,但没有新的连接,只有在重新开始播放视频时才会有连接。

问题:

播放视频流时,播放器是如何导航的?它向服务器发送了什么请求?
也许我在连接处理方面漏掉了什么?

这是一个用于测试的非常基本的版本,它从本地nginx流式传输视频(本地视频URL为http://localhost/31285611):

package main

import (
	"net/http"
)

func main() {
	(&proxy{}).start()
}

type proxy struct {
	// ...
}

func (p *proxy) start() {
	http.HandleFunc("/play", p.connection)
	http.ListenAndServe("localhost:8040", nil)
}

func (p *proxy) connection(w http.ResponseWriter, r *http.Request) {
	disconnect := make(chan bool, 1)
	go p.send(w, r, disconnect)

	// ...

	<-disconnect
}


func (p *proxy) send(rv http.ResponseWriter, rvq *http.Request, disconnect chan bool) {

	rq, _ := http.NewRequest("GET", "http://localhost/31285611", rvq.Body)
	rq.Header = rvq.Header

	rs, _ := http.DefaultClient.Do(rq)
	for k, v := range rs.Header {
		rv.Header().Set(k, v[0])
	}
	rv.WriteHeader(http.StatusOK)

	buf := make([]byte, 1024)

	// for testing sending only first part.
	for i := 0; i < 100000; i++ {
		n, e := rs.Body.Read(buf[0:])
		if n == 0 || e != nil {
			break
		}
		rv.Write(buf[0:])
	}

	disconnect <- true

}

更新(头部信息):

第一个播放器连接:

map[User-Agent:[VLC/2.0.0 LibVLC/2.0.0] Range:[bytes=0-] Connection:[close] Icy-Metadata:[1]]

在Go中创建连接时,从nginx收到的响应:

map[Server:[nginx/1.3.4] Date:[Tue, 23 Apr 2013 13:29:00 GMT] Content-Type:[application/octet-stream] Content-Length:[8147855699] Last-Modified:[Tue, 21 Aug 2012 20:47:20 GMT] Etag:["5033f3d8-1e5a66953"] Content-Range:[bytes 0-8147855698/8147855699]]
英文:

I'm testing a reverse proxy in go. Mainly for playing videos though underlying nginx and streaming videos from other backend servers.

Problem is when navigating through video. For example when playing with vlc through proxy - video starts normally, but stops when trying to navigate. But if i play this video directly from nginx - it works fine.

I expected that on navigation player would create new connection with Range: N- header, but there is no new connections, only when starting video again.

Question:

How does player navigates, when playing video stream? What requests it sends to server?
Maybe i'm missing something in connection handling?

This is very basic version for testing, it streams video from local nginx, (local video url - http://localhost/31285611):

package main
import (
&quot;net/http&quot;
)
func main() {
(&amp;proxy{}).start()
}
type proxy struct {
// ...
}
func (p *proxy) start() {
http.HandleFunc(&quot;/play&quot;, p.connection)
http.ListenAndServe(&quot;localhost:8040&quot;, nil)
}
func (p *proxy) connection(w http.ResponseWriter, r *http.Request) {
disconnect := make(chan bool, 1)
go p.send(w, r, disconnect)
// ...
&lt;-disconnect
}
func (p *proxy) send(rv http.ResponseWriter, rvq *http.Request, disconnect chan bool) {
rq, _ := http.NewRequest(&quot;GET&quot;, &quot;http://localhost/31285611&quot;, rvq.Body)
rq.Header = rvq.Header
rs, _ := http.DefaultClient.Do(rq)
for k, v := range rs.Header {
rv.Header().Set(k, v[0])
}
rv.WriteHeader(http.StatusOK)
buf := make([]byte, 1024)
// for testing sending only first part.
for i := 0; i &lt; 100000; i++ {
n, e := rs.Body.Read(buf[0:])
if n == 0 || e != nil {
break
}
rv.Write(buf[0:])
}
disconnect &lt;- true
}

Update (headers dump):

First player connection:

map[User-Agent:[VLC/2.0.0 LibVLC/2.0.0] Range:[bytes=0-] Connection:[close] Icy-Metadata:[1]]

Response from nginx, when creating connection in go:

map[Server:[nginx/1.3.4] Date:[Tue, 23 Apr 2013 13:29:00 GMT] Content-Type:[application/octet-stream] Content-Length:[8147855699] Last-Modified:[Tue, 21 Aug 2012 20:47:20 GMT] Etag:[&quot;5033f3d8-1e5a66953&quot;] Content-Range:[bytes 0-8147855698/8147855699]]

答案1

得分: 0

我知道这并不真正回答你的问题(而且我还没有足够的积分来评论,所以很抱歉提供这个作为答案!),但你尝试过使用Go的内置http.ReverseProxy(http://golang.org/pkg/net/http/httputil/#ReverseProxy)吗?

这里有一个很好的简单示例https://groups.google.com/forum/?fromgroups=#!topic/golang-nuts/1ufEw_IEVM4,我稍微修改了一下:

package main
import (
"log"
"net/http"
"net/http/httputil"
"net/url"
)
func main() {
proxy := httputil.NewSingleHostReverseProxy(&url.URL{Scheme: "http", Host: "www.google.com", Path: "/"})
err := http.ListenAndServe(":8080", proxy)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}

看看这是否能解决问题。

此外,在之前链接的Google Groups讨论中,提到NginX在分块编码方面存在问题。也许值得检查一下是否相关。

英文:

I know it's not really answering your question (and I don't have enough points to comment yet, so sorry for providing this as an answer!) but have you tried using Go's built in http.ReverseProxy (http://golang.org/pkg/net/http/httputil/#ReverseProxy)?

There seems to be a nice, simple example here https://groups.google.com/forum/?fromgroups=#!topic/golang-nuts/1ufEw_IEVM4 which I've very slightly modified below:

package main
import (
&quot;log&quot;
&quot;net/http&quot;
&quot;net/http/httputil&quot;
&quot;net/url&quot;
)
func main() {
proxy := httputil.NewSingleHostReverseProxy(&amp;url.URL{Scheme: &quot;http&quot;, Host: &quot;www.google.com&quot;, Path: &quot;/&quot;})
err := http.ListenAndServe(&quot;:8080&quot;, proxy)
if err != nil {
log.Fatal(&quot;ListenAndServe: &quot;, err)
}
}

See if that does the job.

Also, in the previously linked Google Groups discussion, there is mention of NginX having issues with chunked encoding. It might be worth checking if this is related.

huangapple
  • 本文由 发表于 2013年4月23日 22:33:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/16172090.html
匿名

发表评论

匿名网友

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

确定