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  )