golang.org/x/playground@v0.0.0-20230418134305-14ebe15bcd59/edit.go (about)

     1  // Copyright 2011 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 main
     6  
     7  import (
     8  	"fmt"
     9  	"html/template"
    10  	"net/http"
    11  	"runtime"
    12  	"strings"
    13  
    14  	"cloud.google.com/go/datastore"
    15  )
    16  
    17  const hostname = "play.golang.org"
    18  
    19  var editTemplate = template.Must(template.ParseFiles("edit.html"))
    20  
    21  type editData struct {
    22  	Snippet   *snippet
    23  	Share     bool
    24  	Analytics bool
    25  	GoVersion string
    26  	Gotip     bool
    27  	Examples  []example
    28  }
    29  
    30  func (s *server) handleEdit(w http.ResponseWriter, r *http.Request) {
    31  	w.Header().Set("Access-Control-Allow-Origin", "*")
    32  	if r.Method == "OPTIONS" {
    33  		// This is likely a pre-flight CORS request.
    34  		return
    35  	}
    36  
    37  	// Redirect foo.play.golang.org to play.golang.org.
    38  	if strings.HasSuffix(r.Host, "."+hostname) {
    39  		http.Redirect(w, r, "https://"+hostname, http.StatusFound)
    40  		return
    41  	}
    42  
    43  	// Serve 404 for /foo.
    44  	if r.URL.Path != "/" && !strings.HasPrefix(r.URL.Path, "/p/") {
    45  		http.NotFound(w, r)
    46  		return
    47  	}
    48  
    49  	snip := &snippet{Body: []byte(s.examples.hello())}
    50  	if strings.HasPrefix(r.URL.Path, "/p/") {
    51  		if !allowShare(r) {
    52  			w.WriteHeader(http.StatusUnavailableForLegalReasons)
    53  			w.Write([]byte(`<h1>Unavailable For Legal Reasons</h1><p>Viewing and/or sharing code snippets is not available in your country for legal reasons. This message might also appear if your country is misdetected. If you believe this is an error, please <a href="https://golang.org/issue">file an issue</a>.</p>`))
    54  			return
    55  		}
    56  		id := r.URL.Path[3:]
    57  		serveText := false
    58  		if strings.HasSuffix(id, ".go") {
    59  			id = id[:len(id)-3]
    60  			serveText = true
    61  		}
    62  
    63  		if err := s.db.GetSnippet(r.Context(), id, snip); err != nil {
    64  			if err != datastore.ErrNoSuchEntity {
    65  				s.log.Errorf("loading Snippet: %v", err)
    66  			}
    67  			http.Error(w, "Snippet not found", http.StatusNotFound)
    68  			return
    69  		}
    70  		if serveText {
    71  			if r.FormValue("download") == "true" {
    72  				w.Header().Set(
    73  					"Content-Disposition", fmt.Sprintf(`attachment; filename="%s.go"`, id),
    74  				)
    75  			}
    76  			w.Header().Set("Content-type", "text/plain; charset=utf-8")
    77  			w.Write(snip.Body)
    78  			return
    79  		}
    80  	}
    81  
    82  	if r.Host == hostname {
    83  		// The main playground is now on go.dev/play.
    84  		http.Redirect(w, r, "https://go.dev/play"+r.URL.Path, http.StatusFound)
    85  		return
    86  	}
    87  
    88  	w.Header().Set("Content-Type", "text/html; charset=utf-8")
    89  	data := &editData{
    90  		Snippet:   snip,
    91  		Share:     allowShare(r),
    92  		GoVersion: runtime.Version(),
    93  		Gotip:     s.gotip,
    94  		Examples:  s.examples.examples,
    95  	}
    96  	if err := editTemplate.Execute(w, data); err != nil {
    97  		s.log.Errorf("editTemplate.Execute(w, %+v): %v", data, err)
    98  		return
    99  	}
   100  }