package handler import ( "errors" "fmt" "net/http" "os" "strconv" "strings" ) func StreamVideoHandler(w http.ResponseWriter, r *http.Request) { videoPath := r.URL.Query().Get("v") videoFile, err := os.Open(videoPath) if err != nil { http.Error(w, "Video file not found.", http.StatusNotFound) return } defer videoFile.Close() fileInfo, err := videoFile.Stat() if err != nil { http.Error(w, "Could not obtain file info.", http.StatusInternalServerError) return } fileSize := fileInfo.Size() rangeHeader := r.Header.Get("Range") if rangeHeader == "" { http.ServeFile(w, r, videoPath) return } start, end, err := getStartEndRange(rangeHeader, fileSize) if err != nil || start > end || end >= fileSize { http.Error(w, "Invalid range.", http.StatusBadRequest) return } w.Header().Set("Content-Type", "video/mp4") w.Header().Set("Content-Range", fmt.Sprintf("bytes %d-%d/%d", start, end, fileSize)) w.Header().Set("Accept-Ranges", "bytes") w.WriteHeader(http.StatusPartialContent) videoFile.Seek(start, 0) buf := make([]byte, end-start+1) videoFile.Read(buf) w.Write(buf) } func getStartEndRange(rangeHeader string, fileSize int64) (int64, int64, error) { rangeParts := strings.Split(rangeHeader, "=") if len(rangeParts) != 2 || rangeParts[0] != "bytes" { return 0, 0, errors.New("invalid range header") } rangeSpec := strings.Split(rangeParts[1], "-") start, err := strconv.ParseInt(rangeSpec[0], 10, 64) if err != nil { return 0, 0, errors.New("invalid range start") } var end int64 if len(rangeSpec) == 2 && rangeSpec[1] != "" { end, err = strconv.ParseInt(rangeSpec[1], 10, 64) if err != nil { return 0, 0, errors.New("invalid range end") } } else { end = fileSize - 1 } return start, end, nil }