1 // Test server to facilitate the data reduction proxy Telemetry tests.
3 // The server runs at http://chromeproxy-test.appspot.com/. Please contact
4 // people in OWNERS for server issues.
6 // For running an AppEngine Go server, see:
7 // https://developers.google.com/appengine/docs/go/gettingstarted/introduction.
9 // The goal is to keep the test logic on the client side (Telemetry)
10 // as much as possible. This server will only return a resource
11 // and/or override the response as specified by the data encoded
12 // in the request URL queries.
14 // For example, on receiving the query
15 // /default?respBody=bmV3IGJvZHk=&respHeader=eyJWaWEiOlsiVmlhMSIsIlZpYTIiXX0%3D&respStatus=204
16 // the server sends back a response with
18 // Additional response headers: "Via: Via1" and "Via: Via2"
19 // Response body: "new body"
20 // where the overriding headers and body are base64 encoded in the request query.
37 http
.HandleFunc("/requestHeader", requestHeader
)
38 http
.HandleFunc("/resource", resource
)
39 http
.HandleFunc("/default", defaultResponse
)
42 // requestHander returns request headers in response body as text.
43 func requestHeader(w http
.ResponseWriter
, r
*http
.Request
) {
47 // resource returns the content of a data file specified by "r=" query as the response body.
48 // The response could be overridden by request queries.
49 // See parseOverrideQuery.
50 func resource(w http
.ResponseWriter
, r
*http
.Request
) {
51 wroteBody
, err
:= applyOverride(w
, r
)
52 if err
!= nil || wroteBody
{
55 path
, ok
:= r
.URL
.Query()["r"]
56 if !ok ||
len(path
) != 1 {
57 w
.WriteHeader(http
.StatusBadRequest
)
58 w
.Write([]byte("no resource in query"))
61 if _
, err
:= writeFromFile(w
, path
[0]); err
!= nil {
62 w
.WriteHeader(http
.StatusBadRequest
)
63 w
.Write([]byte(fmt
.Sprintf("Failed to get %s: %v", path
[0], err
)))
68 // defaultResponse returns "ok" as response body, if the body is not overridden.
69 // The response could be overridden by request queries.
70 // See parseOverrideQuery.
71 func defaultResponse(w http
.ResponseWriter
, r
*http
.Request
) {
72 wroteBody
, err
:= applyOverride(w
, r
)
81 type override
struct {
87 // parseOverrideQuery parses the queries in r and returns an override.
88 // It supports the following queries:
89 // "respStatus": an integer to override response status code;
90 // "respHeader": base64 encoded JSON data to override the response headers;
91 // "respBody": base64 encoded JSON data to override the response body.
92 func parseOverrideQuery(r
*http
.Request
) (*override
, error
) {
94 resp
:= &override
{0, nil, nil}
95 if v
, ok
:= q
["respStatus"]; ok
&& len(v
) == 1 && len(v
[0]) > 0 {
96 status
, err
:= strconv
.ParseInt(v
[0], 10, 0)
98 return nil, errors
.New(fmt
.Sprintf("respStatus: %v", err
))
100 resp
.status
= int(status
)
102 if v
, ok
:= q
["respHeader"]; ok
&& len(v
) == 1 && len(v
[0]) > 0 {
103 // Example header after base64 decoding:
104 // {"Via": ["Telemetry Test", "Test2"], "Name": ["XYZ"], "Cache-Control": ["public"]}
105 headerValue
, err
:= base64
.URLEncoding
.DecodeString(v
[0])
107 return nil, errors
.New(fmt
.Sprintf("Decoding respHeader: %v", err
))
109 var header http
.Header
110 err
= json
.Unmarshal(headerValue
, &header
)
112 return nil, errors
.New(
113 fmt
.Sprintf("Unmarlshal (%s) error: %v", string(headerValue
), err
))
117 if v
, ok
:= q
["respBody"]; ok
&& len(v
) == 1 && len(v
[0]) > 0 {
118 body
, err
:= base64
.URLEncoding
.DecodeString(v
[0])
120 return nil, errors
.New(
121 fmt
.Sprintf("Decoding respBody error: %v", err
))
123 resp
.body
= bytes
.NewBuffer(body
)
128 // applyOverride applies the override queries in r to w and returns whether the response
129 // body is overridden.
130 func applyOverride(w http
.ResponseWriter
, r
*http
.Request
) (wroteBody
bool, err error
) {
131 resp
, err
:= parseOverrideQuery(r
)
133 w
.WriteHeader(http
.StatusBadRequest
)
134 w
.Write([]byte(err
.Error()))
137 headers
:= w
.Header()
138 if resp
.header
!= nil {
139 for k
, v
:= range resp
.header
{
144 w
.WriteHeader(resp
.status
)
146 if resp
.body
!= nil {
147 _
, err
:= io
.Copy(w
, resp
.body
)
153 func writeFromFile(w io
.Writer
, filename
string) (int64, error
) {
154 f
, err
:= os
.Open(filename
)