How do I copy http response from a source and forward it to n clients?

agolangf · · 455 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I am writing this simple MJPEG relay and I have it working for 1 source to n clients. It reads a MJPEG stream, reads the response body and header and sends it to any other client. The point of this is to replicate the stream on a server without putting to much load on the IP camera that can&#39;t handle many connections at once. Now I wanna expand this to work with N number of cameras as well as N number of clients. My old code for 1 camera to N client looks like this:</p> <pre><code>package mjpeg import ( &#34;flag&#34; &#34;image&#34; &#34;image/jpeg&#34; &#34;io&#34; &#34;log&#34; &#34;net/http&#34; &#34;os&#34; &#34;sync&#34; &#34;github.com/mattn/go-mjpeg&#34; ) // Flags for the source MJPEG stream and the server port var url = flag.String(&#34;url&#34;, &#34;&#34;, &#34;URL for the MJPEG stream&#34;) var addr = flag.String(&#34;addr&#34;, &#34;:8080&#34;, &#34;Port to listen on&#34;) // RelayStream reads a MJPEG stream and creates a relay for n number of clients to access func RelayStream() error { // Parse the input flags for port and MJPEG source url flag.Parse() if *url == &#34;&#34; { flag.Usage() os.Exit(1) } log.Println(&#34;Relay stream started&#34;) // Serve the MJPEG video in the default route of / http.HandleFunc(&#34;/&#34;, func(w http.ResponseWriter, r *http.Request) { // Read the mjpeg stream resp, err := http.Get(*url) if err != nil { log.Println(&#34;Error fetching response&#34;) return } // Copy headers from the response to our relay w.Header().Set(&#34;Content-Type&#34;, resp.Header.Get(&#34;Content-Type&#34;)) w.Header().Set(&#34;Content-Length&#34;, resp.Header.Get(&#34;Content-Length&#34;)) // Copy the body io.Copy(w, resp.Body) resp.Body.Close() log.Println(&#34;Relay stream stopped&#34;) }) // Listen on the specifed port and serve the MJPEG err := http.ListenAndServe(*addr, nil) if err != nil { log.Println(&#34;Error listening on the port&#34;) return err } return nil } </code></pre> <p>Now I wanna pass in a list of URLs in the form of url []string instead of using 1 url. I can probably generate the route strings using some sort of uuid generator. But how would setup reading and serving stream for each camera?</p> <hr/>**评论:**<br/><br/>mattn: <pre><p>For example, &#34;/XXXXXXXXXXXXX&#34; given as md5 hash of camera URL?</p></pre>zeus-man: <pre><p>Yup something like that. Hey are you the guy behind <a href="https://github.com/mattn/go-mjpeg" rel="nofollow">https://github.com/mattn/go-mjpeg</a> and the sql library? Love your stuff! I found the go-mjpeg very useful and even contributed a little. Cheers!</p></pre>janderssen: <pre><p>In the handler you could use the gorilla web toolkit : github.com/gorilla</p> <p>Then you could define your route as &#34;/{cameraId}&#34;, then inside the handler it is as simple as follows :</p> <pre><code>func restConnectToCamera(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) cameraId := vars[&#34;cameraId&#34;] } </code></pre> <p>I think this is what you are trying to do ?</p> <p>Cheers and hope this helps</p></pre>zeus-man: <pre><p>Ah yes. This solves my initial pain with the route generation.</p></pre>zeus-man: <pre><p>On an unrelated note is there any example of doing this but with httprouter instead?</p></pre>silviucm: <pre><pre><code>// define your route router.GET(&#34;/myfeeds/:camId&#34;, streamStuff) ... // handler func streamStuff(w http.ResponseWriter, r *http.Request, params httprouter.Params) { id := params.ByName(&#34;camId&#34;) ... } </code></pre></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

455 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传