source: code/trunk/partage.go@ 8

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

Make ifs one-line when appropriate

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