@@ -553,16 +553,12 @@ type fsFile struct {
553553
554554func (ff * fsFile ) NewReader () (io.Reader , error ) {
555555 if ff .isBig () {
556- r , err := ff .bigFileReader ()
557- if err != nil {
558- ff .decReadersCount ()
559- }
560- return r , err
556+ return ff .bigFileReader ()
561557 }
562- return ff .smallFileReader ()
558+ return ff .smallFileReader (), nil
563559}
564560
565- func (ff * fsFile ) smallFileReader () ( io.Reader , error ) {
561+ func (ff * fsFile ) smallFileReader () io.Reader {
566562 v := ff .h .smallFileReaderPool .Get ()
567563 if v == nil {
568564 v = & fsSmallFileReader {}
@@ -571,9 +567,9 @@ func (ff *fsFile) smallFileReader() (io.Reader, error) {
571567 r .ff = ff
572568 r .endPos = ff .contentLength
573569 if r .startPos > 0 {
574- return nil , errors . New ("bug: fsSmallFileReader with non-nil startPos found in the pool" )
570+ panic ("bug: fsSmallFileReader with non-nil startPos found in the pool" )
575571 }
576- return r , nil
572+ return r
577573}
578574
579575// Files bigger than this size are sent with sendfile.
@@ -631,12 +627,12 @@ func (ff *fsFile) Release() {
631627}
632628
633629func (ff * fsFile ) decReadersCount () {
634- ff .h .cacheManager .WithLock ( func () {
635- ff .readersCount --
636- if ff .readersCount < 0 {
637- ff .readersCount = 0
638- }
639- } )
630+ ff .h .cacheManager .Lock ()
631+ ff .readersCount --
632+ if ff .readersCount < 0 {
633+ panic ( "bug: fsFile .readersCount < 0" )
634+ }
635+ ff . h . cacheManager . Unlock ( )
640636}
641637
642638// bigFileReader attempts to trigger sendfile
@@ -796,9 +792,10 @@ func (r *fsSmallFileReader) WriteTo(w io.Writer) (int64, error) {
796792}
797793
798794type cacheManager interface {
799- WithLock (work func ())
800- GetFileFromCache (cacheKind CacheKind , path string ) (* fsFile , bool )
801- SetFileToCache (cacheKind CacheKind , path string , ff * fsFile ) * fsFile
795+ Lock ()
796+ Unlock ()
797+ GetFileFromCache (cacheKind CacheKind , path []byte ) (* fsFile , bool )
798+ SetFileToCache (cacheKind CacheKind , path []byte , ff * fsFile ) * fsFile
802799}
803800
804801var (
@@ -842,19 +839,22 @@ type noopCacheManager struct {
842839 cacheLock sync.Mutex
843840}
844841
845- func (n * noopCacheManager ) WithLock ( work func () ) {
842+ func (n * noopCacheManager ) Lock ( ) {
846843 n .cacheLock .Lock ()
844+ }
847845
848- work ()
849-
846+ func (n * noopCacheManager ) Unlock () {
850847 n .cacheLock .Unlock ()
851848}
852849
853- func (* noopCacheManager ) GetFileFromCache (cacheKind CacheKind , path string ) (* fsFile , bool ) {
850+ func (* noopCacheManager ) GetFileFromCache (cacheKind CacheKind , path [] byte ) (* fsFile , bool ) {
854851 return nil , false
855852}
856853
857- func (* noopCacheManager ) SetFileToCache (cacheKind CacheKind , path string , ff * fsFile ) * fsFile {
854+ func (n * noopCacheManager ) SetFileToCache (cacheKind CacheKind , path []byte , ff * fsFile ) * fsFile {
855+ n .cacheLock .Lock ()
856+ ff .readersCount ++
857+ n .cacheLock .Unlock ()
858858 return ff
859859}
860860
@@ -867,11 +867,11 @@ type inMemoryCacheManager struct {
867867 cacheLock sync.Mutex
868868}
869869
870- func (cm * inMemoryCacheManager ) WithLock ( work func () ) {
870+ func (cm * inMemoryCacheManager ) Lock ( ) {
871871 cm .cacheLock .Lock ()
872+ }
872873
873- work ()
874-
874+ func (cm * inMemoryCacheManager ) Unlock () {
875875 cm .cacheLock .Unlock ()
876876}
877877
@@ -889,11 +889,11 @@ func (cm *inMemoryCacheManager) getFsCache(cacheKind CacheKind) map[string]*fsFi
889889 return fileCache
890890}
891891
892- func (cm * inMemoryCacheManager ) GetFileFromCache (cacheKind CacheKind , path string ) (* fsFile , bool ) {
892+ func (cm * inMemoryCacheManager ) GetFileFromCache (cacheKind CacheKind , path [] byte ) (* fsFile , bool ) {
893893 fileCache := cm .getFsCache (cacheKind )
894894
895895 cm .cacheLock .Lock ()
896- ff , ok := fileCache [path ]
896+ ff , ok := fileCache [string ( path ) ]
897897 if ok {
898898 ff .readersCount ++
899899 }
@@ -902,13 +902,13 @@ func (cm *inMemoryCacheManager) GetFileFromCache(cacheKind CacheKind, path strin
902902 return ff , ok
903903}
904904
905- func (cm * inMemoryCacheManager ) SetFileToCache (cacheKind CacheKind , path string , ff * fsFile ) * fsFile {
905+ func (cm * inMemoryCacheManager ) SetFileToCache (cacheKind CacheKind , path [] byte , ff * fsFile ) * fsFile {
906906 fileCache := cm .getFsCache (cacheKind )
907907
908908 cm .cacheLock .Lock ()
909- ff1 , ok := fileCache [path ]
909+ ff1 , ok := fileCache [string ( path ) ]
910910 if ! ok {
911- fileCache [path ] = ff
911+ fileCache [string ( path ) ] = ff
912912 ff .readersCount ++
913913 } else {
914914 ff1 .readersCount ++
@@ -1005,14 +1005,31 @@ func cleanCacheNolock(
10051005 return pendingFiles , filesToRelease
10061006}
10071007
1008- func (h * fsHandler ) pathToFilePath (path string ) string {
1008+ func (h * fsHandler ) pathToFilePath (path [] byte , hasTrailingSlash bool ) string {
10091009 if _ , ok := h .filesystem .(* osFS ); ! ok {
10101010 if len (path ) < 1 {
1011- return path
1011+ return ""
1012+ } else if len (path ) == 1 && path [0 ] == '/' {
1013+ return ""
1014+ }
1015+ if hasTrailingSlash {
1016+ return string (path [1 : len (path )- 1 ])
10121017 }
1013- return path [1 :]
1018+ return string (path [1 :])
1019+ }
1020+
1021+ // Use byte buffer pool to avoid string concatenation allocations
1022+ b := bytebufferpool .Get ()
1023+ defer bytebufferpool .Put (b )
1024+
1025+ b .B = append (b .B , h .root ... )
1026+ if hasTrailingSlash {
1027+ b .B = append (b .B , path [:len (path )- 1 ]... )
1028+ } else {
1029+ b .B = append (b .B , path ... )
10141030 }
1015- return filepath .FromSlash (h .root + path )
1031+
1032+ return filepath .FromSlash (string (b .B ))
10161033}
10171034
10181035func (h * fsHandler ) filePathToCompressed (filePath string ) string {
@@ -1071,15 +1088,9 @@ func (h *fsHandler) handleRequest(ctx *RequestCtx) {
10711088 }
10721089 }
10731090
1074- originalPathStr := string (path )
1075- pathStr := originalPathStr
1076- if hasTrailingSlash {
1077- pathStr = originalPathStr [:len (originalPathStr )- 1 ]
1078- }
1079-
1080- ff , ok := h .cacheManager .GetFileFromCache (fileCacheKind , originalPathStr )
1091+ ff , ok := h .cacheManager .GetFileFromCache (fileCacheKind , path )
10811092 if ! ok {
1082- filePath := h .pathToFilePath (pathStr )
1093+ filePath := h .pathToFilePath (path , hasTrailingSlash )
10831094
10841095 var err error
10851096 ff , err = h .openFSFile (filePath , mustCompress , fileEncoding )
@@ -1112,7 +1123,7 @@ func (h *fsHandler) handleRequest(ctx *RequestCtx) {
11121123 return
11131124 }
11141125
1115- ff = h .cacheManager .SetFileToCache (fileCacheKind , originalPathStr , ff )
1126+ ff = h .cacheManager .SetFileToCache (fileCacheKind , path , ff )
11161127 }
11171128
11181129 if ! ctx .IfModifiedSince (ff .lastModified ) {
@@ -1123,6 +1134,7 @@ func (h *fsHandler) handleRequest(ctx *RequestCtx) {
11231134
11241135 r , err := ff .NewReader ()
11251136 if err != nil {
1137+ ff .decReadersCount ()
11261138 ctx .Logger ().Printf ("cannot obtain file reader for path=%q: %v" , path , err )
11271139 ctx .Error ("Internal Server Error" , StatusInternalServerError )
11281140 return
0 commit comments