...

Source file src/golang.org/x/tools/playground/playground.go

Documentation: golang.org/x/tools/playground

     1  // Copyright 2013 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package playground registers an HTTP handler at "/compile" that
     6  // proxies requests to the golang.org playground service.
     7  // This package may be used unaltered on App Engine Standard with Go 1.11+ runtime.
     8  package playground // import "golang.org/x/tools/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  // Proxy returns a handler that can be registered on /compile to proxy requests to the Go playground.
    27  //
    28  // This package already contains a func init that does:
    29  //
    30  //	func init() {
    31  //		http.Handle("/compile", Proxy())
    32  //	}
    33  //
    34  // Proxy may be useful for servers that use HTTP muxes other than the default mux.
    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