-
Notifications
You must be signed in to change notification settings - Fork 1
Open
Description
Refer to the following to integrate into the project
Use "github.com/wzshiming/ioswmr"
type teeResponse struct {
fileInfo fs.FileInfo
swmr ioswmr.SWMR
tmp *os.File
}
func (t *teeResponse) ServeHTTP(w http.ResponseWriter, r *http.Request) {
name := path.Base(r.URL.Path)
http.ServeContent(w, r, name, t.fileInfo.ModTime(), t.swmr.NewReadSeeker(0, int(t.fileInfo.Size())))
}
func (t *teeResponse) Close() error {
err := t.swmr.Close()
if err != nil {
return err
}
err = t.tmp.Close()
if err != nil {
return err
}
os.Remove(t.tmp.Name())
return nil
}
func (m *MirrorHandler) cacheFileTee(ctx context.Context, sourceFile, cacheFile string) (*teeResponse, error) {
resp, info, err := httpGet(ctx, m.client(), sourceFile)
if err != nil {
return nil, err
}
defer resp.Close()
var body io.Reader = resp
contentLength := info.Size()
if contentLength == 0 {
return nil, ErrNotOK
}
if m.Logger != nil {
m.Logger.Println("Tee Cache", cacheFile, contentLength)
}
tmp, err := os.CreateTemp("", "mirror-tee-*")
if err != nil {
return nil, err
}
fw, err := m.RemoteCache.Writer(ctx, cacheFile)
if err != nil {
if m.Logger != nil {
m.Logger.Println("Cache writer error", cacheFile, contentLength, err)
}
return nil, err
}
swmr := ioswmr.NewSWMR(tmp)
go func() {
defer fw.Close()
w := io.MultiWriter(swmr, fw)
n, err := io.Copy(w, body)
if err != nil && !errors.Is(err, io.EOF) {
if m.Logger != nil {
m.Logger.Println("SWMR copy error", cacheFile, contentLength, err)
}
_ = fw.Cancel(context.Background())
return
}
if contentLength > 0 && n != contentLength {
err = fmt.Errorf("copied %d bytes, expected %d", n, contentLength)
if m.Logger != nil {
m.Logger.Println("Cache copy error", cacheFile, err)
}
_ = fw.Cancel(context.Background())
return
}
err = fw.Commit(context.Background())
if err != nil {
if m.Logger != nil {
m.Logger.Println("Cache Commit error", cacheFile, err)
}
return
}
}()
return &teeResponse{
fileInfo: info,
swmr: swmr,
tmp: tmp,
}, nil
}Reactions are currently unavailable