forked from akhenakh/gozim
/
main.go
173 lines (142 loc) · 3.96 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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
package main
import (
"flag"
"html/template"
"log"
"net/http"
"os"
"os/signal"
"runtime/pprof"
"strconv"
"github.com/Bren2010/gozim"
"github.com/GeertJohan/go.rice"
"github.com/blevesearch/bleve"
"github.com/hashicorp/golang-lru"
_ "github.com/blevesearch/bleve/analysis/lang/ar"
_ "github.com/blevesearch/bleve/analysis/lang/cjk"
_ "github.com/blevesearch/bleve/analysis/lang/ckb"
_ "github.com/blevesearch/bleve/analysis/lang/en"
_ "github.com/blevesearch/bleve/analysis/lang/fa"
_ "github.com/blevesearch/bleve/analysis/lang/fr"
_ "github.com/blevesearch/bleve/analysis/lang/hi"
_ "github.com/blevesearch/bleve/analysis/lang/it"
_ "github.com/blevesearch/bleve/analysis/lang/pt"
_ "github.com/blevesearch/bleve/index/store/goleveldb"
)
type ResponseType int8
const (
RedirectResponse ResponseType = iota
DataResponse
NoResponse
)
// CachedResponse cache the answer to an URL in the zim
type CachedResponse struct {
ResponseType ResponseType
Data []byte
MimeType string
}
var (
port = flag.Int("port", -1, "port to listen to, read HOST env if not specified, default to 8080 otherwise")
zimPath = flag.String("path", "", "path for the zim file")
indexPath = flag.String("index", "", "path for the index file")
cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
Z *zim.ZimReader
// Cache is filled with CachedResponse to avoid hitting the zim file for a zim URL
cache *lru.ARCCache
idx bool
index bleve.Index
templates map[string]*template.Template
)
func init() {
templates = make(map[string]*template.Template)
tplBox := rice.MustFindBox("templates")
registerTemplate("index", tplBox)
registerTemplate("browse", tplBox)
registerTemplate("search", tplBox)
registerTemplate("searchNoIdx", tplBox)
registerTemplate("searchResult", tplBox)
registerTemplate("about", tplBox)
}
// registerTemplate load template from rice box and add them to a map[string] call templates
func registerTemplate(name string, tplBox *rice.Box) {
tplString, err := tplBox.String(name + ".html")
if err != nil {
log.Fatal(err)
}
templates[name] = template.Must(template.New(name).Parse(tplString))
}
func main() {
log.SetFlags(log.LstdFlags | log.Lshortfile)
flag.Parse()
if *zimPath == "" {
log.Fatal("provide a zim file path")
}
if *cpuprofile != "" {
f, err := os.Create(*cpuprofile)
if err != nil {
log.Fatal(err)
}
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func() {
for _ = range c {
pprof.StopCPUProfile()
os.Exit(1)
}
}()
}
// Do we have an index ?
if indexPath != nil && *indexPath != "" {
if _, err := os.Stat(*indexPath); err != nil {
log.Fatal(err)
}
idx = true
// open the db
var err error
index, err = bleve.Open(*indexPath)
if err != nil {
log.Fatal(err)
}
}
// assets
box := rice.MustFindBox("static")
fileServer := http.StripPrefix("/static/", http.FileServer(box.HTTPBox()))
http.Handle("/static/", fileServer)
// crompress wiki pages
http.HandleFunc("/zim/", zimHandler)
f, err := os.Open(*zimPath)
if err != nil {
log.Fatal(err)
}
z, err := zim.NewReader(f)
Z = z
if err != nil {
log.Fatal(err)
}
// tpl
http.HandleFunc("/search/", searchHandler)
http.HandleFunc("/browse/", browseHandler)
http.HandleFunc("/about/", aboutHandler)
http.HandleFunc("/robots.txt", robotHandler)
http.HandleFunc("/", homeHandler)
// the need for a cache is absolute
// a lot of the same urls will be called repeatedly, css, js ...
// avoid to look for those one
cache, _ = lru.NewARC(40)
// default listening to port 8080
listenPath := ":8080"
if len(os.Getenv("PORT")) > 0 {
listenPath = ":" + os.Getenv("PORT")
}
if port != nil && *port > 0 {
listenPath = ":" + strconv.Itoa(*port)
}
// Opening large indexes could takes minutes on raspberry
log.Println("Listening on", listenPath)
err = http.ListenAndServe(listenPath, nil)
if err != nil {
log.Fatal(err)
}
}