github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/integration/nwo/buildserver.go (about)

     1  /*
     2  Copyright hechain All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package nwo
     8  
     9  import (
    10  	"context"
    11  	"fmt"
    12  	"net"
    13  	"net/http"
    14  	"strings"
    15  	"sync"
    16  	"time"
    17  
    18  	. "github.com/onsi/gomega"
    19  	"github.com/onsi/gomega/gexec"
    20  )
    21  
    22  type BuildServer struct {
    23  	server *http.Server
    24  	lis    net.Listener
    25  }
    26  
    27  func NewBuildServer(args ...string) *BuildServer {
    28  	return &BuildServer{
    29  		server: &http.Server{
    30  			Handler: &buildHandler{args: args},
    31  		},
    32  	}
    33  }
    34  
    35  func (s *BuildServer) Serve() {
    36  	lis, err := net.Listen("tcp", "127.0.0.1:0")
    37  	Expect(err).NotTo(HaveOccurred())
    38  
    39  	s.lis = lis
    40  	go s.server.Serve(lis)
    41  }
    42  
    43  func (s *BuildServer) Shutdown() {
    44  	ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
    45  	defer cancel()
    46  	defer gexec.CleanupBuildArtifacts()
    47  
    48  	s.server.Shutdown(ctx)
    49  }
    50  
    51  func (s *BuildServer) Components() *Components {
    52  	Expect(s.lis).NotTo(BeNil())
    53  	return &Components{
    54  		ServerAddress: s.lis.Addr().String(),
    55  	}
    56  }
    57  
    58  type artifact struct {
    59  	mutex  sync.Mutex
    60  	input  string
    61  	output string
    62  }
    63  
    64  func (a *artifact) build(args ...string) error {
    65  	a.mutex.Lock()
    66  	defer a.mutex.Unlock()
    67  
    68  	if a.output != "" {
    69  		return nil
    70  	}
    71  
    72  	output, err := gexec.Build(a.input, args...)
    73  	if err != nil {
    74  		return err
    75  	}
    76  
    77  	a.output = output
    78  	return nil
    79  }
    80  
    81  type buildHandler struct {
    82  	mutex     sync.Mutex
    83  	artifacts map[string]*artifact
    84  	args      []string
    85  }
    86  
    87  func (b *buildHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    88  	if req.Method != http.MethodGet {
    89  		w.WriteHeader(http.StatusBadRequest)
    90  		return
    91  	}
    92  
    93  	input := strings.TrimPrefix(req.URL.Path, "/")
    94  	a := b.artifact(input)
    95  
    96  	if err := a.build(b.args...); err != nil {
    97  		w.WriteHeader(http.StatusInternalServerError)
    98  		fmt.Fprintf(w, "%s", err)
    99  		return
   100  	}
   101  
   102  	w.WriteHeader(http.StatusOK)
   103  	fmt.Fprintf(w, "%s", a.output)
   104  }
   105  
   106  func (b *buildHandler) artifact(input string) *artifact {
   107  	b.mutex.Lock()
   108  	defer b.mutex.Unlock()
   109  
   110  	if b.artifacts == nil {
   111  		b.artifacts = map[string]*artifact{}
   112  	}
   113  
   114  	a, ok := b.artifacts[input]
   115  	if !ok {
   116  		a = &artifact{input: input}
   117  		b.artifacts[input] = a
   118  	}
   119  
   120  	return a
   121  }