Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(74)

Side by Side Diff: tools/chromeproxy_testserver/server.go

Issue 257663002: A Google AppEngine test server to facilitate chromeproxy Telemetry tests. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Test server to facilitate the data reduction proxy Telemetry tests.
2 //
3 // The server runs at http://chromeproxy-test.appspot.com/. Please contact
4 // people in OWNERS for server issues.
5 //
6 // For running an AppEngine Go server, see:
7 // https://developers.google.com/appengine/docs/go/gettingstarted/introduction.
8 //
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.
13 //
14 // For example, on receiving the query
15 // /default?respBody=bmV3IGJvZHk=&respHeader=eyJWaWEiOlsiVmlhMSIsIlZpYTIiXX0%3D& respStatus=204
16 // the server sends back a response with
17 // Status code: 204
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 .
21
22 package server
23
24 import (
25 "bytes"
26 "encoding/base64"
27 "encoding/json"
28 "errors"
29 "fmt"
30 "io"
31 "net/http"
32 "os"
33 "strconv"
34 )
35
36 func init() {
37 http.HandleFunc("/requestHeader", requestHeader)
38 http.HandleFunc("/resource", resource)
39 http.HandleFunc("/default", defaultResponse)
40 }
41
42 // requestHander returns request headers in response body as text.
43 func requestHeader(w http.ResponseWriter, r *http.Request) {
44 r.Header.Write(w)
45 }
46
47 // resource returns the content of a data file specified by "r=" query as the re sponse 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 {
53 return
54 }
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"))
59 return
60 }
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) ))
64 return
65 }
66 }
67
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)
73 if err != nil {
74 return
75 }
76 if !wroteBody {
77 w.Write([]byte("ok"))
78 }
79 }
80
81 type override struct {
82 status int
83 header http.Header
84 body io.Reader
85 }
86
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) {
93 q := r.URL.Query()
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)
97 if err != nil {
98 return nil, errors.New(fmt.Sprintf("respStatus: %v", err ))
99 }
100 resp.status = int(status)
101 }
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])
106 if err != nil {
107 return nil, errors.New(fmt.Sprintf("Decoding respHeader: %v", err))
108 }
109 var header http.Header
110 err = json.Unmarshal(headerValue, &header)
111 if err != nil {
112 return nil, errors.New(
113 fmt.Sprintf("Unmarlshal (%s) error: %v", string( headerValue), err))
114 }
115 resp.header = header
116 }
117 if v, ok := q["respBody"]; ok && len(v) == 1 && len(v[0]) > 0 {
118 body, err := base64.URLEncoding.DecodeString(v[0])
119 if err != nil {
120 return nil, errors.New(
121 fmt.Sprintf("Decoding respBody error: %v", err))
122 }
123 resp.body = bytes.NewBuffer(body)
124 }
125 return resp, nil
126 }
127
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)
132 if err != nil {
133 w.WriteHeader(http.StatusBadRequest)
134 w.Write([]byte(err.Error()))
135 return false, err
136 }
137 headers := w.Header()
138 if resp.header != nil {
139 for k, v := range resp.header {
140 headers[k] = v
141 }
142 }
143 if resp.status > 0 {
144 w.WriteHeader(resp.status)
145 }
146 if resp.body != nil {
147 _, err := io.Copy(w, resp.body)
148 return true, err
149 }
150 return false, nil
151 }
152
153 func writeFromFile(w io.Writer, filename string) (int64, error) {
154 f, err := os.Open(filename)
155 if err != nil {
156 return 0, err
157 }
158 return io.Copy(w, f)
159 }
OLDNEW
« no previous file with comments | « tools/chromeproxy_testserver/image/image1.png ('k') | tools/chromeproxy_testserver/server_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698