func CreateTestingTransport() *http.Transport {
	dialer := net.Dialer{
		Timeout:   5 * time.Second,
		KeepAlive: 5 * time.Second,
		DualStack: true,
	}
	dialContext := func(ctx context.Context, network, addr string) (net.Conn, error) {
		parts := strings.Split(addr, ":")
		destAddr := fmt.Sprintf("127.0.0.1:%s", parts[1])
		log.Printf("caddytest: redirecting the dialer from %s to %s", addr, destAddr)
		return dialer.DialContext(ctx, network, destAddr)
	}
	return &http.Transport{
		Proxy:                 http.ProxyFromEnvironment,
		DialContext:           dialContext,
		ForceAttemptHTTP2:     true,
		MaxIdleConns:          100,
		IdleConnTimeout:       90 * time.Second,
		TLSHandshakeTimeout:   5 * time.Second,
		ExpectContinueTimeout: 1 * time.Second,
		TLSClientConfig:       &tls.Config{InsecureSkipVerify: true},  
	}
}
CreateTestingTransport creates a testing transport that forces call dialing connections to happen locally
package caddytest
import (
	"bytes"
	"context"
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"log"
	"net"
	"net/http"
	"net/http/cookiejar"
	"os"
	"path"
	"reflect"
	"regexp"
	"runtime"
	"strings"
	"testing"
	"time"
	"github.com/aryann/difflib"
	"github.com/caddyserver/caddy/v2/caddyconfig"
	caddycmd "github.com/caddyserver/caddy/v2/cmd"
	_ "github.com/caddyserver/caddy/v2/modules/standard"
)
type Defaults struct {
	AdminPort int
	Certifcates []string
	TestRequestTimeout time.Duration
	LoadRequestTimeout time.Duration
}
var Default = Defaults{
	AdminPort:          2019,
	Certifcates:        []string{"/caddy.localhost.crt", "/caddy.localhost.key"},
	TestRequestTimeout: 5 * time.Second,
	LoadRequestTimeout: 5 * time.Second,
}
var (
	matchKey  = regexp.MustCompile(`(/[\w\d\.]+\.key)`)
	matchCert = regexp.MustCompile(`(/[\w\d\.]+\.crt)`)
)
type Tester struct {
	Client       *http.Client
	configLoaded bool
	t            *testing.T
}
func NewTester(t *testing.T) *Tester {
	jar, err := cookiejar.New(nil)
	if err != nil {
		t.Fatalf("failed to create cookiejar: %s", err)
	}
	return &Tester{
		Client: &http.Client{
			Transport: CreateTestingTransport(),
			Jar:       jar,
			Timeout:   Default.TestRequestTimeout,
		},
		configLoaded: false,
		t:            t,
	}
}
type configLoadError struct {
	Response string
}
func (e configLoadError) Error() string { return e.Response }
func timeElapsed(start time.Time, name string) {
	elapsed := time.Since(start)
	log.Printf("%s took %s", name, elapsed)
}
func (tc *Tester) InitServer(rawConfig string, configType string) {
	if err := tc.initServer(rawConfig, configType); err != nil {
		tc.t.Logf("failed to load config: %s", err)
		tc.t.Fail()
	}
	if err := tc.ensureConfigRunning(rawConfig, configType); err != nil {
		tc.t.Logf("failed ensurng config is running: %s", err)
		tc.t.Fail()
	}
}
func (tc *Tester) initServer(rawConfig string, configType string) error {
	if testing.Short() {
		tc.t.SkipNow()
		return nil
	}
	err := validateTestPrerequisites()
	if err != nil {
		tc.t.Skipf("skipping tests as failed integration prerequisites. %s", err)
		return nil
	}
	tc.t.Cleanup(func() {
		if tc.t.Failed() && tc.configLoaded {
			res, err := http.Get(fmt.Sprintf("http://localhost:%d/config/", Default.AdminPort))
			if err != nil {
				tc.t.Log("unable to read the current config")
				return
			}
			defer res.Body.Close()
			body, _ := io.ReadAll(res.Body)
			var out bytes.Buffer
			_ = json.Indent(&out, body, "", "  ")
			tc.t.Logf("----------- failed with config -----------\n%s", out.String())
		}
	})
	rawConfig = prependCaddyFilePath(rawConfig)
	client := &http.Client{
		Timeout: Default.LoadRequestTimeout,
	}
	start := time.Now()
	req, err := http.NewRequest("POST", fmt.Sprintf("http://localhost:%d/load", Default.AdminPort), strings.NewReader(rawConfig))
	if err != nil {
		tc.t.Errorf("failed to create request. %s", err)
		return err
	}
	if configType == "json" {
		req.Header.Add("Content-Type", "application/json")
	} else {
		req.Header.Add("Content-Type", "text/"+configType)
	}
	res, err := client.Do(req)
	if err != nil {
		tc.t.Errorf("unable to contact caddy server. %s", err)
		return err
	}
	timeElapsed(start, "caddytest: config load time")
	defer res.Body.Close()
	body, err := io.ReadAll(res.Body)
	if err != nil {
		tc.t.Errorf("unable to read response. %s", err)
		return err
	}
	if res.StatusCode != 200 {
		return configLoadError{Response: string(body)}
	}
	tc.configLoaded = true
	return nil
}
func (tc *Tester) ensureConfigRunning(rawConfig string, configType string) error {
	expectedBytes := []byte(prependCaddyFilePath(rawConfig))
	if configType != "json" {
		adapter := caddyconfig.GetAdapter(configType)
		if adapter == nil {
			return fmt.Errorf("adapter of config type is missing: %s", configType)
		}
		expectedBytes, _, _ = adapter.Adapt([]byte(rawConfig), nil)
	}
	var expected interface{}
	err := json.Unmarshal(expectedBytes, &expected)
	if err != nil {
		return err
	}
	client := &http.Client{
		Timeout: Default.LoadRequestTimeout,
	}
	fetchConfig := func(client *http.Client) interface{} {
		resp, err := client.Get(fmt.Sprintf("http://localhost:%d/config/", Default.AdminPort))
		if err != nil {
			return nil
		}
		defer resp.Body.Close()
		actualBytes, err := io.ReadAll(resp.Body)
		if err != nil {
			return nil
		}
		var actual interface{}
		err = json.Unmarshal(actualBytes, &actual)
		if err != nil {
			return nil
		}
		return actual
	}
	for retries := 4; retries > 0; retries-- {
		if reflect.DeepEqual(expected, fetchConfig(client)) {
			return nil
		}
		time.Sleep(10 * time.Millisecond)
	}
	tc.t.Errorf("POSTed configuration isn't active")
	return errors.New("EnsureConfigRunning: POSTed configuration isn't active")
}
func validateTestPrerequisites() error {
	for _, certName := range Default.Certifcates {
		if _, err := os.Stat(getIntegrationDir() + certName); os.IsNotExist(err) {
			return fmt.Errorf("caddy integration test certificates (%s) not found", certName)
		}
	}
	if isCaddyAdminRunning() != nil {
		os.Args = []string{"caddy", "run"}
		go func() {
			caddycmd.Main()
		}()
		for retries := 4; retries > 0 && isCaddyAdminRunning() != nil; retries-- {
			time.Sleep(10 * time.Millisecond)
		}
	}
	return isCaddyAdminRunning()
}
func isCaddyAdminRunning() error {
	client := &http.Client{
		Timeout: Default.LoadRequestTimeout,
	}
	resp, err := client.Get(fmt.Sprintf("http://localhost:%d/config/", Default.AdminPort))
	if err != nil {
		return fmt.Errorf("caddy integration test caddy server not running. Expected to be listening on localhost:%d", Default.AdminPort)
	}
	resp.Body.Close()
	return nil
}
func getIntegrationDir() string {
	_, filename, _, ok := runtime.Caller(1)
	if !ok {
		panic("unable to determine the current file path")
	}
	return path.Dir(filename)
}
func prependCaddyFilePath(rawConfig string) string {
	r := matchKey.ReplaceAllString(rawConfig, getIntegrationDir()+"$1")
	r = matchCert.ReplaceAllString(r, getIntegrationDir()+"$1")
	return r
}