Clash.Meta/component/resource/vehicle.go

118 lines
2.4 KiB
Go
Raw Normal View History

package resource
2019-12-08 12:17:24 +08:00
import (
"context"
2023-07-16 11:10:07 +08:00
"errors"
2021-10-09 20:35:06 +08:00
"io"
2019-12-08 12:17:24 +08:00
"net/http"
2021-10-09 20:35:06 +08:00
"os"
2019-12-08 12:17:24 +08:00
"time"
2023-07-16 11:10:07 +08:00
2023-11-03 21:01:45 +08:00
mihomoHttp "github.com/metacubex/mihomo/component/http"
2024-09-22 11:36:31 +08:00
"github.com/metacubex/mihomo/component/profile/cachefile"
2023-11-03 21:01:45 +08:00
types "github.com/metacubex/mihomo/constant/provider"
2019-12-08 12:17:24 +08:00
)
type FileVehicle struct {
path string
}
func (f *FileVehicle) Type() types.VehicleType {
return types.File
2019-12-08 12:17:24 +08:00
}
func (f *FileVehicle) Path() string {
return f.path
}
func (f *FileVehicle) Url() string {
return "file://" + f.path
}
2024-09-22 11:36:31 +08:00
func (f *FileVehicle) Read(ctx context.Context, oldHash types.HashType) (buf []byte, hash types.HashType, err error) {
buf, err = os.ReadFile(f.path)
if err != nil {
return
}
hash = types.MakeHash(buf)
return
2019-12-08 12:17:24 +08:00
}
func (f *FileVehicle) Proxy() string {
return ""
}
2019-12-08 12:17:24 +08:00
func NewFileVehicle(path string) *FileVehicle {
return &FileVehicle{path: path}
}
type HTTPVehicle struct {
url string
path string
proxy string
header http.Header
2019-12-08 12:17:24 +08:00
}
2022-11-05 02:24:08 +08:00
func (h *HTTPVehicle) Url() string {
return h.url
}
func (h *HTTPVehicle) Type() types.VehicleType {
return types.HTTP
2019-12-08 12:17:24 +08:00
}
func (h *HTTPVehicle) Path() string {
return h.path
}
func (h *HTTPVehicle) Proxy() string {
return h.proxy
}
2024-09-22 11:36:31 +08:00
func (h *HTTPVehicle) Read(ctx context.Context, oldHash types.HashType) (buf []byte, hash types.HashType, err error) {
2024-08-27 11:04:42 +08:00
ctx, cancel := context.WithTimeout(ctx, time.Second*20)
2019-12-08 12:17:24 +08:00
defer cancel()
2024-09-22 11:36:31 +08:00
header := h.header
setIfNoneMatch := false
if oldHash.IsValid() {
hashBytes, etag := cachefile.Cache().GetETagWithHash(h.url)
if oldHash.EqualBytes(hashBytes) && etag != "" {
if header == nil {
header = http.Header{}
} else {
header = header.Clone()
}
header.Set("If-None-Match", etag)
setIfNoneMatch = true
}
}
resp, err := mihomoHttp.HttpRequestWithProxy(ctx, h.url, http.MethodGet, header, nil, h.proxy)
if err != nil {
2024-09-22 11:36:31 +08:00
return
}
defer resp.Body.Close()
2023-07-16 11:43:18 +08:00
if resp.StatusCode < 200 || resp.StatusCode > 299 {
2024-09-22 11:36:31 +08:00
if setIfNoneMatch && resp.StatusCode == http.StatusNotModified {
return nil, oldHash, nil
}
err = errors.New(resp.Status)
return
2023-07-16 11:10:07 +08:00
}
2024-09-22 11:36:31 +08:00
buf, err = io.ReadAll(resp.Body)
2019-12-08 12:17:24 +08:00
if err != nil {
2024-09-22 11:36:31 +08:00
return
2019-12-08 12:17:24 +08:00
}
2024-09-22 11:36:31 +08:00
hash = types.MakeHash(buf)
cachefile.Cache().SetETagWithHash(h.url, hash.Bytes(), resp.Header.Get("ETag"))
return
2019-12-08 12:17:24 +08:00
}
func NewHTTPVehicle(url string, path string, proxy string, header http.Header) *HTTPVehicle {
2024-09-22 11:36:31 +08:00
return &HTTPVehicle{
url: url,
path: path,
proxy: proxy,
header: header,
}
2019-12-08 12:17:24 +08:00
}