@@ -11,6 +11,7 @@ import (
1111 "path/filepath"
1212 "strings"
1313 "sync"
14+ "time"
1415
1516 "github.com/fatih/color"
1617 "github.com/valyala/fasthttp"
@@ -19,7 +20,7 @@ import (
1920
2021const (
2122 // Version information
22- Version = "SimpleHttpServer v1.3-beta.1 "
23+ Version = "SimpleHttpServer v1.3-beta.2 "
2324 // HTTPProxy returns HTTP_PROXY
2425 HTTPProxy = "HTTP_PROXY"
2526 // HTTPSProxy returns HTTPS_PROXY
@@ -289,6 +290,10 @@ func main() {
289290 fs .PathNotFound = func (ctx * fasthttp.RequestCtx ) {
290291 fallbackpath := filepath .Join (v , config .Fallback )
291292 if _ , err := os .Stat (fallbackpath ); err == nil {
293+ mimeType := staticFileGetMimeType (filepath .Ext (fallbackpath ))
294+ if len (mimeType ) > 0 {
295+ ctx .SetContentType (mimeType )
296+ }
292297 ctx .SendFile (fallbackpath )
293298 } else {
294299 ctx .Error (fasthttp .StatusMessage (fasthttp .StatusNotFound ), fasthttp .StatusNotFound )
@@ -341,6 +346,11 @@ func requestHandler(ctx *fasthttp.RequestCtx) {
341346 }
342347
343348 // router
349+ // log print
350+ if config .Verbose {
351+ statusCode := ctx .Response .StatusCode ()
352+ go logInfo (statusCode , "%d | %s | %s | %s\n " , statusCode , ctx .RemoteIP (), ctx .Method (), ctx .Path ())
353+ }
344354 switch string (ctx .Method ()) {
345355 case "POST" :
346356 switch string (ctx .Path ()) {
@@ -359,12 +369,6 @@ func requestHandler(ctx *fasthttp.RequestCtx) {
359369 default :
360370 ctx .Error (fasthttp .StatusMessage (fasthttp .StatusNotFound ), fasthttp .StatusNotFound )
361371 }
362-
363- // log print
364- if config .Verbose {
365- statusCode := ctx .Response .StatusCode ()
366- go logInfo (statusCode , "%d | %s | %s | %s\n " , statusCode , ctx .RemoteIP (), ctx .Method (), ctx .Path ())
367- }
368372}
369373
370374func fsHandler (ctx * fasthttp.RequestCtx ) {
@@ -417,6 +421,10 @@ func dirHandler(path string, ctx *fasthttp.RequestCtx) bool {
417421 indexfile := filepath .Join (localpath , v )
418422 if fi , err := os .Stat (indexfile ); err == nil {
419423 if ! fi .IsDir () {
424+ mimeType := staticFileGetMimeType (filepath .Ext (indexfile ))
425+ if len (mimeType ) > 0 {
426+ ctx .SetContentType (mimeType )
427+ }
420428 ctx .SendFile (indexfile )
421429 return true
422430 }
@@ -446,6 +454,7 @@ func dirHandler(path string, ctx *fasthttp.RequestCtx) bool {
446454 uploadhtml = fmt .Sprintf (`<form enctype="multipart/form-data" action="/upload" method="post">` +
447455 `<input name="files[]" type="file" multiple>` +
448456 `<input type="submit" value="Upload" onclick="this.disabled=true;this.value='Sending...';"/>` +
457+ `<input type="checkbox" name="o" value="true">Overwrite` +
449458 `<input type="hidden" id="r" name="r" value="%s">` +
450459 `<input type="hidden" id="p" name="p" value="%s"></form>` ,
451460 ctx .RequestURI (), localpath )
@@ -488,6 +497,7 @@ func uploadHandle(ctx *fasthttp.RequestCtx) {
488497 }
489498
490499 var uri , path string
500+ isOverwrite := false
491501 if r , ok := form .Value ["r" ]; ok && len (r ) == 1 {
492502 uri = r [0 ]
493503 }
@@ -502,11 +512,36 @@ func uploadHandle(ctx *fasthttp.RequestCtx) {
502512 ctx .Error (err .Error (), fasthttp .StatusInternalServerError )
503513 return
504514 }
515+ if o , ok := form .Value ["o" ]; ok && len (o ) == 1 {
516+ isOverwrite = o [0 ] == "true"
517+ }
505518
506519 for _ , v := range form .File {
507520 for _ , header := range v {
508521 fn := filepath .Join (path , header .Filename )
509- fasthttp .SaveMultipartFile (header , fn )
522+ if ! isOverwrite && fileOrDirIsExist (fn ) {
523+ for index := 1 ; index <= MaxInt ; index ++ {
524+ ext := filepath .Ext (fn )
525+ newfn := fmt .Sprintf ("%s_%s_%d%s" ,
526+ strings .TrimSuffix (fn , ext ),
527+ time .Now ().Format ("20060102150405" ),
528+ index ,
529+ ext )
530+ if ! fileOrDirIsExist (newfn ) {
531+ fn = newfn
532+ break
533+ }
534+ if index == MaxInt {
535+ ctx .Error ("Sorry, can not create unique filename for " + fn , fasthttp .StatusInternalServerError )
536+ return
537+ }
538+ }
539+ }
540+ logInfo (0 , "%s | Saving file %s" , ctx .RemoteIP (), fn )
541+ err := fasthttp .SaveMultipartFile (header , fn )
542+ if err != nil {
543+ logInfo (fasthttp .StatusInternalServerError , "Save %s failed: %s" , fn , err .Error ())
544+ }
510545 }
511546 }
512547 ctx .Redirect (uri , fasthttp .StatusOK )
@@ -519,6 +554,13 @@ func dirIsExist(path string) bool {
519554 return false
520555}
521556
557+ func fileOrDirIsExist (path string ) bool {
558+ if _ , err := os .Stat (path ); err == nil {
559+ return true
560+ }
561+ return false
562+ }
563+
522564func basicAuth (ctx * fasthttp.RequestCtx ) (username , password string , ok bool ) {
523565 auth := ctx .Request .Header .Peek ("Authorization" )
524566 if auth == nil {
0 commit comments