github.com/google/martian/v3@v3.3.3/messageview/messageview_test.go (about)

     1  // Copyright 2015 Google Inc. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package messageview
    16  
    17  import (
    18  	"bufio"
    19  	"bytes"
    20  	"compress/flate"
    21  	"compress/gzip"
    22  	"io"
    23  	"io/ioutil"
    24  	"net/http"
    25  	"strings"
    26  	"testing"
    27  
    28  	"github.com/google/martian/v3/proxyutil"
    29  )
    30  
    31  func TestRequestViewHeadersOnly(t *testing.T) {
    32  	body := strings.NewReader("body content")
    33  	req, err := http.NewRequest("GET", "http://example.com/path?k=v", body)
    34  	if err != nil {
    35  		t.Fatalf("http.NewRequest(): got %v, want no error", err)
    36  	}
    37  	req.ContentLength = int64(body.Len())
    38  	req.Header.Set("Request-Header", "true")
    39  
    40  	mv := New()
    41  	mv.SkipBody(true)
    42  	if err := mv.SnapshotRequest(req); err != nil {
    43  		t.Fatalf("SnapshotRequest(): got %v, want no error", err)
    44  	}
    45  
    46  	got, err := ioutil.ReadAll(mv.HeaderReader())
    47  	if err != nil {
    48  		t.Fatalf("ioutil.ReadAll(mv.HeaderReader()): got %v, want no error", err)
    49  	}
    50  
    51  	hdrwant := "GET http://example.com/path?k=v HTTP/1.1\r\n" +
    52  		"Host: example.com\r\n" +
    53  		"Content-Length: 12\r\n" +
    54  		"Request-Header: true\r\n\r\n"
    55  
    56  	if !bytes.Equal(got, []byte(hdrwant)) {
    57  		t.Fatalf("mv.HeaderReader(): got %q, want %q", got, hdrwant)
    58  	}
    59  
    60  	br, err := mv.BodyReader()
    61  	if err != nil {
    62  		t.Fatalf("mv.BodyReader(): got %v, want no error", err)
    63  	}
    64  
    65  	if _, err := br.Read(nil); err != io.EOF {
    66  		t.Fatalf("ioutil.ReadAll(mv.BodyReader()): got %v, want io.EOF", err)
    67  	}
    68  
    69  	r, err := mv.Reader()
    70  	if err != nil {
    71  		t.Fatalf("mv.Reader(): got %v, want no error", err)
    72  	}
    73  	got, err = ioutil.ReadAll(r)
    74  	if err != nil {
    75  		t.Fatalf("ioutil.ReadAll(mv.Reader()): got %v, want no error", err)
    76  	}
    77  
    78  	if want := []byte(hdrwant); !bytes.Equal(got, want) {
    79  		t.Fatalf("mv.Read(): got %q, want %q", got, want)
    80  	}
    81  }
    82  
    83  func TestRequestView(t *testing.T) {
    84  	body := strings.NewReader("body content")
    85  	req, err := http.NewRequest("GET", "http://example.com/path?k=v", body)
    86  	if err != nil {
    87  		t.Fatalf("http.NewRequest(): got %v, want no error", err)
    88  	}
    89  	req.Header.Set("Request-Header", "true")
    90  
    91  	// Force Content Length to be unset to simulate lack of Content-Length and
    92  	// Transfer-Encoding which is valid.
    93  	req.ContentLength = -1
    94  
    95  	mv := New()
    96  	if err := mv.SnapshotRequest(req); err != nil {
    97  		t.Fatalf("SnapshotRequest(): got %v, want no error", err)
    98  	}
    99  
   100  	got, err := ioutil.ReadAll(mv.HeaderReader())
   101  	if err != nil {
   102  		t.Fatalf("ioutil.ReadAll(mv.HeaderReader()): got %v, want no error", err)
   103  	}
   104  
   105  	hdrwant := "GET http://example.com/path?k=v HTTP/1.1\r\n" +
   106  		"Host: example.com\r\n" +
   107  		"Request-Header: true\r\n\r\n"
   108  
   109  	if !bytes.Equal(got, []byte(hdrwant)) {
   110  		t.Fatalf("mv.HeaderReader(): got %q, want %q", got, hdrwant)
   111  	}
   112  
   113  	br, err := mv.BodyReader()
   114  	if err != nil {
   115  		t.Fatalf("mv.BodyReader(): got %v, want no error", err)
   116  	}
   117  
   118  	got, err = ioutil.ReadAll(br)
   119  	if err != nil {
   120  		t.Fatalf("ioutil.ReadAll(mv.BodyReader()): got %v, want no error", err)
   121  	}
   122  
   123  	bodywant := "body content"
   124  	if !bytes.Equal(got, []byte(bodywant)) {
   125  		t.Fatalf("mv.BodyReader(): got %q, want %q", got, bodywant)
   126  	}
   127  
   128  	r, err := mv.Reader()
   129  	if err != nil {
   130  		t.Fatalf("mv.Reader(): got %v, want no error", err)
   131  	}
   132  	got, err = ioutil.ReadAll(r)
   133  	if err != nil {
   134  		t.Fatalf("ioutil.ReadAll(mv.Reader()): got %v, want no error", err)
   135  	}
   136  
   137  	if want := []byte(hdrwant + bodywant); !bytes.Equal(got, want) {
   138  		t.Fatalf("mv.Read(): got %q, want %q", got, want)
   139  	}
   140  
   141  	// Sanity check to ensure it still parses.
   142  	if _, err := http.ReadRequest(bufio.NewReader(bytes.NewReader(got))); err != nil {
   143  		t.Fatalf("http.ReadRequest(): got %v, want no error", err)
   144  	}
   145  }
   146  
   147  func TestRequestViewSkipBodyUnlessContentType(t *testing.T) {
   148  	req, err := http.NewRequest("GET", "http://example.com", strings.NewReader("body content"))
   149  	if err != nil {
   150  		t.Fatalf("http.NewRequest(): got %v, want no error", err)
   151  	}
   152  	req.ContentLength = 12
   153  	req.Header.Set("Content-Type", "text/plain; charset=utf-8")
   154  
   155  	mv := New()
   156  	mv.SkipBodyUnlessContentType("text/plain")
   157  	if err := mv.SnapshotRequest(req); err != nil {
   158  		t.Fatalf("SnapshotRequest(): got %v, want no error", err)
   159  	}
   160  
   161  	br, err := mv.BodyReader()
   162  	if err != nil {
   163  		t.Fatalf("mv.BodyReader(): got %v, want no error", err)
   164  	}
   165  
   166  	got, err := ioutil.ReadAll(br)
   167  	if err != nil {
   168  		t.Fatalf("ioutil.ReadAll(mv.BodyReader()): got %v, want no error", err)
   169  	}
   170  
   171  	bodywant := "body content"
   172  	if !bytes.Equal(got, []byte(bodywant)) {
   173  		t.Fatalf("mv.BodyReader(): got %q, want %q", got, bodywant)
   174  	}
   175  
   176  	req.Header.Set("Content-Type", "image/png")
   177  	mv = New()
   178  	mv.SkipBodyUnlessContentType("text/plain")
   179  	if err := mv.SnapshotRequest(req); err != nil {
   180  		t.Fatalf("SnapshotRequest(): got %v, want no error", err)
   181  	}
   182  
   183  	br, err = mv.BodyReader()
   184  	if err != nil {
   185  		t.Fatalf("mv.BodyReader(): got %v, want no error", err)
   186  	}
   187  
   188  	if _, err := br.Read(nil); err != io.EOF {
   189  		t.Fatalf("br.Read(): got %v, want io.EOF", err)
   190  	}
   191  }
   192  
   193  func TestRequestViewChunkedTransferEncoding(t *testing.T) {
   194  	req, err := http.NewRequest("GET", "http://example.com/path?k=v", strings.NewReader("body content"))
   195  	if err != nil {
   196  		t.Fatalf("http.NewRequest(): got %v, want no error", err)
   197  	}
   198  	req.TransferEncoding = []string{"chunked"}
   199  	req.Header.Set("Trailer", "Trailer-Header")
   200  	req.Trailer = http.Header{
   201  		"Trailer-Header": []string{"true"},
   202  	}
   203  
   204  	mv := New()
   205  	if err := mv.SnapshotRequest(req); err != nil {
   206  		t.Fatalf("SnapshotRequest(): got %v, want no error", err)
   207  	}
   208  
   209  	got, err := ioutil.ReadAll(mv.HeaderReader())
   210  	if err != nil {
   211  		t.Fatalf("ioutil.ReadAll(mv.HeaderReader()): got %v, want no error", err)
   212  	}
   213  
   214  	hdrwant := "GET http://example.com/path?k=v HTTP/1.1\r\n" +
   215  		"Host: example.com\r\n" +
   216  		"Transfer-Encoding: chunked\r\n" +
   217  		"Trailer: Trailer-Header\r\n\r\n"
   218  
   219  	if !bytes.Equal(got, []byte(hdrwant)) {
   220  		t.Fatalf("mv.HeaderReader(): got %q, want %q", got, hdrwant)
   221  	}
   222  
   223  	br, err := mv.BodyReader()
   224  	if err != nil {
   225  		t.Fatalf("mv.BodyReader(): got %v, want no error", err)
   226  	}
   227  
   228  	got, err = ioutil.ReadAll(br)
   229  	if err != nil {
   230  		t.Fatalf("ioutil.ReadAll(mv.BodyReader()): got %v, want no error", err)
   231  	}
   232  
   233  	bodywant := "c\r\nbody content\r\n0\r\n"
   234  	if !bytes.Equal(got, []byte(bodywant)) {
   235  		t.Fatalf("mv.BodyReader(): got %q, want %q", got, bodywant)
   236  	}
   237  
   238  	got, err = ioutil.ReadAll(mv.TrailerReader())
   239  	if err != nil {
   240  		t.Fatalf("ioutil.ReadAll(mv.TrailerReader()): got %v, want no error", err)
   241  	}
   242  
   243  	trailerwant := "Trailer-Header: true\r\n"
   244  	if !bytes.Equal(got, []byte(trailerwant)) {
   245  		t.Fatalf("mv.TrailerReader(): got %q, want %q", got, trailerwant)
   246  	}
   247  
   248  	r, err := mv.Reader()
   249  	if err != nil {
   250  		t.Fatalf("mv.Reader(): got %v, want no error", err)
   251  	}
   252  	got, err = ioutil.ReadAll(r)
   253  	if err != nil {
   254  		t.Fatalf("ioutil.ReadAll(mv.Reader()): got %v, want no error", err)
   255  	}
   256  
   257  	if want := []byte(hdrwant + bodywant + trailerwant); !bytes.Equal(got, want) {
   258  		t.Fatalf("mv.Read(): got %q, want %q", got, want)
   259  	}
   260  
   261  	// Sanity check to ensure it still parses.
   262  	if _, err := http.ReadRequest(bufio.NewReader(bytes.NewReader(got))); err != nil {
   263  		t.Fatalf("http.ReadRequest(): got %v, want no error", err)
   264  	}
   265  }
   266  
   267  func TestRequestViewDecodeGzipContentEncoding(t *testing.T) {
   268  	body := new(bytes.Buffer)
   269  	gw := gzip.NewWriter(body)
   270  	gw.Write([]byte("body content"))
   271  	gw.Flush()
   272  	gw.Close()
   273  
   274  	req, err := http.NewRequest("GET", "http://example.com/path?k=v", body)
   275  	if err != nil {
   276  		t.Fatalf("http.NewRequest(): got %v, want no error", err)
   277  	}
   278  	req.TransferEncoding = []string{"chunked"}
   279  	req.Header.Set("Content-Encoding", "gzip")
   280  
   281  	mv := New()
   282  	if err := mv.SnapshotRequest(req); err != nil {
   283  		t.Fatalf("SnapshotRequest(): got %v, want no error", err)
   284  	}
   285  
   286  	got, err := ioutil.ReadAll(mv.HeaderReader())
   287  	if err != nil {
   288  		t.Fatalf("ioutil.ReadAll(mv.HeaderReader()): got %v, want no error", err)
   289  	}
   290  
   291  	hdrwant := "GET http://example.com/path?k=v HTTP/1.1\r\n" +
   292  		"Host: example.com\r\n" +
   293  		"Transfer-Encoding: chunked\r\n" +
   294  		"Content-Encoding: gzip\r\n\r\n"
   295  
   296  	if !bytes.Equal(got, []byte(hdrwant)) {
   297  		t.Fatalf("mv.HeaderReader(): got %q, want %q", got, hdrwant)
   298  	}
   299  
   300  	br, err := mv.BodyReader(Decode())
   301  	if err != nil {
   302  		t.Fatalf("mv.BodyReader(): got %v, want no error", err)
   303  	}
   304  
   305  	got, err = ioutil.ReadAll(br)
   306  	if err != nil {
   307  		t.Fatalf("ioutil.ReadAll(mv.BodyReader()): got %v, wt o error", err)
   308  	}
   309  
   310  	bodywant := "body content"
   311  
   312  	if !bytes.Equal(got, []byte(bodywant)) {
   313  		t.Fatalf("mv.BodyReader(): got %q, want %q", got, bodywant)
   314  	}
   315  
   316  	r, err := mv.Reader(Decode())
   317  	if err != nil {
   318  		t.Fatalf("mv.Reader(): got %v, want no error", err)
   319  	}
   320  	got, err = ioutil.ReadAll(r)
   321  	if err != nil {
   322  		t.Fatalf("ioutil.ReadAll(mv.Reader()): got %v, want no error", err)
   323  	}
   324  
   325  	if want := []byte(hdrwant + bodywant + "\r\n"); !bytes.Equal(got, want) {
   326  		t.Fatalf("mv.Read(): got %q, want %q", got, want)
   327  	}
   328  }
   329  
   330  func TestRequestViewDecodeDeflateContentEncoding(t *testing.T) {
   331  	body := new(bytes.Buffer)
   332  	dw, err := flate.NewWriter(body, -1)
   333  	if err != nil {
   334  		t.Fatalf("flate.NewWriter(): got %v, want no error", err)
   335  	}
   336  	dw.Write([]byte("body content"))
   337  	dw.Flush()
   338  	dw.Close()
   339  
   340  	req, err := http.NewRequest("GET", "http://example.com/path?k=v", body)
   341  	if err != nil {
   342  		t.Fatalf("http.NewRequest(): got %v, want no error", err)
   343  	}
   344  	req.TransferEncoding = []string{"chunked"}
   345  	req.Header.Set("Content-Encoding", "deflate")
   346  
   347  	mv := New()
   348  	if err := mv.SnapshotRequest(req); err != nil {
   349  		t.Fatalf("SnapshotRequest(): got %v, want no error", err)
   350  	}
   351  
   352  	got, err := ioutil.ReadAll(mv.HeaderReader())
   353  	if err != nil {
   354  		t.Fatalf("ioutil.ReadAll(mv.HeaderReader()): got %v, want no error", err)
   355  	}
   356  
   357  	hdrwant := "GET http://example.com/path?k=v HTTP/1.1\r\n" +
   358  		"Host: example.com\r\n" +
   359  		"Transfer-Encoding: chunked\r\n" +
   360  		"Content-Encoding: deflate\r\n\r\n"
   361  
   362  	if !bytes.Equal(got, []byte(hdrwant)) {
   363  		t.Fatalf("mv.HeaderReader(): got %q, want %q", got, hdrwant)
   364  	}
   365  
   366  	br, err := mv.BodyReader(Decode())
   367  	if err != nil {
   368  		t.Fatalf("mv.BodyReader(): got %v, want no error", err)
   369  	}
   370  
   371  	got, err = ioutil.ReadAll(br)
   372  	if err != nil {
   373  		t.Fatalf("ioutil.ReadAll(mv.BodyReader()): got %v, want no error", err)
   374  	}
   375  
   376  	bodywant := "body content"
   377  
   378  	if !bytes.Equal(got, []byte(bodywant)) {
   379  		t.Fatalf("mv.BodyReader(): got %q, want %q", got, bodywant)
   380  	}
   381  
   382  	r, err := mv.Reader(Decode())
   383  	if err != nil {
   384  		t.Fatalf("mv.Reader(): got %v, want no error", err)
   385  	}
   386  	got, err = ioutil.ReadAll(r)
   387  	if err != nil {
   388  		t.Fatalf("ioutil.ReadAll(mv.Reader()): got %v, want no error", err)
   389  	}
   390  
   391  	if want := []byte(hdrwant + bodywant + "\r\n"); !bytes.Equal(got, want) {
   392  		t.Fatalf("mv.Read(): got %q, want %q", got, want)
   393  	}
   394  }
   395  
   396  func TestResponseViewHeadersOnly(t *testing.T) {
   397  	body := strings.NewReader("body content")
   398  	res := proxyutil.NewResponse(200, body, nil)
   399  	res.ContentLength = 12
   400  	res.Header.Set("Response-Header", "true")
   401  
   402  	mv := New()
   403  	mv.SkipBody(true)
   404  	if err := mv.SnapshotResponse(res); err != nil {
   405  		t.Fatalf("SnapshotResponse(): got %v, want no error", err)
   406  	}
   407  
   408  	got, err := ioutil.ReadAll(mv.HeaderReader())
   409  	if err != nil {
   410  		t.Fatalf("ioutil.ReadAll(mv.HeaderReader()): got %v, want no error", err)
   411  	}
   412  
   413  	hdrwant := "HTTP/1.1 200 OK\r\n" +
   414  		"Content-Length: 12\r\n" +
   415  		"Response-Header: true\r\n\r\n"
   416  
   417  	if !bytes.Equal(got, []byte(hdrwant)) {
   418  		t.Fatalf("mv.HeaderReader(): got %q, want %q", got, hdrwant)
   419  	}
   420  
   421  	br, err := mv.BodyReader()
   422  	if err != nil {
   423  		t.Fatalf("mv.BodyReader(): got %v, want no error", err)
   424  	}
   425  
   426  	if _, err := br.Read(nil); err != io.EOF {
   427  		t.Fatalf("ioutil.ReadAll(mv.BodyReader()): got %v, want io.EOF", err)
   428  	}
   429  
   430  	r, err := mv.Reader()
   431  	if err != nil {
   432  		t.Fatalf("mv.Reader(): got %v, want no error", err)
   433  	}
   434  	got, err = ioutil.ReadAll(r)
   435  	if err != nil {
   436  		t.Fatalf("ioutil.ReadAll(mv.Reader()): got %v, want no error", err)
   437  	}
   438  
   439  	if want := []byte(hdrwant); !bytes.Equal(got, want) {
   440  		t.Fatalf("mv.Read(): got %q, want %q", got, want)
   441  	}
   442  }
   443  
   444  func TestResponseView(t *testing.T) {
   445  	body := strings.NewReader("body content")
   446  	res := proxyutil.NewResponse(200, body, nil)
   447  	res.ContentLength = 12
   448  	res.Header.Set("Response-Header", "true")
   449  
   450  	mv := New()
   451  	if err := mv.SnapshotResponse(res); err != nil {
   452  		t.Fatalf("SnapshotResponse(): got %v, want no error", err)
   453  	}
   454  
   455  	got, err := ioutil.ReadAll(mv.HeaderReader())
   456  	if err != nil {
   457  		t.Fatalf("ioutil.ReadAll(mv.HeaderReader()): got %v, want no error", err)
   458  	}
   459  
   460  	hdrwant := "HTTP/1.1 200 OK\r\n" +
   461  		"Content-Length: 12\r\n" +
   462  		"Response-Header: true\r\n\r\n"
   463  
   464  	if !bytes.Equal(got, []byte(hdrwant)) {
   465  		t.Fatalf("mv.HeaderReader(): got %q, want %q", got, hdrwant)
   466  	}
   467  
   468  	br, err := mv.BodyReader()
   469  	if err != nil {
   470  		t.Fatalf("mv.BodyReader(): got %v, want no error", err)
   471  	}
   472  
   473  	got, err = ioutil.ReadAll(br)
   474  	if err != nil {
   475  		t.Fatalf("ioutil.ReadAll(mv.BodyReader()): got %v, want no error", err)
   476  	}
   477  
   478  	bodywant := "body content"
   479  	if !bytes.Equal(got, []byte(bodywant)) {
   480  		t.Fatalf("mv.BodyReader(): got %q, want %q", got, bodywant)
   481  	}
   482  
   483  	r, err := mv.Reader()
   484  	if err != nil {
   485  		t.Fatalf("mv.Reader(): got %v, want no error", err)
   486  	}
   487  	got, err = ioutil.ReadAll(r)
   488  	if err != nil {
   489  		t.Fatalf("ioutil.ReadAll(mv.Reader()): got %v, want no error", err)
   490  	}
   491  
   492  	if want := []byte(hdrwant + bodywant); !bytes.Equal(got, want) {
   493  		t.Fatalf("mv.Read(): got %q, want %q", got, want)
   494  	}
   495  
   496  	// Sanity check to ensure it still parses.
   497  	if _, err := http.ReadResponse(bufio.NewReader(bytes.NewReader(got)), nil); err != nil {
   498  		t.Fatalf("http.ReadResponse(): got %v, want no error", err)
   499  	}
   500  }
   501  
   502  func TestResponseViewSkipBodyUnlessContentType(t *testing.T) {
   503  	res := proxyutil.NewResponse(200, strings.NewReader("body content"), nil)
   504  	res.ContentLength = 12
   505  	res.Header.Set("Content-Type", "text/plain; charset=utf-8")
   506  
   507  	mv := New()
   508  	mv.SkipBodyUnlessContentType("text/plain")
   509  	if err := mv.SnapshotResponse(res); err != nil {
   510  		t.Fatalf("SnapshotResponse(): got %v, want no error", err)
   511  	}
   512  
   513  	br, err := mv.BodyReader()
   514  	if err != nil {
   515  		t.Fatalf("mv.BodyReader(): got %v, want no error", err)
   516  	}
   517  
   518  	got, err := ioutil.ReadAll(br)
   519  	if err != nil {
   520  		t.Fatalf("ioutil.ReadAll(mv.BodyReader()): got %v, want no error", err)
   521  	}
   522  
   523  	bodywant := "body content"
   524  	if !bytes.Equal(got, []byte(bodywant)) {
   525  		t.Fatalf("mv.BodyReader(): got %q, want %q", got, bodywant)
   526  	}
   527  
   528  	res.Header.Set("Content-Type", "image/png")
   529  	mv = New()
   530  	mv.SkipBodyUnlessContentType("text/plain")
   531  	if err := mv.SnapshotResponse(res); err != nil {
   532  		t.Fatalf("SnapshotResponse(): got %v, want no error", err)
   533  	}
   534  
   535  	br, err = mv.BodyReader()
   536  	if err != nil {
   537  		t.Fatalf("mv.BodyReader(): got %v, want no error", err)
   538  	}
   539  
   540  	if _, err := br.Read(nil); err != io.EOF {
   541  		t.Fatalf("br.Read(): got %v, want io.EOF", err)
   542  	}
   543  }
   544  
   545  func TestResponseViewChunkedTransferEncoding(t *testing.T) {
   546  	body := strings.NewReader("body content")
   547  	res := proxyutil.NewResponse(200, body, nil)
   548  	res.TransferEncoding = []string{"chunked"}
   549  	res.Header.Set("Trailer", "Trailer-Header")
   550  	res.Trailer = http.Header{
   551  		"Trailer-Header": []string{"true"},
   552  	}
   553  
   554  	mv := New()
   555  	if err := mv.SnapshotResponse(res); err != nil {
   556  		t.Fatalf("SnapshotResponse(): got %v, want no error", err)
   557  	}
   558  
   559  	got, err := ioutil.ReadAll(mv.HeaderReader())
   560  	if err != nil {
   561  		t.Fatalf("ioutil.ReadAll(mv.HeaderReader()): got %v, want no error", err)
   562  	}
   563  
   564  	hdrwant := "HTTP/1.1 200 OK\r\n" +
   565  		"Transfer-Encoding: chunked\r\n" +
   566  		"Trailer: Trailer-Header\r\n\r\n"
   567  
   568  	if !bytes.Equal(got, []byte(hdrwant)) {
   569  		t.Fatalf("mv.HeaderReader(): got %q, want %q", got, hdrwant)
   570  	}
   571  
   572  	br, err := mv.BodyReader()
   573  	if err != nil {
   574  		t.Fatalf("mv.BodyReader(): got %v, want no error", err)
   575  	}
   576  
   577  	got, err = ioutil.ReadAll(br)
   578  	if err != nil {
   579  		t.Fatalf("ioutil.ReadAll(mv.BodyReader()): got %v, want no error", err)
   580  	}
   581  
   582  	bodywant := "c\r\nbody content\r\n0\r\n"
   583  	if !bytes.Equal(got, []byte(bodywant)) {
   584  		t.Fatalf("mv.BodyReader(): got %q, want %q", got, bodywant)
   585  	}
   586  
   587  	got, err = ioutil.ReadAll(mv.TrailerReader())
   588  	if err != nil {
   589  		t.Fatalf("ioutil.ReadAll(mv.TrailerReader()): got %v, want no error", err)
   590  	}
   591  
   592  	trailerwant := "Trailer-Header: true\r\n"
   593  	if !bytes.Equal(got, []byte(trailerwant)) {
   594  		t.Fatalf("mv.TrailerReader(): got %q, want %q", got, trailerwant)
   595  	}
   596  
   597  	r, err := mv.Reader()
   598  	if err != nil {
   599  		t.Fatalf("mv.Reader(): got %v, want no error", err)
   600  	}
   601  	got, err = ioutil.ReadAll(r)
   602  	if err != nil {
   603  		t.Fatalf("ioutil.ReadAll(mv.Reader()): got %v, want no error", err)
   604  	}
   605  
   606  	if want := []byte(hdrwant + bodywant + trailerwant); !bytes.Equal(got, want) {
   607  		t.Fatalf("mv.Read(): got %q, want %q", got, want)
   608  	}
   609  
   610  	// Sanity check to ensure it still parses.
   611  	if _, err := http.ReadResponse(bufio.NewReader(bytes.NewReader(got)), nil); err != nil {
   612  		t.Fatalf("http.ReadResponse(): got %v, want no error", err)
   613  	}
   614  }
   615  
   616  func TestResponseViewDecodeGzipContentEncoding(t *testing.T) {
   617  	body := new(bytes.Buffer)
   618  	gw := gzip.NewWriter(body)
   619  	gw.Write([]byte("body content"))
   620  	gw.Flush()
   621  	gw.Close()
   622  
   623  	res := proxyutil.NewResponse(200, body, nil)
   624  	res.TransferEncoding = []string{"chunked"}
   625  	res.Header.Set("Content-Encoding", "gzip")
   626  
   627  	mv := New()
   628  	if err := mv.SnapshotResponse(res); err != nil {
   629  		t.Fatalf("SnapshotResponse(): got %v, want no error", err)
   630  	}
   631  
   632  	got, err := ioutil.ReadAll(mv.HeaderReader())
   633  	if err != nil {
   634  		t.Fatalf("ioutil.ReadAll(mv.HeaderReader()): got %v, want no error", err)
   635  	}
   636  
   637  	hdrwant := "HTTP/1.1 200 OK\r\n" +
   638  		"Transfer-Encoding: chunked\r\n" +
   639  		"Content-Encoding: gzip\r\n\r\n"
   640  
   641  	if !bytes.Equal(got, []byte(hdrwant)) {
   642  		t.Fatalf("mv.HeaderReader(): got %q, want %q", got, hdrwant)
   643  	}
   644  
   645  	br, err := mv.BodyReader(Decode())
   646  	if err != nil {
   647  		t.Fatalf("mv.BodyReader(): got %v, want no error", err)
   648  	}
   649  
   650  	got, err = ioutil.ReadAll(br)
   651  	if err != nil {
   652  		t.Fatalf("ioutil.ReadAll(mv.BodyReader()): got %v, wt o error", err)
   653  	}
   654  
   655  	bodywant := "body content"
   656  
   657  	if !bytes.Equal(got, []byte(bodywant)) {
   658  		t.Fatalf("mv.BodyReader(): got %q, want %q", got, bodywant)
   659  	}
   660  
   661  	r, err := mv.Reader(Decode())
   662  	if err != nil {
   663  		t.Fatalf("mv.Reader(): got %v, want no error", err)
   664  	}
   665  	got, err = ioutil.ReadAll(r)
   666  	if err != nil {
   667  		t.Fatalf("ioutil.ReadAll(mv.Reader()): got %v, want no error", err)
   668  	}
   669  
   670  	if want := []byte(hdrwant + bodywant + "\r\n"); !bytes.Equal(got, want) {
   671  		t.Fatalf("mv.Read(): got %q, want %q", got, want)
   672  	}
   673  }
   674  
   675  func TestResponseViewDecodeGzipContentEncodingPartial(t *testing.T) {
   676  	bodywant := "partial content"
   677  	res := proxyutil.NewResponse(206, strings.NewReader(bodywant), nil)
   678  	res.TransferEncoding = []string{"chunked"}
   679  	res.Header.Set("Content-Encoding", "gzip")
   680  
   681  	mv := New()
   682  	if err := mv.SnapshotResponse(res); err != nil {
   683  		t.Fatalf("SnapshotResponse(): got %v, want no error", err)
   684  	}
   685  	br, err := mv.BodyReader(Decode())
   686  	if err != nil {
   687  		t.Fatalf("mv.BodyReader(): got %v, want no error", err)
   688  	}
   689  
   690  	got, err := ioutil.ReadAll(br)
   691  	if err != nil {
   692  		t.Fatalf("ioutil.ReadAll(mv.BodyReader()): got %v, wt o error", err)
   693  	}
   694  	if !bytes.Equal(got, []byte(bodywant)) {
   695  		t.Fatalf("mv.BodyReader(): got %q, want %q", got, bodywant)
   696  	}
   697  }
   698  
   699  func TestResponseViewDecodeDeflateContentEncoding(t *testing.T) {
   700  	body := new(bytes.Buffer)
   701  	dw, err := flate.NewWriter(body, -1)
   702  	if err != nil {
   703  		t.Fatalf("flate.NewWriter(): got %v, want no error", err)
   704  	}
   705  	dw.Write([]byte("body content"))
   706  	dw.Flush()
   707  	dw.Close()
   708  
   709  	res := proxyutil.NewResponse(200, body, nil)
   710  	res.TransferEncoding = []string{"chunked"}
   711  	res.Header.Set("Content-Encoding", "deflate")
   712  
   713  	mv := New()
   714  	if err := mv.SnapshotResponse(res); err != nil {
   715  		t.Fatalf("SnapshotResponse(): got %v, want no error", err)
   716  	}
   717  
   718  	got, err := ioutil.ReadAll(mv.HeaderReader())
   719  	if err != nil {
   720  		t.Fatalf("ioutil.ReadAll(mv.HeaderReader()): got %v, want no error", err)
   721  	}
   722  
   723  	hdrwant := "HTTP/1.1 200 OK\r\n" +
   724  		"Transfer-Encoding: chunked\r\n" +
   725  		"Content-Encoding: deflate\r\n\r\n"
   726  
   727  	if !bytes.Equal(got, []byte(hdrwant)) {
   728  		t.Fatalf("mv.HeaderReader(): got %q, want %q", got, hdrwant)
   729  	}
   730  
   731  	br, err := mv.BodyReader(Decode())
   732  	if err != nil {
   733  		t.Fatalf("mv.BodyReader(): got %v, want no error", err)
   734  	}
   735  
   736  	got, err = ioutil.ReadAll(br)
   737  	if err != nil {
   738  		t.Fatalf("ioutil.ReadAll(mv.BodyReader()): got %v, wt o error", err)
   739  	}
   740  
   741  	bodywant := "body content"
   742  
   743  	if !bytes.Equal(got, []byte(bodywant)) {
   744  		t.Fatalf("mv.BodyReader(): got %q, want %q", got, bodywant)
   745  	}
   746  
   747  	r, err := mv.Reader(Decode())
   748  	if err != nil {
   749  		t.Fatalf("mv.Reader(): got %v, want no error", err)
   750  	}
   751  	got, err = ioutil.ReadAll(r)
   752  	if err != nil {
   753  		t.Fatalf("ioutil.ReadAll(mv.Reader()): got %v, want no error", err)
   754  	}
   755  
   756  	if want := []byte(hdrwant + bodywant + "\r\n"); !bytes.Equal(got, want) {
   757  		t.Fatalf("mv.Read(): got %q, want %q", got, want)
   758  	}
   759  }