initializing webdav server
This commit is contained in:
@@ -2,60 +2,101 @@ package webdav
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/sirrobot01/debrid-blackhole/pkg/debrid/cache"
|
||||
"github.com/sirrobot01/debrid-blackhole/pkg/debrid/torrent"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
var sharedClient = &http.Client{
|
||||
Transport: &http.Transport{
|
||||
// These settings help maintain persistent connections.
|
||||
MaxIdleConns: 100,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
DisableCompression: false,
|
||||
DisableKeepAlives: false,
|
||||
},
|
||||
Timeout: 0,
|
||||
}
|
||||
|
||||
type File struct {
|
||||
cache *cache.Cache
|
||||
cachedTorrent *cache.CachedTorrent
|
||||
file *torrent.File
|
||||
offset int64
|
||||
isDir bool
|
||||
children []os.FileInfo
|
||||
reader io.ReadCloser
|
||||
cache *Cache
|
||||
fileId string
|
||||
torrentId string
|
||||
|
||||
size int64
|
||||
offset int64
|
||||
isDir bool
|
||||
children []os.FileInfo
|
||||
reader io.ReadCloser
|
||||
seekPending bool
|
||||
content []byte
|
||||
name string
|
||||
|
||||
downloadLink string
|
||||
link string
|
||||
}
|
||||
|
||||
// File interface implementations for File
|
||||
|
||||
func (f *File) Close() error {
|
||||
if f.reader != nil {
|
||||
f.reader.Close()
|
||||
f.reader = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *File) GetDownloadLink() string {
|
||||
file := f.file
|
||||
link, err := f.cache.GetFileDownloadLink(f.cachedTorrent, file)
|
||||
if err != nil {
|
||||
return ""
|
||||
// Check if we already have a final URL cached
|
||||
if f.downloadLink != "" {
|
||||
return f.downloadLink
|
||||
}
|
||||
return link
|
||||
downloadLink := f.cache.GetDownloadLink(f.torrentId, f.name, f.link)
|
||||
if downloadLink != "" {
|
||||
f.downloadLink = downloadLink
|
||||
return downloadLink
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func (f *File) Read(p []byte) (n int, err error) {
|
||||
// Directories cannot be read as a byte stream.
|
||||
if f.isDir {
|
||||
return 0, os.ErrInvalid
|
||||
}
|
||||
|
||||
// If we haven't started streaming the file yet, open the HTTP connection.
|
||||
if f.reader == nil {
|
||||
// Create an HTTP GET request to the file's URL.
|
||||
// If file content is preloaded, read from memory.
|
||||
if f.content != nil {
|
||||
if f.offset >= int64(len(f.content)) {
|
||||
return 0, io.EOF
|
||||
}
|
||||
n = copy(p, f.content[f.offset:])
|
||||
f.offset += int64(n)
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// If we haven't started streaming or a seek was requested,
|
||||
// close the existing stream and start a new HTTP GET request.
|
||||
if f.reader == nil || f.seekPending {
|
||||
if f.reader != nil && f.seekPending {
|
||||
f.reader.Close()
|
||||
f.reader = nil
|
||||
}
|
||||
|
||||
// Create a new HTTP GET request for the file's URL.
|
||||
req, err := http.NewRequest("GET", f.GetDownloadLink(), nil)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to create HTTP request: %w", err)
|
||||
}
|
||||
|
||||
// If we've already read some data (f.offset > 0), request only the remaining bytes.
|
||||
// If we've already read some data, request only the remaining bytes.
|
||||
if f.offset > 0 {
|
||||
req.Header.Set("Range", fmt.Sprintf("bytes=%d-", f.offset))
|
||||
}
|
||||
|
||||
// Execute the HTTP request.
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
resp, err := sharedClient.Do(req)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("HTTP request error: %w", err)
|
||||
}
|
||||
@@ -68,6 +109,8 @@ func (f *File) Read(p []byte) (n int, err error) {
|
||||
|
||||
// Store the response body as our reader.
|
||||
f.reader = resp.Body
|
||||
// Reset the seek pending flag now that we've reinitialized the reader.
|
||||
f.seekPending = false
|
||||
}
|
||||
|
||||
// Read data from the HTTP stream.
|
||||
@@ -88,27 +131,57 @@ func (f *File) Seek(offset int64, whence int) (int64, error) {
|
||||
return 0, os.ErrInvalid
|
||||
}
|
||||
|
||||
var newOffset int64
|
||||
switch whence {
|
||||
case io.SeekStart:
|
||||
f.offset = offset
|
||||
newOffset = offset
|
||||
case io.SeekCurrent:
|
||||
f.offset += offset
|
||||
newOffset = f.offset + offset
|
||||
case io.SeekEnd:
|
||||
f.offset = f.file.Size - offset
|
||||
newOffset = f.size - offset
|
||||
default:
|
||||
return 0, os.ErrInvalid
|
||||
}
|
||||
|
||||
if f.offset < 0 {
|
||||
f.offset = 0
|
||||
if newOffset < 0 {
|
||||
newOffset = 0
|
||||
}
|
||||
if f.offset > f.file.Size {
|
||||
f.offset = f.file.Size
|
||||
if newOffset > f.size {
|
||||
newOffset = f.size
|
||||
}
|
||||
|
||||
// If we're seeking to a new position, mark the reader for reset.
|
||||
if newOffset != f.offset {
|
||||
f.offset = newOffset
|
||||
f.seekPending = true
|
||||
}
|
||||
return f.offset, nil
|
||||
}
|
||||
|
||||
func (f *File) Stat() (os.FileInfo, error) {
|
||||
if f.isDir {
|
||||
return &FileInfo{
|
||||
name: f.name,
|
||||
size: 0,
|
||||
mode: 0755 | os.ModeDir,
|
||||
modTime: time.Now(),
|
||||
isDir: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &FileInfo{
|
||||
name: f.name,
|
||||
size: f.size,
|
||||
mode: 0644,
|
||||
modTime: time.Now(),
|
||||
isDir: false,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (f *File) Write(p []byte) (n int, err error) {
|
||||
return 0, os.ErrPermission
|
||||
}
|
||||
|
||||
func (f *File) Readdir(count int) ([]os.FileInfo, error) {
|
||||
if !f.isDir {
|
||||
return nil, os.ErrInvalid
|
||||
@@ -130,31 +203,3 @@ func (f *File) Readdir(count int) ([]os.FileInfo, error) {
|
||||
f.children = f.children[count:]
|
||||
return files, nil
|
||||
}
|
||||
|
||||
func (f *File) Stat() (os.FileInfo, error) {
|
||||
if f.isDir {
|
||||
name := "/"
|
||||
if f.cachedTorrent != nil {
|
||||
name = f.cachedTorrent.Name
|
||||
}
|
||||
return &FileInfo{
|
||||
name: name,
|
||||
size: 0,
|
||||
mode: 0755 | os.ModeDir,
|
||||
modTime: time.Now(),
|
||||
isDir: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &FileInfo{
|
||||
name: f.file.Name,
|
||||
size: f.file.Size,
|
||||
mode: 0644,
|
||||
modTime: time.Now(),
|
||||
isDir: false,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (f *File) Write(p []byte) (n int, err error) {
|
||||
return 0, os.ErrPermission
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user