-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add a HTTP request collector as atest extension
- Loading branch information
1 parent
b0b9bf8
commit 3b4dea9
Showing
10 changed files
with
481 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,3 +3,4 @@ bin/ | |
coverage.out | ||
dist/ | ||
.vscode/launch.json | ||
sample.yaml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
package cmd | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"io" | ||
"net/http" | ||
"os" | ||
"os/signal" | ||
"strings" | ||
"syscall" | ||
|
||
"github.com/elazarl/goproxy" | ||
"github.com/linuxsuren/api-testing/extensions/collector/pkg" | ||
"github.com/linuxsuren/api-testing/extensions/collector/pkg/filter" | ||
atestpkg "github.com/linuxsuren/api-testing/pkg/testing" | ||
"github.com/spf13/cobra" | ||
"gopkg.in/yaml.v2" | ||
) | ||
|
||
type option struct { | ||
port int | ||
filterPath string | ||
output string | ||
} | ||
|
||
func NewRootCmd() (c *cobra.Command) { | ||
opt := &option{} | ||
c = &cobra.Command{ | ||
Use: "atest-collector", | ||
Short: "A collector for API testing, it will start a HTTP proxy server", | ||
RunE: opt.runE, | ||
} | ||
flags := c.Flags() | ||
flags.IntVarP(&opt.port, "port", "p", 8080, "The port for the proxy") | ||
flags.StringVarP(&opt.filterPath, "filter-path", "", "", "The path prefix for filtering") | ||
flags.StringVarP(&opt.output, "output", "o", "sample.yaml", "The output file") | ||
|
||
cobra.MarkFlagRequired(flags, "filter-path") | ||
return | ||
} | ||
|
||
func (o *option) runE(cmd *cobra.Command, args []string) (err error) { | ||
urlFilter := &filter.URLPathFilter{PathPrefix: o.filterPath} | ||
collects := pkg.NewCollects() | ||
|
||
proxy := goproxy.NewProxyHttpServer() | ||
proxy.Verbose = true | ||
proxy.OnRequest().DoFunc( | ||
func(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) { | ||
if urlFilter.Filter(r.URL) { | ||
collects.Add(r.Clone(context.TODO())) | ||
} | ||
return r, nil | ||
}) | ||
|
||
exporter := &sampleExporter{ | ||
testSuite: atestpkg.TestSuite{ | ||
Name: "sample", | ||
}, | ||
} | ||
collects.AddEvent(exporter.add) | ||
|
||
srv := &http.Server{ | ||
Addr: fmt.Sprintf(":%d", o.port), | ||
Handler: proxy, | ||
} | ||
|
||
sig := make(chan os.Signal, 1) | ||
signal.Notify(sig, os.Interrupt, syscall.SIGTERM) | ||
go func() { | ||
<-sig | ||
collects.Stop() | ||
srv.Shutdown(context.Background()) | ||
}() | ||
|
||
cmd.Println("Starting the proxy server with port", o.port) | ||
srv.ListenAndServe() | ||
var data string | ||
if data, err = exporter.export(); err == nil { | ||
err = os.WriteFile(o.output, []byte(data), 0644) | ||
} | ||
return | ||
} | ||
|
||
type sampleExporter struct { | ||
testSuite atestpkg.TestSuite | ||
} | ||
|
||
func (e *sampleExporter) add(r *http.Request) { | ||
body := r.Body | ||
data, _ := io.ReadAll(body) | ||
|
||
fmt.Println("receive", r.URL.Path) | ||
req := atestpkg.Request{ | ||
API: r.URL.String(), | ||
Method: r.Method, | ||
Header: map[string]string{}, | ||
Body: string(data), | ||
} | ||
|
||
testCase := atestpkg.TestCase{ | ||
Request: req, | ||
Expect: atestpkg.Response{ | ||
StatusCode: 200, | ||
}, | ||
} | ||
|
||
specs := strings.Split(r.URL.Path, "/") | ||
if len(specs) > 0 { | ||
testCase.Name = specs[len(specs)-1] | ||
} | ||
|
||
if val := r.Header.Get("Content-Type"); val != "" { | ||
req.Header["Content-Type"] = val | ||
} | ||
|
||
e.testSuite.Items = append(e.testSuite.Items, testCase) | ||
} | ||
|
||
var prefix = `#!api-testing | ||
# yaml-language-server: $schema=https://gitee.com/linuxsuren/api-testing/raw/master/sample/api-testing-schema.json | ||
` | ||
|
||
func (e *sampleExporter) export() (string, error) { | ||
marker := map[string]int{} | ||
|
||
for i, item := range e.testSuite.Items { | ||
if _, ok := marker[item.Name]; ok { | ||
marker[item.Name]++ | ||
e.testSuite.Items[i].Name = fmt.Sprintf("%s-%d", item.Name, marker[item.Name]) | ||
} else { | ||
marker[item.Name] = 0 | ||
} | ||
} | ||
|
||
data, err := yaml.Marshal(e.testSuite) | ||
return prefix + string(data), err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
module github.com/linuxsuren/api-testing/extensions/collector | ||
|
||
go 1.19 | ||
|
||
require ( | ||
github.com/Masterminds/goutils v1.1.1 // indirect | ||
github.com/Masterminds/semver/v3 v3.2.0 // indirect | ||
github.com/Masterminds/sprig/v3 v3.2.3 // indirect | ||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 // indirect | ||
github.com/antonmedv/expr v1.12.1 // indirect | ||
github.com/elazarl/goproxy v0.0.0-20221015165544-a0805db90819 // indirect | ||
github.com/ghodss/yaml v1.0.0 // indirect | ||
github.com/golang/protobuf v1.5.2 // indirect | ||
github.com/google/uuid v1.3.0 // indirect | ||
github.com/huandu/xstrings v1.3.3 // indirect | ||
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect | ||
github.com/imdario/mergo v0.3.11 // indirect | ||
github.com/inconshreveable/mousetrap v1.1.0 // indirect | ||
github.com/invopop/jsonschema v0.7.0 // indirect | ||
github.com/linuxsuren/api-testing v0.0.11 // indirect | ||
github.com/linuxsuren/go-fake-runtime v0.0.0-20230413085645-15e77ab55dbd // indirect | ||
github.com/linuxsuren/unstructured v0.0.1 // indirect | ||
github.com/mitchellh/copystructure v1.0.0 // indirect | ||
github.com/mitchellh/reflectwalk v1.0.0 // indirect | ||
github.com/sergi/go-diff v1.2.0 // indirect | ||
github.com/shopspring/decimal v1.2.0 // indirect | ||
github.com/spf13/cast v1.3.1 // indirect | ||
github.com/spf13/cobra v1.7.0 // indirect | ||
github.com/spf13/pflag v1.0.5 // indirect | ||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect | ||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect | ||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect | ||
golang.org/x/crypto v0.3.0 // indirect | ||
golang.org/x/net v0.8.0 // indirect | ||
golang.org/x/sync v0.1.0 // indirect | ||
golang.org/x/sys v0.6.0 // indirect | ||
golang.org/x/text v0.8.0 // indirect | ||
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect | ||
google.golang.org/grpc v1.54.0 // indirect | ||
google.golang.org/protobuf v1.30.0 // indirect | ||
gopkg.in/yaml.v2 v2.3.0 // indirect | ||
) | ||
|
||
replace github.com/linuxsuren/api-testing => ../../. |
Oops, something went wrong.