commit 85908fe28ceff69ca4ab6b1c008b0c7834f7cbb9 Author: kekskurse Date: Fri Sep 13 20:07:48 2024 +0200 init diff --git a/.woodpecker.yaml b/.woodpecker.yaml new file mode 100644 index 0000000..c6d443c --- /dev/null +++ b/.woodpecker.yaml @@ -0,0 +1,22 @@ +steps: + - name: build + image: golang:1.23 + commands: + - go test ./... + - go build ./ + - name: docker + image: plugins/docker + depends_on: [ build ] + settings: + username: kekskurse + password: + from_secret: docker + repo: kekskurse/minimock + dockerfile: Dockerfile + tags: + - latest + - ${CI_COMMIT_SHA} + when: + event: push + branch: [main] + diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c64b608 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,3 @@ +From scratch +COPY ./minimock /minimock +CMD ["/minimock"] diff --git a/config.sample.yml b/config.sample.yml new file mode 100644 index 0000000..d9aca82 --- /dev/null +++ b/config.sample.yml @@ -0,0 +1,10 @@ +--- +routen: + - path: /test + response_body: "Juhu das geht ja" + - path: /test2 + response_body: "Das geht auch" + - path: /httpstatus + response_body: "Here the http response code should be 234" + response_http_status: 234 + diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..76b3c93 --- /dev/null +++ b/go.mod @@ -0,0 +1,18 @@ +module git.keks.cloud/kekskurse/minimock + +go 1.23.1 + +require ( + github.com/rs/zerolog v1.33.0 + github.com/urfave/cli/v2 v2.27.4 + gopkg.in/yaml.v3 v3.0.1 +) + +require ( + github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect + golang.org/x/sys v0.12.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..032fa72 --- /dev/null +++ b/go.sum @@ -0,0 +1,27 @@ +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/urfave/cli/v2 v2.27.4 h1:o1owoI+02Eb+K107p27wEX9Bb8eqIoZCfLXloLUSWJ8= +github.com/urfave/cli/v2 v2.27.4/go.mod h1:m4QzxcD2qpra4z7WhzEGn74WZLViBnMpb1ToCAKdGRQ= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go new file mode 100644 index 0000000..f6d3577 --- /dev/null +++ b/main.go @@ -0,0 +1,106 @@ +package main + +import ( + "encoding/json" + "net/http" + "os" + "time" + + "github.com/rs/zerolog/log" + "github.com/urfave/cli/v2" + "gopkg.in/yaml.v3" +) + +type config struct { + Routen []routeConfig `yaml:"routen"` +} +type routeConfig struct { + Path string + ResponseHTTPStatus int `yaml:"response_http_status"` + ResponseBody string `yaml:"response_body"` + ResponseHeaders map[string]string `yaml:"response_header"` +} + +type requestData struct { + Path string `json:"path"` + Time time.Time `json:"time"` +} + +var requestDataList []requestData + +func (ro routeConfig) httpHandler(w http.ResponseWriter, r *http.Request) { + if ro.ResponseHTTPStatus != 0 { + w.WriteHeader(ro.ResponseHTTPStatus) + } + for v := range ro.ResponseHeaders { + w.Header().Add(v, ro.ResponseHeaders[v]) + } + _, err := w.Write([]byte(ro.ResponseBody)) + if err != nil { + log.Error().Err(err).Msg("cant write body to response writer") + } + + rde := requestData{ + Path: r.URL.Path, + Time: time.Now(), + } + + requestDataList = append(requestDataList, rde) +} + +func main() { + app := &cli.App{ + Name: "run", + Usage: "Run the minimock http server", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "config", + Aliases: []string{"c"}, + Usage: "Load configuration from `FILE`", + Value: "config.yml", + }, + }, + Action: action, + } + + if err := app.Run(os.Args); err != nil { + log.Fatal().Err(err).Msg("Finish App") + } +} + +func action(c *cli.Context) error { + log.Info().Msg("Start") + fileContent, err := os.ReadFile(c.String("config")) + if err != nil { + return err + } + + co := config{} + err = yaml.Unmarshal(fileContent, &co) + if err != nil { + return err + } + initServer(co) + + err = http.ListenAndServe(":3333", nil) + return err +} + +func initServer(c config) { + for _, ro := range c.Routen { + log.Debug().Str("path", ro.Path).Msg("Register Route") + http.HandleFunc(ro.Path, ro.httpHandler) + } + + http.HandleFunc("/requestlog", func(w http.ResponseWriter, r *http.Request) { + data, err := json.Marshal(requestDataList) + if err != nil { + log.Error().Err(err).Msg("cant marshal request data list") + return + } + _, err = w.Write(data) + if err != nil { + log.Error().Err(err).Msg("error writing responste data lsit via http") + } + }) +} diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..0b26af8 --- /dev/null +++ b/readme.md @@ -0,0 +1,2 @@ +# MiniMock +Small HTTP Server sending static response (body, header, httpstatuscode) based on a config file. Also all requests are stored and visible via api. This can be used to develop and tests software talking with external http servers.