diff --git a/internal/server/http/handler.go b/internal/server/http/handler.go index cab0ae0..c440397 100644 --- a/internal/server/http/handler.go +++ b/internal/server/http/handler.go @@ -1,14 +1,12 @@ package http import ( - "io" "log" "net/http" - "os" "time" ) -// ImposterHandler create specific handler for the received imposter +// Handler create specific handler for the received imposter func ImposterHandler(i Imposter) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { res := i.NextResponse() @@ -17,7 +15,7 @@ func ImposterHandler(i Imposter) http.HandlerFunc { } writeHeaders(res, w) w.WriteHeader(res.Status) - writeBody(i, res, w) + writeBody(res, w) } } @@ -31,27 +29,9 @@ func writeHeaders(r Response, w http.ResponseWriter) { } } -func writeBody(i Imposter, r Response, w http.ResponseWriter) { - wb := []byte(r.Body) - - if r.BodyFile != nil { - bodyFile := i.CalculateFilePath(*r.BodyFile) - wb = fetchBodyFromFile(bodyFile) - } - w.Write(wb) -} - -func fetchBodyFromFile(bodyFile string) (bytes []byte) { - if _, err := os.Stat(bodyFile); os.IsNotExist(err) { - log.Printf("the body file %s not found\n", bodyFile) - return - } - - f, _ := os.Open(bodyFile) - defer f.Close() - bytes, err := io.ReadAll(f) +func writeBody(r Response, w http.ResponseWriter) { + _, err := w.Write(r.BodyData) if err != nil { - log.Printf("imposible read the file %s: %v\n", bodyFile, err) + log.Printf("error writing body: %v\n", err) } - return } diff --git a/internal/server/http/handler_test.go b/internal/server/http/handler_test.go index ba87c9e..38d4ce3 100644 --- a/internal/server/http/handler_test.go +++ b/internal/server/http/handler_test.go @@ -59,6 +59,7 @@ func TestImposterHandler(t *testing.T) { assert.NoError(t, err) rec := httptest.NewRecorder() + tt.imposter.PopulateBodyData() handler := ImposterHandler(tt.imposter) handler.ServeHTTP(rec, req) @@ -95,6 +96,7 @@ func TestInvalidRequestWithSchema(t *testing.T) { req, err := http.NewRequest("POST", "/gophers", bytes.NewBuffer(tt.request)) assert.Nil(t, err) rec := httptest.NewRecorder() + tt.imposter.PopulateBodyData() handler := ImposterHandler(tt.imposter) handler.ServeHTTP(rec, req) @@ -125,6 +127,7 @@ func TestImposterHandler_MultipleRequests(t *testing.T) { }, } + imp.PopulateBodyData() handler := ImposterHandler(imp) // First request @@ -141,12 +144,15 @@ func TestImposterHandler_MultipleRequests(t *testing.T) { }) t.Run("idempotent", func(t *testing.T) { - handler := ImposterHandler(Imposter{ + imp := Imposter{ Request: Request{Method: "POST", Endpoint: "/gophers"}, Response: Responses{ {Status: http.StatusAccepted, Body: "Accepted"}, }, - }) + } + imp.PopulateBodyData() + + handler := ImposterHandler(imp) // First request rec := httptest.NewRecorder() diff --git a/internal/server/http/imposter.go b/internal/server/http/imposter.go index e5ae638..e6a7f58 100644 --- a/internal/server/http/imposter.go +++ b/internal/server/http/imposter.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "io/fs" + "log" "os" "path" "path/filepath" @@ -57,6 +58,34 @@ func (i *Imposter) CalculateFilePath(filePath string) string { return path.Join(i.BasePath, filePath) } +func (i *Imposter) PopulateBodyData() { + for idx, resp := range i.Response { + resp.BodyData = []byte(resp.Body) + + if resp.BodyFile != nil { + bodyFile := i.CalculateFilePath(*resp.BodyFile) + resp.BodyData = fetchBodyFromFile(bodyFile) + } + + i.Response[idx] = resp + } +} + +func fetchBodyFromFile(bodyFile string) (bytes []byte) { + if _, err := os.Stat(bodyFile); os.IsNotExist(err) { + log.Printf("ERROR: the body file %s not found\n", bodyFile) + return + } + + f, _ := os.Open(bodyFile) + defer f.Close() + bytes, err := io.ReadAll(f) + if err != nil { + log.Printf("ERROR: imposible read the file %s: %v\n", bodyFile, err) + } + return +} + // Request represent the structure of real request type Request struct { Method string `json:"method"` @@ -71,6 +100,7 @@ type Response struct { Status int `json:"status"` Body string `json:"body"` BodyFile *string `json:"bodyFile" yaml:"bodyFile"` + BodyData []byte `json:"-" yaml:"-"` Headers *map[string]string `json:"headers"` Delay ResponseDelay `json:"delay" yaml:"delay"` } @@ -201,9 +231,9 @@ func (i ImposterFs) unmarshalImposters(imposterConfig ImposterConfig) ([]Imposte return nil, fmt.Errorf("%w: error while unmarshalling imposter's file %s", parseError, imposterConfig.FilePath) } - for i := range imposters { - imposters[i].BasePath = filepath.Dir(imposterConfig.FilePath) - imposters[i].Path = imposterConfig.FilePath + for idx := range imposters { + imposters[idx].BasePath = filepath.Dir(filepath.Join(i.path, imposterConfig.FilePath)) + imposters[idx].Path = imposterConfig.FilePath } return imposters, nil diff --git a/internal/server/http/server.go b/internal/server/http/server.go index d334e84..d5a18d3 100644 --- a/internal/server/http/server.go +++ b/internal/server/http/server.go @@ -155,6 +155,7 @@ func (s *Server) Shutdown() error { func (s *Server) addImposterHandler(imposters []Imposter) { for _, imposter := range imposters { + imposter.PopulateBodyData() r := s.router.HandleFunc(imposter.Request.Endpoint, ImposterHandler(imposter)). Methods(imposter.Request.Method). MatcherFunc(MatcherBySchema(imposter))