Files
codapi/httpx/mock.go
2023-11-25 04:02:45 +05:00

97 lines
2.2 KiB
Go

package httpx
import (
"bufio"
"bytes"
"fmt"
"io"
"net/http"
"net/http/httptest"
"os"
"path"
"path/filepath"
)
var contentTypes = map[string]string{
".json": "application/json",
".txt": "text/plain",
}
// MockClient serves responses from the file system instead of remote calls.
// Should be used for testing purposes only.
type MockClient struct {
dir string
}
// Mock creates a new MockClient and installs it instead of the default one.
func Mock(path ...string) *MockClient {
dir := filepath.Join("testdata", filepath.Join(path...))
c := &MockClient{dir: dir}
client = c
return c
}
// Do serves the file according to the request URL.
func (c *MockClient) Do(req *http.Request) (*http.Response, error) {
filename := filepath.Join(c.dir, path.Base(req.URL.Path))
data, err := os.ReadFile(filename)
if err != nil {
resp := http.Response{
Status: http.StatusText(http.StatusNotFound),
StatusCode: http.StatusNotFound,
}
return &resp, nil
}
cType, ok := contentTypes[path.Ext(filename)]
if !ok {
cType = "application/octet-stream"
}
rdr := respond(cType, data)
resp, err := http.ReadResponse(bufio.NewReader(rdr), req)
if err != nil {
panic(err)
}
return resp, nil
}
func respond(cType string, data []byte) io.Reader {
buf := bytes.Buffer{}
buf.WriteString("HTTP/1.1 200 OK\n")
buf.WriteString(fmt.Sprintf("Content-Type: %s\n\n", cType))
_, err := buf.Write(data)
if err != nil {
panic(err)
}
return &buf
}
// MockServer creates a mock HTTP server and installs its client
// instead of the default one. Serves responses from the file system
// instead of remote calls. Should be used for testing purposes only.
func MockServer() *httptest.Server {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
filename := filepath.Join("testdata", path.Base(r.URL.Path))
data, err := os.ReadFile(filename)
if err != nil {
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
return
}
cType, ok := contentTypes[path.Ext(filename)]
if !ok {
cType = "application/octet-stream"
}
w.Header().Set("content-type", cType)
_, err = w.Write(data)
if err != nil {
panic(err)
}
}))
client = srv.Client()
return srv
}