forked from wellington/wellington
/
http.go
83 lines (77 loc) · 2.11 KB
/
http.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
package wellington
import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
"path/filepath"
"strconv"
"time"
libsass "github.com/wellington/go-libsass"
)
// FileHandler starts a file server serving files out of the specified
// build directory.
func FileHandler(gen string) http.Handler {
abs, err := filepath.Abs(gen)
if err != nil {
log.Fatalf("Can not resolve relative path: %s", gen)
}
return http.StripPrefix("/build/",
http.FileServer(http.Dir(abs)),
)
}
// Response is the object returned on HTTP responses from wellington
type Response struct {
Contents string `json:"contents"`
Start time.Time `json:"start"`
Elapsed string `json:"elapsed"`
Error string `json:"error"`
}
// HTTPHandler starts a CORS enabled web server that takes as input
// Sass and outputs CSS.
func HTTPHandler(ctx *libsass.Context) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
var (
pout bytes.Buffer
buf bytes.Buffer
)
start := time.Now()
// Set headers
if origin := r.Header.Get("Origin"); origin != "" {
w.Header().Set("Access-Control-Allow-Origin", origin)
}
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token")
w.Header().Set("Access-Control-Allow-Credentials", "true")
_, err := StartParser(ctx, r.Body, &pout, NewPartialMap())
if err != nil {
enc := json.NewEncoder(w)
enc.Encode(Response{
Start: start,
Elapsed: strconv.FormatFloat(float64(
time.Since(start).Nanoseconds())/float64(time.Millisecond),
'f', 3, 32) + "ms",
Contents: "",
Error: fmt.Sprintf("%s", err),
})
return
}
err = ctx.Compile(&pout, &buf)
defer func() {
enc := json.NewEncoder(w)
errString := ""
if err != nil {
errString = err.Error()
}
enc.Encode(Response{
Start: start,
Elapsed: strconv.FormatFloat(float64(
time.Since(start).Nanoseconds())/(1000*1000),
'f', 3, 32) + "ms",
Contents: buf.String(),
Error: errString,
})
}()
}
}