fix streaming
This commit is contained in:
@@ -15,16 +15,14 @@ import (
|
|||||||
var sharedClient = &http.Client{
|
var sharedClient = &http.Client{
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
MaxIdleConns: 200,
|
MaxIdleConns: 100,
|
||||||
MaxIdleConnsPerHost: 50,
|
MaxIdleConnsPerHost: 20,
|
||||||
MaxConnsPerHost: 100,
|
MaxConnsPerHost: 50,
|
||||||
IdleConnTimeout: 300 * time.Second,
|
IdleConnTimeout: 90 * time.Second,
|
||||||
TLSHandshakeTimeout: 15 * time.Second,
|
TLSHandshakeTimeout: 10 * time.Second,
|
||||||
ResponseHeaderTimeout: 60 * time.Second,
|
ResponseHeaderTimeout: 30 * time.Second,
|
||||||
ExpectContinueTimeout: 2 * time.Second,
|
ExpectContinueTimeout: 1 * time.Second,
|
||||||
DisableKeepAlives: false,
|
DisableKeepAlives: false,
|
||||||
WriteBufferSize: 64 * 1024,
|
|
||||||
ReadBufferSize: 64 * 1024,
|
|
||||||
},
|
},
|
||||||
Timeout: 0,
|
Timeout: 0,
|
||||||
}
|
}
|
||||||
@@ -313,11 +311,6 @@ func (f *File) handleRangeRequest(upstreamReq *http.Request, r *http.Request, w
|
|||||||
start, end := ranges[0].start, ranges[0].end
|
start, end := ranges[0].start, ranges[0].end
|
||||||
|
|
||||||
if byteRange != nil {
|
if byteRange != nil {
|
||||||
// Add bounds checking to prevent overflow
|
|
||||||
if start > f.size-byteRange[0] || end > f.size-byteRange[0] {
|
|
||||||
w.Header().Set("Content-Range", fmt.Sprintf("bytes */%d", f.size))
|
|
||||||
return -1 // Invalid range after offset
|
|
||||||
}
|
|
||||||
start += byteRange[0]
|
start += byteRange[0]
|
||||||
end += byteRange[0]
|
end += byteRange[0]
|
||||||
}
|
}
|
||||||
@@ -328,11 +321,9 @@ func (f *File) handleRangeRequest(upstreamReq *http.Request, r *http.Request, w
|
|||||||
|
|
||||||
func (f *File) streamVideoOptimized(w http.ResponseWriter, src io.Reader) error {
|
func (f *File) streamVideoOptimized(w http.ResponseWriter, src io.Reader) error {
|
||||||
// Use larger buffer for video streaming (better throughput)
|
// Use larger buffer for video streaming (better throughput)
|
||||||
buf := make([]byte, 256*1024) // 256KB buffer for better performance
|
buf := make([]byte, 64*1024) // 64KB buffer
|
||||||
flushInterval := 8 * 1024 // Flush every 8KB for responsive streaming
|
|
||||||
var totalWritten int
|
|
||||||
|
|
||||||
// Preread first chunk for immediate response
|
// First chunk optimization - send immediately for faster start
|
||||||
n, err := src.Read(buf)
|
n, err := src.Read(buf)
|
||||||
if err != nil && err != io.EOF {
|
if err != nil && err != io.EOF {
|
||||||
if isClientDisconnection(err) {
|
if isClientDisconnection(err) {
|
||||||
@@ -350,7 +341,6 @@ func (f *File) streamVideoOptimized(w http.ResponseWriter, src io.Reader) error
|
|||||||
}
|
}
|
||||||
return &streamError{Err: writeErr, StatusCode: 0}
|
return &streamError{Err: writeErr, StatusCode: 0}
|
||||||
}
|
}
|
||||||
totalWritten += n
|
|
||||||
|
|
||||||
// Flush immediately for faster video start
|
// Flush immediately for faster video start
|
||||||
if flusher, ok := w.(http.Flusher); ok {
|
if flusher, ok := w.(http.Flusher); ok {
|
||||||
@@ -362,41 +352,16 @@ func (f *File) streamVideoOptimized(w http.ResponseWriter, src io.Reader) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stream remaining data with periodic flushing
|
// Continue with optimized copy for remaining data
|
||||||
for {
|
_, err = io.CopyBuffer(w, src, buf)
|
||||||
n, err := src.Read(buf)
|
|
||||||
if n > 0 {
|
|
||||||
_, writeErr := w.Write(buf[:n])
|
|
||||||
if writeErr != nil {
|
|
||||||
if isClientDisconnection(writeErr) {
|
|
||||||
return &streamError{Err: writeErr, StatusCode: 0, IsClientDisconnection: true}
|
|
||||||
}
|
|
||||||
return &streamError{Err: writeErr, StatusCode: 0}
|
|
||||||
}
|
|
||||||
totalWritten += n
|
|
||||||
|
|
||||||
// Flush periodically to maintain streaming performance
|
|
||||||
if totalWritten%flushInterval == 0 {
|
|
||||||
if flusher, ok := w.(http.Flusher); ok {
|
|
||||||
flusher.Flush()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == io.EOF {
|
|
||||||
// Final flush
|
|
||||||
if flusher, ok := w.(http.Flusher); ok {
|
|
||||||
flusher.Flush()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if isClientDisconnection(err) {
|
if isClientDisconnection(err) {
|
||||||
return &streamError{Err: err, StatusCode: 0, IsClientDisconnection: true}
|
return &streamError{Err: err, StatusCode: 0, IsClientDisconnection: true}
|
||||||
}
|
}
|
||||||
return &streamError{Err: err, StatusCode: 0}
|
return &streamError{Err: err, StatusCode: 0}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Reference in New Issue
Block a user