github.com/pdmccormick/importable-docker-buildx@v0.0.0-20240426161518-e47091289030/util/gitutil/testutilserve.go (about)

     1  package gitutil
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net"
     7  	"net/http"
     8  	"testing"
     9  
    10  	"github.com/stretchr/testify/require"
    11  )
    12  
    13  type gitServe struct {
    14  	token string
    15  }
    16  
    17  type GitServeOpt func(*gitServe)
    18  
    19  func WithAccessToken(token string) GitServeOpt {
    20  	return func(s *gitServe) {
    21  		s.token = token
    22  	}
    23  }
    24  
    25  func GitServeHTTP(c *Git, t testing.TB, opts ...GitServeOpt) (url string) {
    26  	t.Helper()
    27  	gitUpdateServerInfo(c, t)
    28  	ctx, cancel := context.WithCancel(context.TODO())
    29  
    30  	gs := &gitServe{}
    31  	for _, opt := range opts {
    32  		opt(gs)
    33  	}
    34  
    35  	ready := make(chan struct{})
    36  	done := make(chan struct{})
    37  
    38  	name := "test.git"
    39  	dir, err := c.GitDir()
    40  	if err != nil {
    41  		cancel()
    42  	}
    43  
    44  	var addr string
    45  	go func() {
    46  		mux := http.NewServeMux()
    47  		prefix := fmt.Sprintf("/%s/", name)
    48  
    49  		handler := func(next http.Handler) http.Handler {
    50  			var tokenChecked bool
    51  			return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    52  				if gs.token != "" && !tokenChecked {
    53  					t.Logf("git access token to check: %q", gs.token)
    54  					user, pass, _ := r.BasicAuth()
    55  					t.Logf("basic auth: user=%q pass=%q", user, pass)
    56  					if pass != gs.token {
    57  						http.Error(w, "Unauthorized", http.StatusUnauthorized)
    58  						return
    59  					}
    60  					tokenChecked = true
    61  				}
    62  				next.ServeHTTP(w, r)
    63  			})
    64  		}
    65  
    66  		mux.Handle(prefix, handler(http.StripPrefix(prefix, http.FileServer(http.Dir(dir)))))
    67  		l, err := net.Listen("tcp", "localhost:0")
    68  		if err != nil {
    69  			panic(err)
    70  		}
    71  
    72  		addr = l.Addr().String()
    73  
    74  		close(ready)
    75  
    76  		s := http.Server{Handler: mux} //nolint:gosec // potential attacks are not relevant for tests
    77  		go s.Serve(l)
    78  		<-ctx.Done()
    79  		s.Shutdown(context.TODO())
    80  		l.Close()
    81  
    82  		close(done)
    83  	}()
    84  	<-ready
    85  
    86  	t.Cleanup(func() {
    87  		cancel()
    88  		<-done
    89  	})
    90  	return fmt.Sprintf("http://%s/%s", addr, name)
    91  }
    92  
    93  func gitUpdateServerInfo(c *Git, tb testing.TB) {
    94  	tb.Helper()
    95  	_, err := fakeGit(c, "update-server-info")
    96  	require.NoError(tb, err)
    97  }