...
1
2
3
4
5
6
7
8 package playground
9
10 import (
11 "bytes"
12 "context"
13 "fmt"
14 "io"
15 "log"
16 "net/http"
17 "time"
18 )
19
20 const baseURL = "https://play.golang.org"
21
22 func init() {
23 http.Handle("/compile", Proxy())
24 }
25
26
27
28
29
30
31
32
33
34
35 func Proxy() http.Handler {
36 return http.HandlerFunc(bounce)
37 }
38
39 func bounce(w http.ResponseWriter, r *http.Request) {
40 b := new(bytes.Buffer)
41 if err := passThru(b, r); err != nil {
42 http.Error(w, "500 Internal Server Error", http.StatusInternalServerError)
43 log.Println(err)
44 return
45 }
46 io.Copy(w, b)
47 }
48
49 func passThru(w io.Writer, req *http.Request) error {
50 defer req.Body.Close()
51 url := baseURL + req.URL.Path
52 ctx, cancel := context.WithTimeout(req.Context(), 60*time.Second)
53 defer cancel()
54 r, err := post(ctx, url, req.Header.Get("Content-Type"), req.Body)
55 if err != nil {
56 return fmt.Errorf("making POST request: %v", err)
57 }
58 defer r.Body.Close()
59 if _, err := io.Copy(w, r.Body); err != nil {
60 return fmt.Errorf("copying response Body: %v", err)
61 }
62 return nil
63 }
64
65 func post(ctx context.Context, url, contentType string, body io.Reader) (*http.Response, error) {
66 req, err := http.NewRequest(http.MethodPost, url, body)
67 if err != nil {
68 return nil, fmt.Errorf("http.NewRequest: %v", err)
69 }
70 req.Header.Set("Content-Type", contentType)
71 return http.DefaultClient.Do(req.WithContext(ctx))
72 }
73
View as plain text