func TestModifierFromJSON(t *testing.T) { msg := []byte(` { "querystring.Modifier": { "scope": ["request"], "name": "param", "value": "true" } }`) r, err := parse.FromJSON(msg) if err != nil { t.Fatalf("parse.FromJSON(): got %v, want no error", err) } req, err := http.NewRequest("GET", "http://martian.test", nil) if err != nil { t.Fatalf("http.NewRequest(): got %q, want no error", err) } reqmod := r.RequestModifier() if reqmod == nil { t.Fatalf("reqmod: got nil, want not nil") } if err := reqmod.ModifyRequest(req); err != nil { t.Fatalf("reqmod.ModifyRequest(): got %v, want no error", err) } if got, want := req.URL.Query().Get("param"), "true"; got != want { t.Errorf("req.URL.Query().Get(%q): got %q, want %q", "param", got, want) } }
func TestVerifierFromJSON(t *testing.T) { msg := []byte(`{ "method.Verifier": { "scope": ["request"], "method": "POST" } }`) r, err := parse.FromJSON(msg) if err != nil { t.Fatalf("parse.FromJSON(): got %v, want no error", err) } reqmod := r.RequestModifier() if reqmod == nil { t.Fatal("reqmod: got nil, want not nil") } reqv, ok := reqmod.(verify.RequestVerifier) if !ok { t.Fatal("reqmod.(verify.RequestVerifier): got !ok, want ok") } req, err := http.NewRequest("GET", "http://example.com", nil) if err != nil { t.Fatalf("http.NewRequest(): got %v, want no error", err) } if err := reqv.ModifyRequest(req); err != nil { t.Fatalf("ModifyRequest(): got %v, want no error", err) } if err := reqv.VerifyRequests(); err == nil { t.Error("VerifyRequests(): got nil, want not nil") } }
func TestFromJSON(t *testing.T) { msg := []byte(`{ "status.Modifier": { "scope": ["response"], "statusCode": 400 } }`) r, err := parse.FromJSON(msg) if err != nil { t.Fatalf("parse.FromJSON(): got %v, want no error", err) } resmod := r.ResponseModifier() if resmod == nil { t.Fatal("resmod: got nil, want not nil") } res := proxyutil.NewResponse(200, nil, nil) if err := resmod.ModifyResponse(res); err != nil { t.Fatalf("ModifyResponse(): got %v, want no error", err) } if got, want := res.StatusCode, 400; got != want { t.Errorf("res.StatusCode: got %d, want %d", got, want) } }
// ServeHTTP accepts a POST request with a body containing a modifier as a JSON // message and updates the contained reqmod and resmod with the parsed // modifier. func (m *Modifier) ServeHTTP(rw http.ResponseWriter, req *http.Request) { if req.Method != "POST" { rw.Header().Set("Allow", "POST") rw.WriteHeader(405) return } body, err := ioutil.ReadAll(req.Body) if err != nil { http.Error(rw, err.Error(), 500) martian.Errorf("error reading request body: %v", err) return } req.Body.Close() r, err := parse.FromJSON(body) if err != nil { http.Error(rw, err.Error(), 400) martian.Errorf("error parsing JSON: %v", err) return } m.SetRequestModifier(r.RequestModifier()) m.SetResponseModifier(r.ResponseModifier()) }
func TestModifierFromJSON(t *testing.T) { msg := []byte(`{ "cookie.Modifier": { "scope": ["request", "response"], "name": "martian", "value": "value" } }`) r, err := parse.FromJSON(msg) if err != nil { t.Fatalf("parse.FromJSON(): got %v, want no error", err) } req, err := http.NewRequest("GET", "http://example.com/path/", nil) if err != nil { t.Fatalf("http.NewRequest(): got %v, want no error", err) } reqmod := r.RequestModifier() if reqmod == nil { t.Fatal("reqmod: got nil, want not nil") } if err := reqmod.ModifyRequest(martian.NewContext(), req); err != nil { t.Fatalf("reqmod.ModifyRequest(): got %v, want no error", err) } if got, want := len(req.Cookies()), 1; got != want { t.Fatalf("len(req.Cookies): got %v, want %v", got, want) } if got, want := req.Cookies()[0].Name, "martian"; got != want { t.Errorf("req.Cookies()[0].Name: got %v, want %v", got, want) } if got, want := req.Cookies()[0].Value, "value"; got != want { t.Errorf("req.Cookies()[0].Value: got %v, want %v", got, want) } resmod := r.ResponseModifier() if resmod == nil { t.Fatal("resmod: got nil, want not nil") } res := proxyutil.NewResponse(200, nil, req) if err := resmod.ModifyResponse(martian.NewContext(), res); err != nil { t.Fatalf("resmod.ModifyResponse(): got %v, want no error", err) } if got, want := len(res.Cookies()), 1; got != want { t.Fatalf("len(res.Cookies): got %v, want %v", got, want) } if got, want := res.Cookies()[0].Name, "martian"; got != want { t.Errorf("res.Cookies()[0].Name: got %v, want %v", got, want) } if got, want := res.Cookies()[0].Value, "value"; got != want { t.Errorf("res.Cookies()[0].Value: got %v, want %v", got, want) } }
// groupFromJSON builds a priority.Group from JSON. // // Example JSON: // { // "priority.Group": { // "scope": ["request", "response"], // "modifiers": [ // { // "priority": 100, // Will run first. // "modifier": { ... }, // }, // { // "priority": 0, // Will run last. // "modifier": { ... }, // } // ] // } // } func groupFromJSON(b []byte) (*parse.Result, error) { msg := &groupJSON{} if err := json.Unmarshal(b, msg); err != nil { return nil, err } pg := NewGroup() for _, m := range msg.Modifiers { r, err := parse.FromJSON(m.Modifier) if err != nil { return nil, err } reqmod := r.RequestModifier() if reqmod != nil { pg.AddRequestModifier(reqmod, m.Priority) } resmod := r.ResponseModifier() if resmod != nil { pg.AddResponseModifier(resmod, m.Priority) } } return parse.NewResult(pg, msg.Scope) }
func TestLoggerFromJSON(t *testing.T) { msg := []byte(`{ "log.Logger": { "scope": ["request", "response"] } }`) r, err := parse.FromJSON(msg) if err != nil { t.Fatalf("parse.FromJSON(): got %v, want no error", err) } reqmod := r.RequestModifier() if reqmod == nil { t.Fatal("r.RequestModifier(): got nil, want not nil") } if _, ok := reqmod.(*Logger); !ok { t.Error("reqmod.(*Logger): got !ok, want ok") } resmod := r.ResponseModifier() if resmod == nil { t.Fatal("r.ResponseModifier(): got nil, want not nil") } if _, ok := resmod.(*Logger); !ok { t.Error("resmod.(*Logger); got !ok, want ok") } }
// filterFromJSON takes a JSON message as a byte slice and returns a // parse.Result that contains a URLFilter and a bitmask that represents the // type of modifier. // // Example JSON configuration message: // { // "scheme": "https", // "host": "example.com", // "path": "/foo/bar", // "rawQuery": "q=value", // "scope": ["request", "response"], // "modifier": { ... } // } func filterFromJSON(b []byte) (*parse.Result, error) { msg := &filterJSON{} if err := json.Unmarshal(b, msg); err != nil { return nil, err } filter := NewFilter(&url.URL{ Scheme: msg.Scheme, Host: msg.Host, Path: msg.Path, RawQuery: msg.Query, }) r, err := parse.FromJSON(msg.Modifier) if err != nil { return nil, err } reqmod := r.RequestModifier() if err != nil { return nil, err } if reqmod != nil { filter.SetRequestModifier(reqmod) } resmod := r.ResponseModifier() if resmod != nil { filter.SetResponseModifier(resmod) } return parse.NewResult(filter, msg.Scope) }
func TestVerifierFromJSON(t *testing.T) { msg := []byte(`{ "status.Verifier": { "scope": ["response"], "statusCode": 400 } }`) r, err := parse.FromJSON(msg) if err != nil { t.Fatalf("parse.FromJSON(): got %v, want no error", err) } resmod := r.ResponseModifier() if resmod == nil { t.Fatal("resmod: got nil, want not nil") } resv, ok := resmod.(verify.ResponseVerifier) if !ok { t.Fatal("reqmod.(verify.RequestVerifier): got !ok, want ok") } req, err := http.NewRequest("GET", "http://www.example.com", nil) if err != nil { t.Fatalf("http.NewRequest(): got %v, want no error", err) } res := proxyutil.NewResponse(200, nil, req) if err := resv.ModifyResponse(martian.NewContext(), res); err != nil { t.Fatalf("ModifyResponse(): got %v, want no error", err) } if err := resv.VerifyResponses(); err == nil { t.Error("VerifyResponses(): got nil, want not nil") } }
func (m *Modifier) servePOST(rw http.ResponseWriter, req *http.Request) { body, err := ioutil.ReadAll(req.Body) if err != nil { http.Error(rw, err.Error(), 500) log.Errorf("martianhttp: error reading request body: %v", err) return } req.Body.Close() r, err := parse.FromJSON(body) if err != nil { http.Error(rw, err.Error(), 400) log.Errorf("martianhttp: error parsing JSON: %v", err) return } buf := new(bytes.Buffer) if err := json.Indent(buf, body, "", " "); err != nil { http.Error(rw, err.Error(), 400) log.Errorf("martianhttp: error formatting JSON: %v", err) return } m.mu.Lock() defer m.mu.Unlock() m.config = buf.Bytes() m.setRequestModifier(r.RequestModifier()) m.setResponseModifier(r.ResponseModifier()) }
func TestVerifierFromJSON(t *testing.T) { msg := []byte(`{ "url.Verifier": { "scope": ["request"], "scheme": "https", "host": "www.martian.proxy", "path": "/testing", "query": "test=true" } }`) r, err := parse.FromJSON(msg) if err != nil { t.Fatalf("parse.FromJSON(): got %v, want no error", err) } reqmod := r.RequestModifier() if reqmod == nil { t.Fatal("reqmod: got nil, want not nil") } reqv, ok := reqmod.(verify.RequestVerifier) if !ok { t.Fatal("reqmod.(verify.RequestVerifier): got !ok, want ok") } req, err := http.NewRequest("GET", "https://www.martian.proxy/testing?test=false", nil) if err != nil { t.Fatalf("http.NewRequest(): got %v, want no error", err) } if err := reqv.ModifyRequest(req); err != nil { t.Fatalf("ModifyRequest(): got %v, want no error", err) } if err := reqv.VerifyRequests(); err == nil { t.Error("VerifyRequests(): got nil, want not nil") } }
// filterFromJSON takes a JSON message and returns a querystring.Filter. // // Example JSON: // { // "name": "param", // "value": "example", // "scope": ["request", "response"], // "modifier": { ... } // } func filterFromJSON(b []byte) (*parse.Result, error) { msg := &filterJSON{} if err := json.Unmarshal(b, msg); err != nil { return nil, err } nameMatcher, err := regexp.Compile(msg.Name) if err != nil { return nil, err } valueMatcher, err := regexp.Compile(msg.Value) if err != nil { return nil, err } filter, err := NewFilter(nameMatcher, valueMatcher) if err != nil { return nil, err } r, err := parse.FromJSON(msg.Modifier) if err != nil { return nil, err } reqmod := r.RequestModifier() filter.SetRequestModifier(reqmod) resmod := r.ResponseModifier() filter.SetResponseModifier(resmod) return parse.NewResult(filter, msg.Scope) }
func TestFilterFromJSON(t *testing.T) { msg := []byte(` { "querystring.Filter": { "scope": ["request", "response"], "name": "param", "value": "true", "modifier": { "header.Modifier": { "scope": ["request", "response"], "name": "Mod-Run", "value": "true" } } } }`) r, err := parse.FromJSON(msg) if err != nil { t.Fatalf("parse.FromJSON(): got %v, want no error", err) } reqmod := r.RequestModifier() if reqmod == nil { t.Fatal("reqmod: got nil, want not nil") } req, err := http.NewRequest("GET", "https://martian.test?param=true", nil) if err != nil { t.Fatalf("http.NewRequest(): got %v, want no error", err) } ctx := martian.NewContext() if err := reqmod.ModifyRequest(ctx, req); err != nil { t.Fatalf("reqmod.ModifyRequest(): got %v, want no error", err) } if got, want := req.Header.Get("Mod-Run"), "true"; got != want { t.Errorf("req.Header.Get(%q): got %q, want %q", "Mod-Run", got, want) } resmod := r.ResponseModifier() if resmod == nil { t.Fatalf("resmod: got nil, want not nil") } res := proxyutil.NewResponse(200, nil, req) if err := resmod.ModifyResponse(ctx, res); err != nil { t.Fatalf("resmod.ModifyResponse(): got %v, want no error", err) } if got, want := res.Header.Get("Mod-Run"), "true"; got != want { t.Errorf("res.Header.Get(%q): got %q, want %q", "Mod-Run", got, want) } }
func TestFilterFromJSON(t *testing.T) { msg := []byte(`{ "header.Filter": { "scope": ["request", "response"], "name": "Martian-Passthrough", "value": "true", "modifier": { "header.Modifier" : { "scope": ["request", "response"], "name": "Martian-Testing", "value": "true" } } } }`) r, err := parse.FromJSON(msg) if err != nil { t.Fatalf("parse.FromJSON(): got %v, want no error", err) } reqmod := r.RequestModifier() if reqmod == nil { t.Fatal("reqmod: got nil, want not nil") } req, err := http.NewRequest("GET", "http://example.com", nil) if err != nil { t.Fatalf("http.NewRequest(): got %v, want no error", err) } req.Header.Set("Martian-Passthrough", "true") if err := reqmod.ModifyRequest(req); err != nil { t.Fatalf("ModifyRequest(): got %v, want no error", err) } if got, want := req.Header.Get("Martian-Testing"), "true"; got != want { t.Fatalf("req.Header.Get(%q): got %q, want %q", "Martian-Testing", got, want) } resmod := r.ResponseModifier() if resmod == nil { t.Fatal("resmod: got nil, want not nil") } res := proxyutil.NewResponse(200, nil, nil) res.Header.Set("Martian-Passthrough", "true") if err := resmod.ModifyResponse(res); err != nil { t.Fatalf("ModifyResponse(): got %v, want no error", err) } if got, want := res.Header.Get("Martian-Testing"), "true"; got != want { t.Fatalf("res.Header.Get(%q): got %q, want %q", "Martian-Testing", got, want) } }
func TestVerifierFromJSON(t *testing.T) { msg := []byte(`{ "header.Verifier": { "scope": ["request", "response"], "name": "Martian-Test", "value": "true" } }`) r, err := parse.FromJSON(msg) if err != nil { t.Fatalf("parse.FromJSON(): got %v, want no error", err) } reqmod := r.RequestModifier() if reqmod == nil { t.Fatal("reqmod: got nil, want not nil") } reqv, ok := reqmod.(verify.RequestVerifier) if !ok { t.Fatal("reqmod.(verify.RequestVerifier): got !ok, want ok") } req, err := http.NewRequest("GET", "http://example.com", nil) if err != nil { t.Fatalf("http.NewRequest(): got %v, want no error", err) } if err := reqv.ModifyRequest(req); err != nil { t.Fatalf("ModifyRequest(): got %v, want no error", err) } if err := reqv.VerifyRequests(); err == nil { t.Error("VerifyRequests(): got nil, want not nil") } resmod := r.ResponseModifier() if resmod == nil { t.Fatal("resmod: got nil, want not nil") } resv, ok := resmod.(verify.ResponseVerifier) if !ok { t.Fatal("resmod.(verify.ResponseVerifier): got !ok, want ok") } res := proxyutil.NewResponse(200, nil, req) if err := resv.ModifyResponse(res); err != nil { t.Fatalf("ModifyResponse(): got %v, want no error", err) } if err := resv.VerifyResponses(); err == nil { t.Error("VerifyResponses(): got nil, want not nil") } }
func TestCopyModifierFromJSON(t *testing.T) { msg := []byte(`{ "header.Copy": { "from": "Original", "to": "Copy", "scope": ["request", "response"] } }`) r, err := parse.FromJSON(msg) if err != nil { t.Fatalf("parse.FromJSON(): got %v, want no error", err) } req, err := http.NewRequest("GET", "http://example.com", nil) if err != nil { t.Fatalf("http.NewRequest(): got %q, want no error", err) } req.Header.Set("Original", "test") reqmod := r.RequestModifier() if reqmod == nil { t.Fatal("reqmod: got nil, want not nil") } if err := reqmod.ModifyRequest(req); err != nil { t.Fatalf("ModifyRequest(): got %v, want no error", err) } if got, want := req.Header.Get("Copy"), "test"; got != want { t.Errorf("req.Header.Get(%q): got %q, want %q", "Copy", got, want) } resmod := r.ResponseModifier() if resmod == nil { t.Fatal("resmod: got nil, want not nil") } res := proxyutil.NewResponse(200, nil, req) res.Header.Set("Original", "test") if err := resmod.ModifyResponse(res); err != nil { t.Fatalf("ModifyResponse(): got %v, want no error", err) } if got, want := res.Header.Get("Copy"), "test"; got != want { t.Errorf("res.Header.Get(%q): got %q, want %q", "Copy", got, want) } }
func TestFromJSON(t *testing.T) { msg := []byte(`{ "skip.RoundTrip": {} }`) r, err := parse.FromJSON(msg) if err != nil { t.Fatalf("parse.FromJSON(): got %v, want no error", err) } reqmod := r.RequestModifier() if _, ok := reqmod.(*RoundTrip); !ok { t.Fatal("reqmod.(*RoundTrip): got !ok, want ok") } }
// filterFromJSON takes a JSON message and returns a querystring.Filter. // // Example JSON: // { // "name": "param", // "value": "example", // "scope": ["request", "response"], // "modifier": { ... } // } func filterFromJSON(b []byte) (*parse.Result, error) { msg := &filterJSON{} if err := json.Unmarshal(b, msg); err != nil { return nil, err } f := NewFilter(msg.Name, msg.Value) r, err := parse.FromJSON(msg.Modifier) if err != nil { return nil, err } f.SetRequestModifier(r.RequestModifier()) f.SetResponseModifier(r.ResponseModifier()) return parse.NewResult(f, msg.Scope) }
func TestModifierFromJSON(t *testing.T) { rawMsg := ` { "body.Modifier":{ "scope": ["response"], "contentType": "text/plain", "body": %q } } ` payload := base64.StdEncoding.EncodeToString([]byte("data")) msg := []byte(fmt.Sprintf(rawMsg, payload)) r, err := parse.FromJSON(msg) if err != nil { t.Fatalf("parse.FromJSON(): got %v, want no error", err) } resmod := r.ResponseModifier() if resmod == nil { t.Fatalf("resmod: got nil, want not nil") } res := proxyutil.NewResponse(200, nil, nil) if err := resmod.ModifyResponse(martian.NewContext(), res); err != nil { t.Fatalf("resmod.ModifyResponse(): got %v, want no error", err) } if got, want := res.Header.Get("Content-Type"), "text/plain"; got != want { t.Errorf("res.Header.Get(%q): got %v, want %v", "Content-Type", got, want) } got, err := ioutil.ReadAll(res.Body) if err != nil { t.Fatalf("ioutil.ReadAll(): got %v, want no error", err) } res.Body.Close() if want := []byte("data"); !bytes.Equal(got, want) { t.Errorf("res.Body: got %q, want %q", got, want) } }
func TestModifierFromJSON(t *testing.T) { msg := []byte(`{ "url.Modifier": { "scope": ["request"], "scheme": "https", "host": "www.martian.proxy", "path": "/testing", "query": "test=true" } }`) r, err := parse.FromJSON(msg) if err != nil { t.Fatalf("parse.FromJSON(): got %v, want no error", err) } reqmod := r.RequestModifier() if reqmod == nil { t.Fatal("reqmod: got nil, want not nil") } req, err := http.NewRequest("GET", "http://example.com", nil) if err != nil { t.Fatalf("http.NewRequest(): got %v, want no error", err) } if err := reqmod.ModifyRequest(martian.NewContext(), req); err != nil { t.Fatalf("ModifyRequest(): got %v, want no error", err) } if got, want := req.URL.Scheme, "https"; got != want { t.Errorf("req.URL.Scheme: got %q, want %q", got, want) } if got, want := req.URL.Host, "www.martian.proxy"; got != want { t.Errorf("req.URL.Host: got %q, want %q", got, want) } if got, want := req.URL.Path, "/testing"; got != want { t.Errorf("req.URL.Path: got %q, want %q", got, want) } if got, want := req.URL.RawQuery, "test=true"; got != want { t.Errorf("req.URL.RawQuery: got %q, want %q", got, want) } }
func TestLoggerFromJSON(t *testing.T) { msg := []byte(`{ "log.Logger": { "scope": ["request", "response"], "headersOnly": true, "decode": true } }`) r, err := parse.FromJSON(msg) if err != nil { t.Fatalf("parse.FromJSON(): got %v, want no error", err) } reqmod := r.RequestModifier() if reqmod == nil { t.Fatal("r.RequestModifier(): got nil, want not nil") } if _, ok := reqmod.(*Logger); !ok { t.Error("reqmod.(*Logger): got !ok, want ok") } resmod := r.ResponseModifier() if resmod == nil { t.Fatal("r.ResponseModifier(): got nil, want not nil") } l, ok := resmod.(*Logger) if !ok { t.Error("resmod.(*Logger); got !ok, want ok") } if !l.headersOnly { t.Error("l.headersOnly: got false, want true") } if !l.decode { t.Error("l.decode: got false, want true") } }
func TestGroupFromJSON(t *testing.T) { msg := []byte(`{ "priority.Group": { "scope": ["request", "response"], "modifiers": [ { "priority": 100, "modifier": { "header.Modifier": { "scope": ["request", "response"], "name": "X-Testing", "value": "true" } } }, { "priority": 0, "modifier": { "header.Modifier": { "scope": ["request", "response"], "name": "Y-Testing", "value": "true" } } } ] } }`) r, err := parse.FromJSON(msg) if err != nil { t.Fatalf("parse.FromJSON(): got %v, want no error", err) } reqmod := r.RequestModifier() if reqmod == nil { t.Fatal("reqmod: got nil, want not nil") } req, err := http.NewRequest("GET", "http://example.com", nil) if err != nil { t.Fatalf("http.NewRequest(): got %v, want no error", err) } if err := reqmod.ModifyRequest(req); err != nil { t.Fatalf("ModifyRequest(): got %v, want no error", err) } if got, want := req.Header.Get("X-Testing"), "true"; got != want { t.Errorf("req.Header.Get(%q): got %q, want %q", "X-Testing", got, want) } if got, want := req.Header.Get("Y-Testing"), "true"; got != want { t.Errorf("req.Header.Get(%q): got %q, want %q", "Y-Testing", got, want) } resmod := r.ResponseModifier() if resmod == nil { t.Fatal("resmod: got nil, want not nil") } res := proxyutil.NewResponse(200, nil, req) if err := resmod.ModifyResponse(res); err != nil { t.Fatalf("ModifyResponse(): got %v, want no error", err) } if got, want := res.Header.Get("X-Testing"), "true"; got != want { t.Errorf("res.Header.Get(%q): got %q, want %q", "X-Testing", got, want) } if got, want := res.Header.Get("Y-Testing"), "true"; got != want { t.Errorf("res.Header.Get(%q): got %q, want %q", "Y-Testing", got, want) } }
func TestBlacklistModifierFromJSON(t *testing.T) { msg := []byte(`{ "header.Blacklist": { "scope": ["request", "response"], "names": ["X-Testing", "Y-Testing"] } }`) r, err := parse.FromJSON(msg) if err != nil { t.Fatalf("parse.FromJSON(): got %v, want no error", err) } req, err := http.NewRequest("GET", "http://martian.test", nil) if err != nil { t.Fatalf("http.NewRequest(): got %q, want no error", err) } req.Header.Set("X-Testing", "value") req.Header.Set("Y-Testing", "value") req.Header.Set("Z-Testing", "value") reqmod := r.RequestModifier() if reqmod == nil { t.Fatalf("reqmod: got nil, want not nil") } res := proxyutil.NewResponse(200, nil, req) res.Header.Set("X-Testing", "value") res.Header.Set("Y-Testing", "value") res.Header.Set("Z-Testing", "value") resmod := r.ResponseModifier() if resmod == nil { t.Fatalf("resmod: got nil, want not nil") } tt := []struct { header string want string }{ { header: "X-Testing", want: "", }, { header: "Y-Testing", want: "", }, { header: "Z-Testing", want: "value", }, } for i, tc := range tt { if err := reqmod.ModifyRequest(martian.NewContext(), req); err != nil { t.Fatalf("%d. reqmod.ModifyRequest(): got %v, want no error", i, err) } if got, want := req.Header.Get(tc.header), tc.want; got != want { t.Errorf("%d. req.Header.Get(%q): got %q, want %q", i, tc.header, got, want) } if err := resmod.ModifyResponse(martian.NewContext(), res); err != nil { t.Fatalf("%d. resmod.ModifyResponse(): got %v, want no error", i, err) } if got, want := res.Header.Get(tc.header), tc.want; got != want { t.Errorf("%d. res.Header.Get(%q): got %q, want %q", i, tc.header, got, want) } } }