aboutsummaryrefslogtreecommitdiff
path: root/send_over_http.go
diff options
context:
space:
mode:
Diffstat (limited to 'send_over_http.go')
-rw-r--r--send_over_http.go122
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
+}