1- package server
1+ package main
22
33import (
4+ "context"
5+ "crypto/tls"
46 "fmt"
57 "html/template"
68 "io"
79 "math"
10+ "net"
811 "net/http"
912 "net/url"
1013 "os"
1114 "path"
1215 "path/filepath"
1316 "sort"
1417 "strings"
18+ "sync"
19+ "sync/atomic"
20+ "time"
1521
1622 "github.com/astaxie/beego/logs"
1723)
1824
1925const (
20- tarGzKey = "tar.gz"
21- tarGzValue = "true"
22- tarGzContentType = "application/x-tar+gzip"
23-
2426 zipKey = "zip"
2527 zipValue = "true"
2628 zipContentType = "application/zip"
@@ -45,7 +47,6 @@ const directoryListingTemplateText = `
4547 </thead>
4648 <tbody>
4749 {{- if .Files }}
48- <tr><td colspan=3><a href="{{ .TarGzURL }}">.tar.gz of all files</a></td></tr>
4950 <tr><td colspan=3><a href="{{ .ZipURL }}">.zip of all files</a></td></tr>
5051 {{- end }}
5152 {{- range .Files }}
@@ -104,21 +105,30 @@ type directoryListingFileData struct {
104105type directoryListingData struct {
105106 Title string
106107 ZipURL * url.URL
107- TarGzURL * url.URL
108108 Files []directoryListingFileData
109109 AllowUpload bool
110110}
111111
112+ var (
113+ directoryListingTemplate = template .Must (template .New ("" ).Parse (directoryListingTemplateText ))
114+ )
115+
112116type fileHandler struct {
113117 route string
114118 path string
115119 allowUpload bool
116120 allowDelete bool
117- }
118121
119- var (
120- directoryListingTemplate = template .Must (template .New ("" ).Parse (directoryListingTemplateText ))
121- )
122+ timeout int
123+ address string
124+ server * http.Server
125+
126+ flowbytes int64
127+ requests int64
128+ sessions int64
129+
130+ sync.WaitGroup
131+ }
122132
123133func (f * fileHandler ) serveStatus (w http.ResponseWriter , r * http.Request , status int ) error {
124134 w .WriteHeader (status )
@@ -129,18 +139,11 @@ func (f *fileHandler) serveStatus(w http.ResponseWriter, r *http.Request, status
129139 return nil
130140}
131141
132- func (f * fileHandler ) serveTarGz (w http.ResponseWriter , r * http.Request , path string ) error {
133- w .Header ().Set ("Content-Type" , tarGzContentType )
134- name := filepath .Base (path ) + ".tar.gz"
135- w .Header ().Set ("Content-Disposition" , fmt .Sprintf (`attachment; filename=%q` , name ))
136- return tarGz (w , path )
137- }
138-
139142func (f * fileHandler ) serveZip (w http.ResponseWriter , r * http.Request , osPath string ) error {
140143 w .Header ().Set ("Content-Type" , zipContentType )
141144 name := filepath .Base (osPath ) + ".zip"
142145 w .Header ().Set ("Content-Disposition" , fmt .Sprintf (`attachment; filename=%q` , name ))
143- return zip (w , osPath )
146+ return FileZip (w , osPath )
144147}
145148
146149func (f * fileHandler ) serveDir (w http.ResponseWriter , r * http.Request , osPath string ) error {
@@ -158,14 +161,8 @@ func (f *fileHandler) serveDir(w http.ResponseWriter, r *http.Request, osPath st
158161 AllowUpload : f .allowUpload ,
159162 Title : func () string {
160163 relPath , _ := filepath .Rel (f .path , osPath )
161- return filepath .Join (filepath .Base (f .path ), relPath )
162- }(),
163- TarGzURL : func () * url.URL {
164- url := * r .URL
165- q := url .Query ()
166- q .Set (tarGzKey , tarGzValue )
167- url .RawQuery = q .Encode ()
168- return & url
164+ urlPath := filepath .Join (filepath .Base (f .path ), relPath )
165+ return strings .ReplaceAll (urlPath , osPathSeparator , "/" )
169166 }(),
170167 ZipURL : func () * url.URL {
171168 url := * r .URL
@@ -178,7 +175,7 @@ func (f *fileHandler) serveDir(w http.ResponseWriter, r *http.Request, osPath st
178175 for _ , d := range files {
179176 name := d .Name ()
180177 if d .IsDir () {
181- name += osPathSeparator
178+ name += "/"
182179 }
183180 fileData := directoryListingFileData {
184181 Name : name ,
@@ -213,7 +210,7 @@ func (f *fileHandler) serveUploadTo(w http.ResponseWriter, r *http.Request, osPa
213210 return err
214211 }
215212 outPath := filepath .Join (osPath , filepath .Base (h .Filename ))
216- out , err := os .OpenFile (outPath , os .O_CREATE | os .O_WRONLY , 0600 )
213+ out , err := os .OpenFile (outPath , os .O_CREATE | os .O_WRONLY , 0644 )
217214 if err != nil {
218215 return err
219216 }
@@ -229,7 +226,9 @@ func (f *fileHandler) serveUploadTo(w http.ResponseWriter, r *http.Request, osPa
229226
230227// ServeHTTP is http.Handler.ServeHTTP
231228func (f * fileHandler ) ServeHTTP (w http.ResponseWriter , r * http.Request ) {
232- logs .Info ("[%s] %s %s %s" , f .path , r .RemoteAddr , r .Method , r .URL .String ())
229+ logs .Info ("http server request [%s] %s %s %s" , f .path , r .RemoteAddr , r .Method , r .URL .String ())
230+
231+ atomic .AddInt64 (& f .requests , 1 )
233232
234233 urlPath := r .URL .Path
235234 if ! strings .HasPrefix (urlPath , "/" ) {
@@ -241,6 +240,7 @@ func (f *fileHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
241240 osPath := strings .ReplaceAll (urlPath , "/" , osPathSeparator )
242241 osPath = filepath .Clean (osPath )
243242 osPath = filepath .Join (f .path , osPath )
243+
244244 info , err := os .Stat (osPath )
245245 switch {
246246 case os .IsNotExist (err ):
@@ -258,11 +258,6 @@ func (f *fileHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
258258 if err != nil {
259259 _ = f .serveStatus (w , r , http .StatusInternalServerError )
260260 }
261- case r .URL .Query ().Get (tarGzKey ) != "" :
262- err := f .serveTarGz (w , r , osPath )
263- if err != nil {
264- _ = f .serveStatus (w , r , http .StatusInternalServerError )
265- }
266261 case f .allowUpload && info .IsDir () && r .Method == http .MethodPost :
267262 err := f .serveUploadTo (w , r , osPath )
268263 if err != nil {
@@ -282,3 +277,85 @@ func (f *fileHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
282277 http .ServeFile (w , r , osPath )
283278 }
284279}
280+
281+ func (f * fileHandler ) Shutdown () error {
282+ context , cencel := context .WithTimeout (context .Background (), time .Duration (5 )* time .Second )
283+ err := f .server .Shutdown (context )
284+ cencel ()
285+ if err != nil {
286+ logs .Error ("http file server ready to shut down fail, %s" , err .Error ())
287+ }
288+ f .Wait ()
289+ return err
290+ }
291+
292+ func CreateHttpServer (addr , folder string ,
293+ upload , delete bool ,
294+ https bool , cert , key string ) (* fileHandler , error ) {
295+
296+ listen , err := net .Listen ("tcp" , addr )
297+ if err != nil {
298+ logs .Error ("http file server listen %s address fail" , addr )
299+ return nil , err
300+ }
301+ logs .Info ("http file server listening on %s" , addr )
302+
303+ var tlsConfig * tls.Config
304+ if https {
305+ tlsConfig , err = CreateTlsConfig (cert , key )
306+ if err != nil {
307+ logs .Error ("create tls config for http server fail, %s" , err .Error ())
308+ return nil , err
309+ }
310+ listen = tls .NewListener (listen , tlsConfig )
311+ }
312+
313+ fileHandler := & fileHandler {
314+ route : "/" ,
315+ path : folder ,
316+ allowUpload : upload ,
317+ allowDelete : delete ,
318+ }
319+
320+ httpserver := & http.Server {
321+ Handler : fileHandler ,
322+ ReadTimeout : time .Duration (60 ) * time .Second ,
323+ WriteTimeout : time .Duration (60 ) * time .Second ,
324+ TLSConfig : tlsConfig ,
325+ }
326+
327+ fileHandler .server = httpserver
328+ fileHandler .Add (1 )
329+
330+ go func () {
331+ defer fileHandler .Done ()
332+ err = httpserver .Serve (listen )
333+ if err != nil {
334+ logs .Error ("http server attach listen instance fail, %s" , err .Error ())
335+ }
336+ }()
337+
338+ return fileHandler , nil
339+ }
340+
341+ // func HttpServer(addr string, folder string, cert, key string) error {
342+
343+ // mux := http.DefaultServeMux
344+
345+ // fileHandler := &fileHandler{
346+ // route: "/",
347+ // path: folder,
348+ // allowUpload: true,
349+ // allowDelete: true,
350+ // }
351+
352+ // mux.Handle("/", fileHandler)
353+
354+ // logs.Info("http file server listening on %s", addr)
355+
356+ // if cert != "" && key != "" {
357+ // return http.ListenAndServeTLS(addr, cert, key, mux)
358+ // }
359+
360+ // return http.ListenAndServe(addr, mux)
361+ // }
0 commit comments