This repository has been archived by the owner on Oct 21, 2020. It is now read-only.
/
server.go
114 lines (105 loc) · 2.29 KB
/
server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package server
import (
"flag"
"fmt"
"io/ioutil"
"log"
"net"
"net/http"
"net/http/httputil"
"net/url"
"os"
"path/filepath"
"runtime"
"strings"
"github.com/nobonobo/wecty/cmd/wecty/commands"
)
// ProxyURL ...
type ProxyURL struct {
m map[string]*url.URL
}
func (p ProxyURL) String() string {
res := []string{}
for k, v := range p.m {
res = append(res, strings.Join([]string{k, v.String()}, "="))
}
return fmt.Sprint(res)
}
// Set ...
func (p *ProxyURL) Set(s string) error {
params := strings.SplitN(s, "=", 2)
if len(params) < 2 || len(params[0]) == 0 || params[0] == "/" {
return fmt.Errorf("path must not be empty or root(/)")
}
u, err := url.Parse(params[1])
if err != nil {
return err
}
p.m[params[0]] = u
return nil
}
// Server ...
type Server struct {
*flag.FlagSet
urls ProxyURL
addr string
isTinyGo bool
}
// Usage ...
func (s *Server) Usage() {
s.FlagSet.Usage()
}
// Execute ...
func (s *Server) Execute(args []string) error {
if err := s.FlagSet.Parse(args); err != nil {
return err
}
log.Println("listen and serve:", s.addr)
for p, u := range s.urls.m {
log.Printf("proxy: %q => %q", p, u.String())
http.Handle(p,
http.StripPrefix(strings.TrimRight(p, "/"),
httputil.NewSingleHostReverseProxy(u),
),
)
}
tempDir, err := ioutil.TempDir("", "gobuild")
if err != nil {
return err
}
defer os.RemoveAll(tempDir)
l, err := net.Listen("tcp", ":8080")
if err != nil {
return err
}
d, err := os.Getwd()
if err != nil {
return err
}
dh := &DevHandler{
goCmd: "go",
wasmExecPath: filepath.Join(runtime.GOROOT(), "misc", "wasm", "wasm_exec.js"),
workDir: d,
tempDir: tempDir,
}
if s.isTinyGo {
dh.goCmd = "tinygo"
output, err := commands.RunCmd(d, nil, "tinygo", "env", "TINYGOROOT")
if err != nil {
return err
}
dh.wasmExecPath = filepath.Join(strings.TrimSpace(output), "targets", "wasm_exec.js")
}
http.Handle("/", dh)
return http.Serve(l, nil)
}
func init() {
s := &Server{
FlagSet: flag.NewFlagSet("server", flag.ContinueOnError),
urls: ProxyURL{m: map[string]*url.URL{}},
}
s.FlagSet.StringVar(&s.addr, "addr", ":8080", "listen address")
s.FlagSet.BoolVar(&s.isTinyGo, "tinygo", false, "use tinygo tool chain")
s.FlagSet.Var(&s.urls, "p", `proxy url(value="path=URL")`)
commands.Register(s)
}