diff options
Diffstat (limited to 'send_over_http.go')
-rw-r--r-- | send_over_http.go | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/send_over_http.go b/send_over_http.go new file mode 100644 index 0000000..c34145b --- /dev/null +++ b/send_over_http.go @@ -0,0 +1,122 @@ +package sendoverhttp + +import ( + "fmt" + "io/fs" + "log" + "net" + "net/http" + "os" + "path/filepath" +) + +func preferredIP() (*net.IP, error) { + ips, err := net.InterfaceAddrs() + if err != nil { + return nil, err + } + for _, addr := range ips { + ipNet, ok := addr.(*net.IPNet) + if !ok { + continue + } + if ipNet.IP.IsLoopback() { + continue + } + return &ipNet.IP, nil + } + return nil, nil +} + +type Server struct { + filepath string + + closeCh chan struct{} + mr *MultiRunner +} + +type SingleFileDir string + +func (s SingleFileDir) Open(name string) (http.File, error) { + if name == "index.html" { + return nil, fs.ErrNotExist + } + + fp := string(s) + stat, err := os.Stat(fp) + if err != nil { + return nil, err + } + if stat.IsDir() { + return http.Dir(fp).Open(name) + } + + switch name { + case "/": + return nil, os.ErrNotExist + case "/" + filepath.Base(fp): + return os.Open(fp) + default: + return nil, os.ErrNotExist + + } +} + +func NewServer(fp string) *Server { + return &Server{ + closeCh: make(chan struct{}), + filepath: fp, + mr: NewMultiRunner(), + } +} + +func (s *Server) Start() error { + ip, err := preferredIP() + if err != nil { + return err + } + + prot := "http" + port := "8081" + + url := fmt.Sprintf("%s://%s:%s", prot, ip, port) + if stat, _ := os.Stat(s.filepath); !stat.IsDir() { + url += "/" + filepath.Base(s.filepath) + } + + qrCodeShower := NewTerminalQRShower(url) + go s.mr.Run(qrCodeShower) + + httpRunner := NewRunner() + httpSrv := &http.Server{ + Addr: ":" + port, + } + + var d http.FileSystem = http.Dir(s.filepath) + if stat, _ := os.Stat(s.filepath); !stat.IsDir() { + // Show user the name of the file + d = SingleFileDir(s.filepath) + } + httpSrv.Handler = http.FileServer(d) + + httpRunner.OnStart = func() error { + l, err := net.Listen("tcp4", ip.String()+":"+port) + if err != nil { + log.Fatal(err) + } + return httpSrv.Serve(l) + } + httpRunner.OnStop = func() { + _ = httpSrv.Close() + } + go s.mr.Run(httpRunner) + + <-s.closeCh + close(s.closeCh) + return nil +} + +func (s *Server) Stop() { + s.mr.Stop() + return +} |