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 }