source: code/trunk/partage.go@ 3

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

Serve files as-is for context "/f/"

File size: 2.6 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) int {
36 buffer := make([]byte, 4096)
37
38 var sz int
39
40 for {
41 n, err := s.Read(buffer)
42
43 if err == io.EOF {
44 n, err := f.Write(buffer[:n])
45 if err != nil {
46 fmt.Println(err)
47 }
48 sz += n
49 break
50 }
51 if err != nil {
52 fmt.Println(err)
53 return -1
54 }
55
56 n, err = f.Write(buffer[:n])
57 if err != nil {
58 fmt.Println(err)
59 }
60 sz += n
61 }
62
63 f.Sync()
64 return sz
65}
66
67func servefile(f *os.File, w http.ResponseWriter) {
68 buffer := make([]byte, 4096)
69
70 mime := contenttype(f)
71 w.Header().Set("Content-Type", mime)
72
73 f.Seek(0, 0)
74 for {
75 n, err := f.Read(buffer)
76
77 if err != nil {
78 if err == io.EOF {
79 _, err := w.Write(buffer[:n])
80 if err != nil {
81 fmt.Println(err)
82 }
83 break
84 }
85 fmt.Println(err)
86 return
87 }
88
89 _, err = w.Write(buffer[:n])
90 if err != nil {
91 fmt.Println(err)
92 }
93 }
94}
95
96func parse(w http.ResponseWriter, r *http.Request) {
97
98 fmt.Printf("%s %s\n", r.Method, r.URL.Path)
99
100 // Max 15 Gb uploads
101 if r.ContentLength > conf.maxsize {
102 w.WriteHeader(http.StatusRequestEntityTooLarge)
103 w.Write([]byte("File is too big"))
104 }
105
106 err := r.ParseForm()
107 if err != nil {
108 fmt.Printf("%s %s: %s", r.Method, r.URL.Path, err)
109 }
110
111 switch r.Method {
112 case "PUT":
113 tmp, _ := ioutil.TempFile(conf.filepath, "*"+path.Ext(r.URL.Path))
114 f, err := os.Create(tmp.Name())
115 if err != nil {
116 fmt.Println(err)
117 return
118 }
119 defer f.Close()
120
121 if writefile(f, r.Body) < 0 {
122 w.WriteHeader(http.StatusInternalServerError)
123 return
124 }
125
126 resp := conf.baseuri + conf.filectx + filepath.Base(tmp.Name())
127 w.Write([]byte(resp))
128
129 case "GET":
130 // r.URL.Path is sanitized regarding "." and ".."
131 filename := r.URL.Path
132 if r.URL.Path == "/" {
133 filename = "/index.html"
134 }
135
136 f, err := os.Open(conf.rootdir + filename)
137 if err != nil {
138 w.WriteHeader(http.StatusNotFound)
139 fmt.Println(err)
140 return
141 }
142 defer f.Close()
143
144 servefile(f, w)
145 }
146}
147
148func main() {
149 conf.bind = "0.0.0.0:8080"
150 conf.maxsize = 28 * 1024 * 1024
151 conf.filepath = "/tmp"
152 conf.rootdir = "./static"
153 conf.baseuri = "http://192.168.0.3:8080"
154 conf.filectx = "/f/"
155
156 http.HandleFunc("/", parse)
157 http.Handle(conf.filectx, http.StripPrefix(conf.filectx, http.FileServer(http.Dir(conf.filepath))))
158 http.ListenAndServe("0.0.0.0:8080", nil)
159}
Note: See TracBrowser for help on using the repository browser.