10

I've written this simple http server to serve video file:

package main

import (
    "net/http"
    "os"
    "bytes"
    "io"
    "fmt"
)

func handler(w http.ResponseWriter, r *http.Request) {

rangeValue := r.Header.Get("range")
fmt.Println("Range:")
fmt.Println(rangeValue)

buf := bytes.NewBuffer(nil)
f, _ := os.Open("oceans_1.webm")
io.Copy(buf, f)           // Error handling elided for brevity.
f.Close()

w.Header().Set("Accept-Ranges","bytes")
w.Header().Set("Content-Type", "video/webm")
w.Header().Set("Content-Length","22074728")
w.Header().Set("Last-Modified", "Wed, 29 Nov 2017 17:10:44 GMT")

w.WriteHeader(206)
w.Write(buf.Bytes())
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}

The video is served perfect, but I can not change time of the video. When I click on the timeline video cursor it doesn't change the position and the video doesn't jump to specific time.

When I serve the video using http.ServeFile(w, r, "oceans_1.webm") everything works perfect - I can change video time.

Simon
  • 1,099
  • 1
  • 11
  • 29
  • 7
    Because seeking the video at client side requires support for partial content serving from the server. See possible duplicate: [How to serve http partial content with Go?](https://stackoverflow.com/questions/36540610/how-to-serve-http-partial-content-with-go) – icza Nov 29 '17 at 19:39

1 Answers1

4

This different behavior is directly addressed on the net/http package, on the documentation for ServeContent (emphasis mine):

ServeContent replies to the request using the content in the provided ReadSeeker. The main benefit of ServeContent over io.Copy is that it handles Range requests properly, sets the MIME type, and handles If-Match, If-Unmodified-Since, If-None-Match, If-Modified-Since, and If-Range requests.

If you check the net/http code, you'll see that ServeFile calls serveContent (through serveFile), which is the same unexported function called by ServeContent.

I've not digged into the reason for the different behaviors, but the documentation on the package makes quite clear why your io.Copy strategy is not working, while the http.ServeFile does.

Jofre
  • 3,718
  • 1
  • 23
  • 31
  • BTW, as @icza said in the comment to the original question, the reason for this different behavior (that I had not digged in), is clearly explained in [this other SO answer](https://stackoverflow.com/questions/36540610/how-to-serve-http-partial-content-with-go). – Jofre Jun 14 '18 at 19:56