source: code/trunk/partage.go@ 7

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

Add newline after URL file download

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 _, err := w.Write(buffer[:n])
81 if err != nil {
82 fmt.Println(err)
83 }
84 break
85 }
86 fmt.Println(err)
87 return
88 }
89
90 _, err = w.Write(buffer[:n])
91 if err != nil {
92 fmt.Println(err)
93 }
94 }
95}
96
97func parse(w http.ResponseWriter, r *http.Request) {
98
99 // Max 15 Gb uploads
100 if r.ContentLength > conf.maxsize {
101 w.WriteHeader(http.StatusRequestEntityTooLarge)
102 w.Write([]byte("File is too big"))
103 }
104
105 err := r.ParseForm()
106 if err != nil {
107 fmt.Printf("%s %s: %s", r.Method, r.URL.Path, err)
108 }
109
110 switch r.Method {
111 case "PUT":
112 tmp, _ := ioutil.TempFile(conf.filepath, "*"+path.Ext(r.URL.Path))
113 f, err := os.Create(tmp.Name())
114 if err != nil {
115 fmt.Println(err)
116 return
117 }
118 defer f.Close()
119
120 if writefile(f, r.Body, r.ContentLength) < 0 {
121 w.WriteHeader(http.StatusInternalServerError)
122 return
123 }
124
125 resp := conf.baseuri + conf.filectx + filepath.Base(tmp.Name()) + "\r\n"
126 w.Write([]byte(resp))
127
128 case "GET":
129 // r.URL.Path is sanitized regarding "." and ".."
130 filename := r.URL.Path
131 if r.URL.Path == "/" {
132 filename = "/index.html"
133 }
134
135 f, err := os.Open(conf.rootdir + filename)
136 if err != nil {
137 w.WriteHeader(http.StatusNotFound)
138 fmt.Println(err)
139 return
140 }
141 defer f.Close()
142
143 servefile(f, w)
144 }
145}
146
147func main() {
148 conf.bind = "0.0.0.0:8080"
149 conf.maxsize = 28 * 1024 * 1024
150 conf.filepath = "/tmp"
151 conf.rootdir = "./static"
152 conf.baseuri = "http://192.168.0.3:8080"
153 conf.filectx = "/f/"
154
155 http.HandleFunc("/", parse)
156 http.Handle(conf.filectx, http.StripPrefix(conf.filectx, http.FileServer(http.Dir(conf.filepath))))
157 http.ListenAndServe("0.0.0.0:8080", nil)
158}
Note: See TracBrowser for help on using the repository browser.