forked from TrueCloudLab/distribution
98 lines
2.3 KiB
Go
98 lines
2.3 KiB
Go
|
package test
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"fmt"
|
||
|
"io"
|
||
|
"io/ioutil"
|
||
|
"net/http"
|
||
|
)
|
||
|
|
||
|
// RequestResponseMap is a mapping from Requests to Responses
|
||
|
type RequestResponseMap []RequestResponseMapping
|
||
|
|
||
|
// RequestResponseMapping defines an ordered list of Responses to be sent in
|
||
|
// response to a given Request
|
||
|
type RequestResponseMapping struct {
|
||
|
Request Request
|
||
|
Responses []Response
|
||
|
}
|
||
|
|
||
|
// TODO(bbland): add support for request headers
|
||
|
|
||
|
// Request is a simplified http.Request object
|
||
|
type Request struct {
|
||
|
// Method is the http method of the request, for example GET
|
||
|
Method string
|
||
|
|
||
|
// Route is the http route of this request
|
||
|
Route string
|
||
|
|
||
|
// Body is the byte contents of the http request
|
||
|
Body []byte
|
||
|
}
|
||
|
|
||
|
func (r Request) String() string {
|
||
|
return fmt.Sprintf("%s %s\n%s", r.Method, r.Route, r.Body)
|
||
|
}
|
||
|
|
||
|
// Response is a simplified http.Response object
|
||
|
type Response struct {
|
||
|
// Statuscode is the http status code of the Response
|
||
|
StatusCode int
|
||
|
|
||
|
// Headers are the http headers of this Response
|
||
|
Headers http.Header
|
||
|
|
||
|
// Body is the response body
|
||
|
Body []byte
|
||
|
}
|
||
|
|
||
|
// testHandler is an http.Handler with a defined mapping from Request to an
|
||
|
// ordered list of Response objects
|
||
|
type testHandler struct {
|
||
|
responseMap map[string][]Response
|
||
|
}
|
||
|
|
||
|
// NewHandler returns a new test handler that responds to defined requests
|
||
|
// with specified responses
|
||
|
// Each time a Request is received, the next Response is returned in the
|
||
|
// mapping, until no Responses are defined, at which point a 404 is sent back
|
||
|
func NewHandler(requestResponseMap RequestResponseMap) http.Handler {
|
||
|
responseMap := make(map[string][]Response)
|
||
|
for _, mapping := range requestResponseMap {
|
||
|
responseMap[mapping.Request.String()] = mapping.Responses
|
||
|
}
|
||
|
return &testHandler{responseMap: responseMap}
|
||
|
}
|
||
|
|
||
|
func (app *testHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||
|
defer r.Body.Close()
|
||
|
|
||
|
requestBody, _ := ioutil.ReadAll(r.Body)
|
||
|
request := Request{
|
||
|
Method: r.Method,
|
||
|
Route: r.URL.Path,
|
||
|
Body: requestBody,
|
||
|
}
|
||
|
|
||
|
responses, ok := app.responseMap[request.String()]
|
||
|
|
||
|
if !ok || len(responses) == 0 {
|
||
|
http.NotFound(w, r)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
response := responses[0]
|
||
|
app.responseMap[request.String()] = responses[1:]
|
||
|
|
||
|
responseHeader := w.Header()
|
||
|
for k, v := range response.Headers {
|
||
|
responseHeader[k] = v
|
||
|
}
|
||
|
|
||
|
w.WriteHeader(response.StatusCode)
|
||
|
|
||
|
io.Copy(w, bytes.NewReader(response.Body))
|
||
|
}
|