Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201105173854-bc9fc8d8c4bc / playground / playground.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201105173854-bc9fc8d8c4bc/playground/playground.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201105173854-bc9fc8d8c4bc/playground/playground.go
new file mode 100644 (file)
index 0000000..14e9841
--- /dev/null
@@ -0,0 +1,90 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package playground registers HTTP handlers at "/compile" and "/share" that
+// proxy requests to the golang.org playground service.
+// This package may be used unaltered on App Engine Standard with Go 1.11+ runtime.
+package playground // import "golang.org/x/tools/playground"
+
+import (
+       "bytes"
+       "context"
+       "fmt"
+       "io"
+       "log"
+       "net/http"
+       "os"
+       "strings"
+       "time"
+
+       "golang.org/x/tools/godoc/golangorgenv"
+)
+
+const baseURL = "https://play.golang.org"
+
+func init() {
+       http.HandleFunc("/compile", bounce)
+       http.HandleFunc("/share", bounce)
+}
+
+func bounce(w http.ResponseWriter, r *http.Request) {
+       b := new(bytes.Buffer)
+       if err := passThru(b, r); os.IsPermission(err) {
+               http.Error(w, "403 Forbidden", http.StatusForbidden)
+               log.Println(err)
+               return
+       } else if err != nil {
+               http.Error(w, "500 Internal Server Error", http.StatusInternalServerError)
+               log.Println(err)
+               return
+       }
+       io.Copy(w, b)
+}
+
+func passThru(w io.Writer, req *http.Request) error {
+       if req.URL.Path == "/share" && googleCN(req) {
+               return os.ErrPermission
+       }
+       defer req.Body.Close()
+       url := baseURL + req.URL.Path
+       ctx, cancel := context.WithTimeout(req.Context(), 60*time.Second)
+       defer cancel()
+       r, err := post(ctx, url, req.Header.Get("Content-Type"), req.Body)
+       if err != nil {
+               return fmt.Errorf("making POST request: %v", err)
+       }
+       defer r.Body.Close()
+       if _, err := io.Copy(w, r.Body); err != nil {
+               return fmt.Errorf("copying response Body: %v", err)
+       }
+       return nil
+}
+
+func post(ctx context.Context, url, contentType string, body io.Reader) (*http.Response, error) {
+       req, err := http.NewRequest(http.MethodPost, url, body)
+       if err != nil {
+               return nil, fmt.Errorf("http.NewRequest: %v", err)
+       }
+       req.Header.Set("Content-Type", contentType)
+       return http.DefaultClient.Do(req.WithContext(ctx))
+}
+
+// googleCN reports whether request r is considered
+// to be served from golang.google.cn.
+func googleCN(r *http.Request) bool {
+       if r.FormValue("googlecn") != "" {
+               return true
+       }
+       if strings.HasSuffix(r.Host, ".cn") {
+               return true
+       }
+       if !golangorgenv.CheckCountry() {
+               return false
+       }
+       switch r.Header.Get("X-Appengine-Country") {
+       case "", "ZZ", "CN":
+               return true
+       }
+       return false
+}