/
main.go
130 lines (112 loc) · 2.56 KB
/
main.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
129
130
package main
import (
"bytes"
"flag"
"fmt"
"go/build"
"html/template"
"io"
"io/ioutil"
"log"
"net/http"
"os"
"path/filepath"
"strings"
"bitbucket.org/kardianos/osext"
"github.com/aarzilli/golua/lua"
)
var (
bind = flag.String("bind", ":8080", "[host]:port where to serve on")
asserts = flag.String("asserts", getWorkDir(), "path to assers")
//verbose = flag.Bool("verbose", false, "path to assers")
)
func getWorkDir() string {
p, err := build.Default.Import("github.com/nordicdyno/luawshop2014-gopher-on-lua", "", build.FindOnly)
if err != nil {
filename, _ := osext.Executable()
return filepath.Join(filepath.Dir(filename), "resources")
}
return filepath.Join(p.Dir, "resources")
}
func init() {
flag.Parse()
}
type appHandler struct{}
func main() {
h := appHandler{}
http.Handle("/", h)
if err := http.ListenAndServe(*bind, nil); err != nil {
fmt.Fprintf(os.Stderr, "error: %s\n", err)
os.Exit(1)
}
}
func (h appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
defer func() {
if rec := recover(); rec != nil {
log.Println("Catch error. Recovering...")
var doc bytes.Buffer
err := errorTemplate.Execute(&doc, &ErrorPage{
Code: http.StatusInternalServerError,
Message: rec,
})
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "text/html;charset=utf-8")
w.WriteHeader(http.StatusInternalServerError)
io.WriteString(w, doc.String())
}
}()
dir := *asserts
if _, err := os.Stat(dir); err != nil {
if os.IsNotExist(err) {
panic("Dir" + dir + " not exists")
}
panic(err)
}
if r.Method == "GET" {
if strings.HasSuffix(r.URL.Path, ".lua") {
serveLua(dir, w, r)
return
}
fs := http.FileServer(http.Dir(dir))
fs.ServeHTTP(w, r)
return
} else {
http.Error(w, "Invalid request method.", 405)
}
}
func serveLua(dir string, w http.ResponseWriter, r *http.Request) {
file := filepath.Join(dir, r.URL.Path)
content, err := ioutil.ReadFile(file)
if err != nil {
panic(err)
}
luaPrint := func(L *lua.State) int {
s := L.ToString(1)
io.WriteString(w, s)
io.WriteString(w, "\n")
if f, ok := w.(http.Flusher); ok {
f.Flush()
}
return 0
}
L := lua.NewState()
defer L.Close()
L.OpenLibs()
L.Register("print", luaPrint)
L.MustDoString(string(content))
}
type ErrorPage struct {
Code int
Message interface{}
}
var errorTemplate = template.Must(template.New("").Parse(`
<html><body>
<h2>This app is crashed with error:</h2>
<h2>Code: {{.Code}}<br>
Message: «{{.Message}}»
</h2>
</body></html>
`))