source: code/trunk/partage.go@ 11

Last change on this file since 11 was 11, checked in by dev, 4 years ago

Add templating system for pages

File size: 3.3 KB
Line 
1package main
2
3import (
4 "fmt"
5 "io"
6 "io/ioutil"
7 "net/http"
8 "os"
9 "path"
10 "path/filepath"
11 "html/template"
12
13 "github.com/dustin/go-humanize"
14)
15
16type templatedata struct {
17 Maxsize string
18}
19
20var conf struct {
21 bind string
22 baseuri string
23 filepath string
24 rootdir string
25 templatedir string
26 filectx string
27 maxsize int64
28}
29
30
31func contenttype(f *os.File) string {
32 buffer := make([]byte, 512)
33
34 _, err := f.Read(buffer)
35 if err != nil {
36 return ""
37 }
38
39 mime := http.DetectContentType(buffer)
40
41 return mime
42}
43
44func writefile(f *os.File, s io.ReadCloser, contentlength int64) int64 {
45 buffer := make([]byte, 4096)
46 eof := false
47 sz := int64(0)
48
49 defer f.Sync()
50
51 for !eof {
52 n, err := s.Read(buffer)
53 if err != nil && err != io.EOF {
54 fmt.Println(err)
55 return -1
56 } else if err == io.EOF {
57 eof = true
58 }
59
60 /* ensure we don't write more than expected */
61 r := int64(n)
62 if sz+r > contentlength {
63 r = contentlength - sz
64 eof = true
65 }
66
67 _, err = f.Write(buffer[:r])
68 if err != nil {
69 fmt.Println(err)
70 }
71 sz += r
72 }
73
74 return sz
75}
76
77func servefile(f *os.File, w http.ResponseWriter) {
78 buffer := make([]byte, 4096)
79
80 mime := contenttype(f)
81 w.Header().Set("Content-Type", mime)
82
83 f.Seek(0, 0)
84 for {
85 n, err := f.Read(buffer)
86
87 if err != nil {
88 if err == io.EOF {
89 if _, err := w.Write(buffer[:n]); err != nil {
90 fmt.Println(err)
91 }
92 break
93 }
94 fmt.Println(err)
95 return
96 }
97
98 if _, err = w.Write(buffer[:n]); err != nil {
99 fmt.Println(err)
100 }
101 }
102}
103
104func servetemplate(w http.ResponseWriter, f string, d templatedata) {
105 t, err := template.ParseFiles(conf.templatedir + "/" + f)
106 if err != nil {
107 w.WriteHeader(http.StatusInternalServerError)
108 return
109 }
110
111 err = t.Execute(w, d)
112 if err != nil {
113 fmt.Println(err)
114 }
115}
116
117func uploaderPut(w http.ResponseWriter, r *http.Request) {
118 // Max 15 Gb uploads
119 if r.ContentLength > conf.maxsize {
120 w.WriteHeader(http.StatusRequestEntityTooLarge)
121 w.Write([]byte("File is too big"))
122 }
123
124 tmp, _ := ioutil.TempFile(conf.filepath, "*"+path.Ext(r.URL.Path))
125 f, err := os.Create(tmp.Name())
126 if err != nil {
127 fmt.Println(err)
128 return
129 }
130 defer f.Close()
131
132 if writefile(f, r.Body, r.ContentLength) < 0 {
133 w.WriteHeader(http.StatusInternalServerError)
134 return
135 }
136
137 resp := conf.baseuri + conf.filectx + filepath.Base(tmp.Name()) + "\r\n"
138 w.Write([]byte(resp))
139}
140
141func uploaderGet(w http.ResponseWriter, r *http.Request) {
142 // r.URL.Path is sanitized regarding "." and ".."
143 filename := r.URL.Path
144 if r.URL.Path == "/" || r.URL.Path == "/index" {
145 data := templatedata{ Maxsize: humanize.IBytes(uint64(conf.maxsize))}
146 servetemplate(w, "/index.html", data)
147 return
148 }
149
150 f, err := os.Open(conf.rootdir + filename)
151 if err != nil {
152 w.WriteHeader(http.StatusNotFound)
153 fmt.Println(err)
154 return
155 }
156 defer f.Close()
157
158 servefile(f, w)
159}
160
161func uploader(w http.ResponseWriter, r *http.Request) {
162 switch r.Method {
163 case "PUT":
164 uploaderPut(w, r)
165 case "GET":
166 uploaderGet(w, r)
167 }
168}
169
170func main() {
171 conf.bind = "0.0.0.0:8080"
172 conf.maxsize = 30064771072 // 28Gib
173 conf.filepath = "/tmp"
174 conf.rootdir = "./static"
175 conf.baseuri = "http://192.168.0.3:8080"
176 conf.filectx = "/f/"
177 conf.templatedir = "./templates"
178
179 http.HandleFunc("/", uploader)
180 http.Handle(conf.filectx, http.StripPrefix(conf.filectx, http.FileServer(http.Dir(conf.filepath))))
181 http.ListenAndServe("0.0.0.0:8080", nil)
182}
Note: See TracBrowser for help on using the repository browser.