|
|
@ -15,34 +15,24 @@ import (
|
|
15
|
15
|
)
|
|
16
|
16
|
|
|
17
|
17
|
type Language interface {
|
|
18
|
|
Eval(code string) (result []byte, err error)
|
|
|
18
|
RunFile(f *os.File) (result []byte, err error)
|
|
|
19
|
Extension() string
|
|
19
|
20
|
}
|
|
20
|
21
|
|
|
21
|
22
|
type LanguageGo struct{}
|
|
|
23
|
type LanguagePython struct{}
|
|
22
|
24
|
|
|
23
|
25
|
var Go = LanguageGo{}
|
|
|
26
|
var Python = LanguagePython{}
|
|
24
|
27
|
|
|
25
|
|
func (g LanguageGo) Eval(code string) ([]byte, error) {
|
|
26
|
|
// write code to temp file
|
|
27
|
|
f, err := writeCode(code)
|
|
28
|
|
defer f.Close()
|
|
29
|
|
if err != nil {
|
|
30
|
|
return nil, err
|
|
31
|
|
}
|
|
32
|
|
// `go run` it
|
|
33
|
|
res, err := runCode(f)
|
|
34
|
|
if err != nil {
|
|
35
|
|
return res, err
|
|
36
|
|
}
|
|
37
|
|
// remove the file
|
|
38
|
|
os.Remove(f.Name())
|
|
39
|
|
// return output
|
|
40
|
|
return res, nil
|
|
|
28
|
var languageMappings = map[string]Language{
|
|
|
29
|
"go": Go,
|
|
|
30
|
"python": Python,
|
|
41
|
31
|
}
|
|
42
|
32
|
|
|
43
|
|
func writeCode(code string) (*os.File, error) {
|
|
|
33
|
func writeCode(code string, extension string) (*os.File, error) {
|
|
44
|
34
|
// create tmp file
|
|
45
|
|
f, err := os.Create("/tmp/linguaevalia-go.go") // FIXME: actually create a tmpfile
|
|
|
35
|
f, err := os.Create(fmt.Sprintf("/tmp/linguaevalia-%s.%s", extension, extension)) // FIXME: actually create a tmpfile
|
|
46
|
36
|
if err != nil {
|
|
47
|
37
|
return f, err
|
|
48
|
38
|
}
|
|
|
@ -54,19 +44,46 @@ func writeCode(code string) (*os.File, error) {
|
|
54
|
44
|
return f, nil
|
|
55
|
45
|
}
|
|
56
|
46
|
|
|
57
|
|
func runCode(f *os.File) ([]byte, error) {
|
|
|
47
|
func (l LanguageGo) RunFile(f *os.File) ([]byte, error) {
|
|
58
|
48
|
cmd := exec.Command("go", "run", f.Name())
|
|
59
|
49
|
return cmd.CombinedOutput()
|
|
60
|
50
|
}
|
|
61
|
51
|
|
|
|
52
|
func (l LanguageGo) Extension() string { return "go" }
|
|
|
53
|
|
|
|
54
|
func (l LanguagePython) RunFile(f *os.File) ([]byte, error) {
|
|
|
55
|
cmd := exec.Command("python", f.Name())
|
|
|
56
|
return cmd.CombinedOutput()
|
|
|
57
|
}
|
|
|
58
|
|
|
|
59
|
func (l LanguagePython) Extension() string { return "py" }
|
|
|
60
|
|
|
|
61
|
func Eval(lang Language, code string) ([]byte, error) {
|
|
|
62
|
// write code to temp file
|
|
|
63
|
f, err := writeCode(code, lang.Extension())
|
|
|
64
|
defer f.Close()
|
|
|
65
|
if err != nil {
|
|
|
66
|
return nil, err
|
|
|
67
|
}
|
|
|
68
|
// `go run` it
|
|
|
69
|
res, err := lang.RunFile(f)
|
|
|
70
|
if err != nil {
|
|
|
71
|
return res, err
|
|
|
72
|
}
|
|
|
73
|
// remove the file
|
|
|
74
|
os.Remove(f.Name())
|
|
|
75
|
// return output
|
|
|
76
|
return res, nil
|
|
|
77
|
}
|
|
|
78
|
|
|
62
|
79
|
func runCodeHandler(w http.ResponseWriter, r *http.Request) {
|
|
63
|
80
|
code, err := ioutil.ReadAll(r.Body)
|
|
64
|
81
|
if err != nil {
|
|
65
|
82
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
66
|
83
|
return
|
|
67
|
84
|
}
|
|
68
|
|
//fmt.Println(string(code))
|
|
69
|
|
res, err := Go.Eval(string(code))
|
|
|
85
|
lang := getLanguage(r)
|
|
|
86
|
res, err := Eval(lang, string(code))
|
|
70
|
87
|
if err != nil {
|
|
71
|
88
|
http.Error(w, string(res), http.StatusNotAcceptable)
|
|
72
|
89
|
return
|
|
|
@ -74,6 +91,17 @@ func runCodeHandler(w http.ResponseWriter, r *http.Request) {
|
|
74
|
91
|
w.Write(res)
|
|
75
|
92
|
}
|
|
76
|
93
|
|
|
|
94
|
func getLanguage(r *http.Request) Language {
|
|
|
95
|
langName := r.URL.Query().Get("language")
|
|
|
96
|
if langName != "" {
|
|
|
97
|
lang, ok := languageMappings[langName]
|
|
|
98
|
if ok {
|
|
|
99
|
return lang
|
|
|
100
|
}
|
|
|
101
|
}
|
|
|
102
|
return Go
|
|
|
103
|
}
|
|
|
104
|
|
|
77
|
105
|
func homePageHandler(w http.ResponseWriter, r *http.Request) {
|
|
78
|
106
|
homePageTemplate.Execute(w, nil)
|
|
79
|
107
|
}
|