github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/cmd/service/handler/exec/exec.go (about) 1 package exec 2 3 import ( 4 "context" 5 "io" 6 "os" 7 "os/exec" 8 "path/filepath" 9 "strings" 10 11 "github.com/tickoalcantara12/micro/v3/service/errors" 12 "github.com/tickoalcantara12/micro/v3/service/proxy" 13 "github.com/tickoalcantara12/micro/v3/service/server" 14 ) 15 16 type Proxy struct { 17 options proxy.Options 18 19 // The file or directory to read from 20 Endpoint string 21 } 22 23 func filePath(eps ...string) string { 24 p := filepath.Join(eps...) 25 return strings.Replace(p, "../", "", -1) 26 } 27 28 func getEndpoint(hdr map[string]string) string { 29 ep := hdr["Micro-Endpoint"] 30 if len(ep) > 0 && ep[0] == '/' { 31 return ep 32 } 33 return "" 34 } 35 36 func (p *Proxy) ProcessMessage(ctx context.Context, msg server.Message) error { 37 return nil 38 } 39 40 // ServeRequest honours the server.Router interface 41 func (p *Proxy) ServeRequest(ctx context.Context, req server.Request, rsp server.Response) error { 42 if p.Endpoint == "" { 43 exe, err := os.Executable() 44 if err != nil { 45 return err 46 } 47 // set the endpoint to the current path 48 p.Endpoint = filepath.Dir(exe) 49 } 50 51 for { 52 // get data 53 _, err := req.Read() 54 if err == io.EOF { 55 return nil 56 } 57 if err != nil { 58 return err 59 } 60 61 // get the header 62 hdr := req.Header() 63 64 // get endpoint 65 endpoint := getEndpoint(hdr) 66 67 // filepath 68 file := filePath(p.Endpoint, endpoint) 69 70 // exec the script or command 71 // TODO: add args 72 cmd := exec.Command(file) 73 out, err := cmd.CombinedOutput() 74 if err != nil { 75 return errors.InternalServerError(req.Service(), err.Error()) 76 } 77 78 // write back the header 79 rsp.WriteHeader(hdr) 80 // write the body 81 err = rsp.Write(out) 82 if err == io.EOF { 83 return nil 84 } 85 if err != nil { 86 return errors.InternalServerError(req.Service(), err.Error()) 87 } 88 } 89 90 } 91 92 func (p *Proxy) String() string { 93 return "exec" 94 } 95 96 //NewSingleHostProxy returns a router which sends requests to a single file 97 func NewSingleHostProxy(url string) proxy.Proxy { 98 return &Proxy{ 99 Endpoint: url, 100 } 101 } 102 103 // NewProxy returns a new proxy which will execute a script, binary or anything 104 func NewProxy(opts ...proxy.Option) proxy.Proxy { 105 var options proxy.Options 106 for _, o := range opts { 107 o(&options) 108 } 109 p := new(Proxy) 110 p.Endpoint = options.Endpoint 111 112 return p 113 }