-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
103 lines (93 loc) · 2.34 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
package main
import (
"encoding/json"
"flag"
"fmt"
"image/png"
"log"
"net/http"
"os"
"path"
"strconv"
"time"
"github.com/fogleman/density"
"github.com/gorilla/mux"
)
const CqlHost = "127.0.0.1"
var Port int
var CacheDirectory string
var Keyspace string
var Table string
var BaseZoom int
func init() {
flag.IntVar(&Port, "port", 5000, "server port")
flag.StringVar(&CacheDirectory, "cache", "cache", "cache directory")
flag.StringVar(&Keyspace, "keyspace", "density", "keyspace name")
flag.StringVar(&Table, "table", "points", "table name")
flag.IntVar(&BaseZoom, "zoom", 13, "tile zoom")
}
func cachePath(zoom, x, y int) string {
return fmt.Sprintf("%s/%d/%d/%d.png", CacheDirectory, zoom, x, y)
}
func pathExists(p string) bool {
_, err := os.Stat(p)
return err == nil
}
func parseInt(x string) int {
value, _ := strconv.ParseInt(x, 0, 0)
return int(value)
}
func Handler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
zoom := parseInt(vars["zoom"])
x := parseInt(vars["x"])
y := parseInt(vars["y"])
p := cachePath(zoom, x, y)
if !pathExists(p) {
// nothing in cache, render the tile
renderer := density.NewRenderer(CqlHost, Keyspace, Table, BaseZoom)
im, ok := renderer.Render(zoom, x, y)
if ok {
// save tile in cache
d, _ := path.Split(p)
os.MkdirAll(d, 0777)
f, err := os.Create(p)
if err != nil {
// unable to cache, just send the png
w.Header().Set("Content-Type", "image/png")
w.Header().Set("Access-Control-Allow-Origin", "*")
png.Encode(w, im)
return
}
png.Encode(f, im)
f.Close()
} else {
// blank tile
http.NotFound(w, r)
return
}
} else {
fmt.Printf("CACHED (%d %d %d)\n", zoom, x, y)
}
// serve cached tile
w.Header().Set("Content-Type", "image/png")
w.Header().Set("Access-Control-Allow-Origin", "*")
http.ServeFile(w, r, p)
}
func main() {
flag.Parse()
router := mux.NewRouter()
router.HandleFunc("/api/health/", func(w http.ResponseWriter, r *http.Request) {
// an example API handler
json.NewEncoder(w).Encode(map[string]bool{"ok": true})
})
router.HandleFunc("/{zoom:[0-9]+}/{x:[0-9]+}/{y:[0-9]+}.png", Handler)
srv := &http.Server{
Handler: router,
Addr: "0.0.0.0:5000",
// Good practice: enforce timeouts for servers you create!
WriteTimeout: 15 * time.Second,
ReadTimeout: 15 * time.Second,
}
log.Fatal(srv.ListenAndServe())
}