diff --git a/README.md b/README.md index 824438f..d29f8b9 100644 --- a/README.md +++ b/README.md @@ -74,5 +74,7 @@ endpoints: defaultResponseContent: "Sample service" # Default response content-type, if not provided "text/plain; charset=utf-8" defaultResponseContentType: text/plain; charset=utf-8 + # Path to the file that is returned by default, if provided then defaultResponseContent is ignored + defaultResponseFile: "mockice/index.html" ``` diff --git a/pkg/endpoint/endpoint.go b/pkg/endpoint/endpoint.go index 116ee66..605fc5f 100644 --- a/pkg/endpoint/endpoint.go +++ b/pkg/endpoint/endpoint.go @@ -1,7 +1,11 @@ package endpoint import ( + "io" + "io/ioutil" "net/http" + "os" + "strings" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -14,6 +18,7 @@ type Config struct { DefaultResponseCode *int `yaml:"defaultResponseCode"` DefaultResponseContent string `yaml:"defaultResponseContent"` DefaultResponseContentType *string `yaml:"defaultResponseContentType"` + DefaultResponseFile *string `yaml:"defaultResponseFile"` } // DefaultConfig generates default configuration with /hello endpoint @@ -51,17 +56,28 @@ func (e *Endpoint) Handle(writer http.ResponseWriter, request *http.Request) { return } - if e.config.DefaultResponseContentType != nil { - writer.Header().Set("Content-Type", *e.config.DefaultResponseContentType) + writer.Header().Set("Content-Type", e.defaultContentType()) + + var reader io.ReadCloser + if e.config.DefaultResponseFile != nil { + file, err := e.fileReader(writer) + if err != nil { + http.Error(writer, err.Error(), http.StatusInternalServerError) + e.log.Error(err) + return + } + + reader = file } else { - writer.Header().Set("Content-Type", "text/plain; charset=utf-8") + reader = ioutil.NopCloser(strings.NewReader(e.config.DefaultResponseContent)) } + defer reader.Close() if e.config.DefaultResponseCode != nil { writer.WriteHeader(*e.config.DefaultResponseCode) } - _, err := writer.Write([]byte(e.config.DefaultResponseContent)) + _, err := io.Copy(writer, reader) if err != nil { err = errors.Wrapf(err, "while writing response") http.Error(writer, err.Error(), http.StatusInternalServerError) @@ -70,6 +86,22 @@ func (e *Endpoint) Handle(writer http.ResponseWriter, request *http.Request) { } } +func (e *Endpoint) defaultContentType() string { + if e.config.DefaultResponseContentType != nil { + return *e.config.DefaultResponseContentType + } + return "text/plain; charset=utf-8" +} + +func (e *Endpoint) fileReader(writer io.Writer) (io.ReadCloser, error) { + file, err := os.Open(*e.config.DefaultResponseFile) + if err != nil { + return nil, errors.Wrapf(err, "while opening file %s", *e.config.DefaultResponseFile) + } + + return file, nil +} + // Name returns name of the endpoint func (e *Endpoint) Name() string { return e.config.Name diff --git a/pkg/endpoint/endpoint_test.go b/pkg/endpoint/endpoint_test.go index 0668014..6943889 100644 --- a/pkg/endpoint/endpoint_test.go +++ b/pkg/endpoint/endpoint_test.go @@ -3,6 +3,7 @@ package endpoint_test import ( "bytes" "fmt" + "io/ioutil" "net/http" "net/http/httptest" "strings" @@ -105,6 +106,37 @@ func TestEndpoint_Handle(t *testing.T) { DefaultResponseCode: intPointer(http.StatusNotModified), }, }, + "With file": { + method: http.MethodGet, + expectedResponseCode: http.StatusOK, + config: endpoint.Config{ + Name: "simple", + DefaultResponseCode: intPointer(http.StatusOK), + DefaultResponseContentType: stringPointer("text/markdown; charset=utf-8"), + DefaultResponseFile: stringPointer("testdata/test.md"), + }, + }, + "With file and content": { + method: http.MethodGet, + expectedResponseCode: http.StatusOK, + config: endpoint.Config{ + Name: "simple", + DefaultResponseContent: "test", + DefaultResponseCode: intPointer(http.StatusOK), + DefaultResponseContentType: stringPointer("text/markdown; charset=utf-8"), + DefaultResponseFile: stringPointer("testdata/test.md"), + }, + }, + "With not existing file": { + method: http.MethodGet, + expectedResponseCode: http.StatusInternalServerError, + config: endpoint.Config{ + Name: "simple", + DefaultResponseCode: intPointer(http.StatusOK), + DefaultResponseContentType: stringPointer("text/markdown; charset=utf-8"), + DefaultResponseFile: stringPointer("testdata/test.md.fail"), + }, + }, } { t.Run(testName, func(t *testing.T) { // Given @@ -133,11 +165,26 @@ func TestEndpoint_Handle(t *testing.T) { buff := new(bytes.Buffer) buff.ReadFrom(recorder.Result().Body) - g.Expect(buff.String()).To(Equal(testCase.config.DefaultResponseContent)) + if testCase.config.DefaultResponseFile == nil { + g.Expect(buff.String()).To(Equal(testCase.config.DefaultResponseContent)) + } else { + content, err := readFile(*testCase.config.DefaultResponseFile) + g.Expect(err).To(Succeed()) + g.Expect(buff.String()).To(Equal(content)) + } }) } } +func readFile(path string) (string, error) { + content, err := ioutil.ReadFile(path) + if err != nil { + return "", err + } + + return string(content), nil +} + func stringPointer(value string) *string { return &value } diff --git a/pkg/endpoint/testdata/test.md b/pkg/endpoint/testdata/test.md new file mode 100644 index 0000000..d696bf7 --- /dev/null +++ b/pkg/endpoint/testdata/test.md @@ -0,0 +1,3 @@ +# Header + +Text \ No newline at end of file