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  }