/
exec.go
113 lines (94 loc) · 2.11 KB
/
exec.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
package exec
import (
"context"
"io"
"os"
"os/exec"
"path/filepath"
"strings"
"github.com/micro/micro/v3/service/errors"
"github.com/micro/micro/v3/service/proxy"
"github.com/micro/micro/v3/service/server"
)
type Proxy struct {
options proxy.Options
// The file or directory to read from
Endpoint string
}
func filePath(eps ...string) string {
p := filepath.Join(eps...)
return strings.Replace(p, "../", "", -1)
}
func getEndpoint(hdr map[string]string) string {
ep := hdr["Micro-Endpoint"]
if len(ep) > 0 && ep[0] == '/' {
return ep
}
return ""
}
func (p *Proxy) ProcessMessage(ctx context.Context, msg server.Message) error {
return nil
}
// ServeRequest honours the server.Router interface
func (p *Proxy) ServeRequest(ctx context.Context, req server.Request, rsp server.Response) error {
if p.Endpoint == "" {
exe, err := os.Executable()
if err != nil {
return err
}
// set the endpoint to the current path
p.Endpoint = filepath.Dir(exe)
}
for {
// get data
_, err := req.Read()
if err == io.EOF {
return nil
}
if err != nil {
return err
}
// get the header
hdr := req.Header()
// get endpoint
endpoint := getEndpoint(hdr)
// filepath
file := filePath(p.Endpoint, endpoint)
// exec the script or command
// TODO: add args
cmd := exec.Command(file)
out, err := cmd.CombinedOutput()
if err != nil {
return errors.InternalServerError(req.Service(), err.Error())
}
// write back the header
rsp.WriteHeader(hdr)
// write the body
err = rsp.Write(out)
if err == io.EOF {
return nil
}
if err != nil {
return errors.InternalServerError(req.Service(), err.Error())
}
}
}
func (p *Proxy) String() string {
return "exec"
}
//NewSingleHostProxy returns a router which sends requests to a single file
func NewSingleHostProxy(url string) proxy.Proxy {
return &Proxy{
Endpoint: url,
}
}
// NewProxy returns a new proxy which will execute a script, binary or anything
func NewProxy(opts ...proxy.Option) proxy.Proxy {
var options proxy.Options
for _, o := range opts {
o(&options)
}
p := new(Proxy)
p.Endpoint = options.Endpoint
return p
}