-
-
Notifications
You must be signed in to change notification settings - Fork 8
/
goplay.go
128 lines (113 loc) · 2.96 KB
/
goplay.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Package goplay provides The Go Playground (https://play.golang.org/) client
package goplay
import (
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"time"
)
const defaultBaseURL = "https://play.golang.org"
// DefaultClient is default Go Playground client.
var DefaultClient = &Client{}
var delay = time.Sleep
// Client represensts The Go Playground client.
type Client struct {
// The base URL of The Go Playground. Default is `https://play.golang.org/`.
BaseURL string
// The HTTP client to use when sending requests. Defaults to
// `http.DefaultClient`.
HTTPClient *http.Client
}
func (c *Client) httpClient() *http.Client {
if c.HTTPClient != nil {
return c.HTTPClient
}
return http.DefaultClient
}
func (c *Client) baseURL() string {
if c.BaseURL != "" {
return c.BaseURL
}
return defaultBaseURL
}
func (c *Client) shareEndpoint() string {
return c.baseURL() + "/share"
}
func (c *Client) compileEndpoint() string {
return c.baseURL() + "/compile"
}
// Run runs code which compiled in The Go Playground.
func (c *Client) Run(code io.Reader, stdout io.Writer, stderr io.Writer) error {
resp, err := c.Compile(code)
if err != nil {
return err
}
if resp.Errors != "" {
return errors.New(resp.Errors)
}
for _, event := range resp.Events {
delay(event.Delay)
w := stderr
if event.Kind == "stdout" {
w = stdout
}
fmt.Fprint(w, event.Message)
}
return nil
}
// Compile compiles code on The Go Playground.
func (c *Client) Compile(code io.Reader) (*Response, error) {
b, err := ioutil.ReadAll(code)
if err != nil {
return nil, err
}
v := url.Values{}
v.Set("version", "2")
v.Set("body", string(b))
resp, err := c.httpClient().PostForm(c.compileEndpoint(), v)
if err != nil {
return nil, err
}
defer resp.Body.Close()
var r Response
if err := json.NewDecoder(resp.Body).Decode(&r); err != nil {
return nil, err
}
return &r, nil
}
// Share creates go playground share link.
func (c *Client) Share(code io.Reader) (string, error) {
req, err := http.NewRequest("POST", c.shareEndpoint(), code)
if err != nil {
return "", err
}
resp, err := c.httpClient().Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
return fmt.Sprintf("%s/p/%s", c.baseURL(), string(b)), nil
}
// Response represensts response type of /compile.
type Response struct {
Errors string
Events []*Event
// Licence: Copyright (c) 2014 The Go Authors. All rights reserved.
// https://github.com/golang/playground/blob/816964eae74f7612221c13ab73f2a8021c581010/sandbox/sandbox.go#L35-L38
}
// Event represensts event of /compile result.
type Event struct {
Message string
Kind string // "stdout" or "stderr"
Delay time.Duration // time to wait before printing Message
// Licence: Copyright (c) 2014 The Go Authors. All rights reserved.
// https://github.com/golang/playground/blob/816964eae74f7612221c13ab73f2a8021c581010/sandbox/play.go#L76-L80
}