go-hep.org/x/hep@v0.38.1/groot/riofs/plugin/http/http.go (about) 1 // Copyright ©2019 The go-hep Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package http is a plugin for riofs.Open to support opening ROOT files over http(s). 6 package http 7 8 import ( 9 "io" 10 "net/http" 11 "os" 12 "runtime" 13 14 "go-hep.org/x/hep/groot/internal/httpio" 15 "go-hep.org/x/hep/groot/riofs" 16 ) 17 18 func init() { 19 riofs.Register("http", openFile) 20 riofs.Register("https", openFile) 21 } 22 23 func openFile(path string) (riofs.Reader, error) { 24 r, err := httpio.Open(path) 25 if err != nil { 26 // HTTP server may not support accept-range. 27 return tmpFileFrom(path) 28 } 29 rc, err := rcacheOf(&preader{r: r, n: runtime.NumCPU()}) 30 if err != nil { 31 _ = r.Close() 32 return tmpFileFrom(path) 33 } 34 return rc, nil 35 } 36 37 func tmpFileFrom(path string) (riofs.Reader, error) { 38 resp, err := http.Get(path) 39 if err != nil { 40 return nil, err 41 } 42 defer resp.Body.Close() 43 44 f, err := os.CreateTemp("", "riofs-remote-") 45 if err != nil { 46 return nil, err 47 } 48 _, err = io.CopyBuffer(f, resp.Body, make([]byte, 16*1024*1024)) 49 if err != nil { 50 f.Close() 51 return nil, err 52 } 53 _, err = f.Seek(0, 0) 54 if err != nil { 55 f.Close() 56 return nil, err 57 } 58 return &tmpFile{f}, nil 59 } 60 61 // tmpFile wraps a regular os.File to automatically remove it when closed. 62 type tmpFile struct { 63 *os.File 64 } 65 66 func (f *tmpFile) Close() error { 67 err1 := f.File.Close() 68 err2 := os.Remove(f.File.Name()) 69 if err1 != nil { 70 return err1 71 } 72 return err2 73 } 74 75 var ( 76 _ riofs.Reader = (*tmpFile)(nil) 77 _ riofs.Writer = (*tmpFile)(nil) 78 )