Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
B
beego
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
beego
Commits
9b725c73
Commit
9b725c73
authored
Nov 08, 2015
by
astaxie
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1376 from JessonChan/develop
static file code refactor and bug fixed
parents
dc3e324f
860568cb
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
100 additions
and
101 deletions
+100
-101
config.go
config.go
+12
-11
output.go
context/output.go
+2
-14
memzipfile.go
memzipfile.go
+25
-25
staticfile.go
staticfile.go
+61
-51
No files found.
config.go
View file @
9b725c73
...
...
@@ -523,18 +523,19 @@ func ParseConfig() (err error) {
if
sgz
:=
AppConfig
.
String
(
"StaticExtensionsToGzip"
);
sgz
!=
""
{
extensions
:=
strings
.
Split
(
sgz
,
","
)
if
len
(
extensions
)
>
0
{
StaticExtensionsToGzip
=
[]
string
{}
for
_
,
ext
:=
range
extensions
{
if
len
(
ext
)
==
0
{
continue
}
extWithDot
:=
ext
if
extWithDot
[
:
1
]
!=
"."
{
extWithDot
=
"."
+
extWithDot
}
StaticExtensionsToGzip
=
append
(
StaticExtensionsToGzip
,
extWithDot
)
fileExts
:=
[]
string
{}
for
_
,
ext
:=
range
extensions
{
ext
=
strings
.
TrimSpace
(
ext
)
if
ext
==
""
{
continue
}
if
!
strings
.
HasPrefix
(
ext
,
"."
)
{
ext
=
"."
+
ext
}
fileExts
=
append
(
fileExts
,
ext
)
}
if
len
(
fileExts
)
>
0
{
StaticExtensionsToGzip
=
fileExts
}
}
...
...
context/output.go
View file @
9b725c73
...
...
@@ -103,22 +103,10 @@ func (output *BeegoOutput) Cookie(name string, value string, others ...interface
//fix cookie not work in IE
if
len
(
others
)
>
0
{
switch
v
:=
others
[
0
]
.
(
type
)
{
case
int
:
case
int
,
int32
,
int64
:
if
v
>
0
{
fmt
.
Fprintf
(
&
b
,
"; Expires=%s; Max-Age=%d"
,
time
.
Now
()
.
Add
(
time
.
Duration
(
v
)
*
time
.
Second
)
.
UTC
()
.
Format
(
time
.
RFC1123
),
v
)
}
else
if
v
<
0
{
fmt
.
Fprintf
(
&
b
,
"; Max-Age=0"
)
}
case
int64
:
if
v
>
0
{
fmt
.
Fprintf
(
&
b
,
"; Expires=%s; Max-Age=%d"
,
time
.
Now
()
.
Add
(
time
.
Duration
(
v
)
*
time
.
Second
)
.
UTC
()
.
Format
(
time
.
RFC1123
),
v
)
}
else
if
v
<
0
{
fmt
.
Fprintf
(
&
b
,
"; Max-Age=0"
)
}
case
int32
:
if
v
>
0
{
fmt
.
Fprintf
(
&
b
,
"; Expires=%s; Max-Age=%d"
,
time
.
Now
()
.
Add
(
time
.
Duration
(
v
)
*
time
.
Second
)
.
UTC
()
.
Format
(
time
.
RFC1123
),
v
)
}
else
if
v
<
0
{
}
else
if
v
<=
0
{
fmt
.
Fprintf
(
&
b
,
"; Max-Age=0"
)
}
}
...
...
memzipfile.go
View file @
9b725c73
...
...
@@ -29,72 +29,72 @@ import (
)
var
(
gmfim
=
make
(
map
[
string
]
*
memFileInfo
)
lock
sync
.
RWMutex
menFileInfoMap
=
make
(
map
[
string
]
*
memFileInfo
)
lock
sync
.
RWMutex
)
//
O
penMemZipFile returns MemFile object with a compressed static file.
//
o
penMemZipFile returns MemFile object with a compressed static file.
// it's used for serve static file if gzip enable.
func
openMemZipFile
(
path
string
,
zip
string
)
(
*
memFile
,
error
)
{
os
f
ile
,
e
:=
os
.
Open
(
path
)
os
F
ile
,
e
:=
os
.
Open
(
path
)
if
e
!=
nil
{
return
nil
,
e
}
defer
os
f
ile
.
Close
()
defer
os
F
ile
.
Close
()
os
fileinfo
,
e
:=
osf
ile
.
Stat
()
os
FileInfo
,
e
:=
osF
ile
.
Stat
()
if
e
!=
nil
{
return
nil
,
e
}
mod
time
:=
osfilei
nfo
.
ModTime
()
fileSize
:=
os
filei
nfo
.
Size
()
mod
Time
:=
osFileI
nfo
.
ModTime
()
fileSize
:=
os
FileI
nfo
.
Size
()
lock
.
RLock
()
cfi
,
ok
:=
gmfim
[
zip
+
":"
+
path
]
cfi
,
ok
:=
menFileInfoMap
[
zip
+
":"
+
path
]
lock
.
RUnlock
()
if
!
(
ok
&&
cfi
.
ModTime
()
==
mod
t
ime
&&
cfi
.
fileSize
==
fileSize
)
{
if
!
(
ok
&&
cfi
.
ModTime
()
==
mod
T
ime
&&
cfi
.
fileSize
==
fileSize
)
{
var
content
[]
byte
if
zip
==
"gzip"
{
var
zip
b
uf
bytes
.
Buffer
gzip
writer
,
e
:=
gzip
.
NewWriterLevel
(
&
zipb
uf
,
gzip
.
BestCompression
)
var
zip
B
uf
bytes
.
Buffer
gzip
Writer
,
e
:=
gzip
.
NewWriterLevel
(
&
zipB
uf
,
gzip
.
BestCompression
)
if
e
!=
nil
{
return
nil
,
e
}
_
,
e
=
io
.
Copy
(
gzip
writer
,
osf
ile
)
gzip
w
riter
.
Close
()
_
,
e
=
io
.
Copy
(
gzip
Writer
,
osF
ile
)
gzip
W
riter
.
Close
()
if
e
!=
nil
{
return
nil
,
e
}
content
,
e
=
ioutil
.
ReadAll
(
&
zip
b
uf
)
content
,
e
=
ioutil
.
ReadAll
(
&
zip
B
uf
)
if
e
!=
nil
{
return
nil
,
e
}
}
else
if
zip
==
"deflate"
{
var
zip
b
uf
bytes
.
Buffer
deflate
writer
,
e
:=
flate
.
NewWriter
(
&
zipb
uf
,
flate
.
BestCompression
)
var
zip
B
uf
bytes
.
Buffer
deflate
Writer
,
e
:=
flate
.
NewWriter
(
&
zipB
uf
,
flate
.
BestCompression
)
if
e
!=
nil
{
return
nil
,
e
}
_
,
e
=
io
.
Copy
(
deflate
writer
,
osf
ile
)
deflate
w
riter
.
Close
()
_
,
e
=
io
.
Copy
(
deflate
Writer
,
osF
ile
)
deflate
W
riter
.
Close
()
if
e
!=
nil
{
return
nil
,
e
}
content
,
e
=
ioutil
.
ReadAll
(
&
zip
b
uf
)
content
,
e
=
ioutil
.
ReadAll
(
&
zip
B
uf
)
if
e
!=
nil
{
return
nil
,
e
}
}
else
{
content
,
e
=
ioutil
.
ReadAll
(
os
f
ile
)
content
,
e
=
ioutil
.
ReadAll
(
os
F
ile
)
if
e
!=
nil
{
return
nil
,
e
}
}
cfi
=
&
memFileInfo
{
os
fileinfo
,
modt
ime
,
content
,
int64
(
len
(
content
)),
fileSize
}
cfi
=
&
memFileInfo
{
os
FileInfo
,
modT
ime
,
content
,
int64
(
len
(
content
)),
fileSize
}
lock
.
Lock
()
defer
lock
.
Unlock
()
gmfim
[
zip
+
":"
+
path
]
=
cfi
menFileInfoMap
[
zip
+
":"
+
path
]
=
cfi
}
return
&
memFile
{
fi
:
cfi
,
offset
:
0
},
nil
}
...
...
@@ -139,7 +139,7 @@ func (fi *memFileInfo) Sys() interface{} {
return
nil
}
//
M
emFile contains MemFileInfo and bytes offset when reading.
//
m
emFile contains MemFileInfo and bytes offset when reading.
// it implements io.Reader,io.ReadCloser and io.Seeker.
type
memFile
struct
{
fi
*
memFileInfo
...
...
@@ -198,7 +198,7 @@ func (f *memFile) Seek(offset int64, whence int) (ret int64, err error) {
return
f
.
offset
,
nil
}
//
G
etAcceptEncodingZip returns accept encoding format in http header.
//
g
etAcceptEncodingZip returns accept encoding format in http header.
// zip is first, then deflate if both accepted.
// If no accepted, return empty string.
func
getAcceptEncodingZip
(
r
*
http
.
Request
)
string
{
...
...
staticfile.go
View file @
9b725c73
...
...
@@ -31,97 +31,107 @@ func serverStaticRouter(ctx *context.Context) {
return
}
requestPath
:=
filepath
.
Clean
(
ctx
.
Input
.
Request
.
URL
.
Path
)
i
:=
0
for
prefix
,
staticDir
:=
range
StaticDir
{
if
len
(
prefix
)
==
0
{
continue
// special processing : favicon.ico/robots.txt can be in any static dir
if
requestPath
==
"/favicon.ico"
||
requestPath
==
"/robots.txt"
{
file
:=
path
.
Join
(
"."
,
requestPath
)
if
utils
.
FileExists
(
file
)
{
http
.
ServeFile
(
ctx
.
ResponseWriter
,
ctx
.
Request
,
file
)
return
}
if
requestPath
==
"/favicon.ico"
||
requestPath
==
"/robots.txt"
{
for
_
,
staticDir
:=
range
StaticDir
{
file
:=
path
.
Join
(
staticDir
,
requestPath
)
if
utils
.
FileExists
(
file
)
{
http
.
ServeFile
(
ctx
.
ResponseWriter
,
ctx
.
Request
,
file
)
return
}
i
++
if
i
==
len
(
StaticDir
)
{
http
.
NotFound
(
ctx
.
ResponseWriter
,
ctx
.
Request
)
return
}
}
http
.
NotFound
(
ctx
.
ResponseWriter
,
ctx
.
Request
)
return
}
for
prefix
,
staticDir
:=
range
StaticDir
{
if
len
(
prefix
)
==
0
{
continue
}
if
strings
.
HasPrefix
(
requestPath
,
prefix
)
{
if
len
(
requestPath
)
>
len
(
prefix
)
&&
requestPath
[
len
(
prefix
)]
!=
'/'
{
continue
}
file
:=
path
.
Join
(
staticDir
,
requestPath
[
len
(
prefix
)
:
])
fi
nfo
,
err
:=
os
.
Stat
(
file
)
file
Path
:=
path
.
Join
(
staticDir
,
requestPath
[
len
(
prefix
)
:
])
fi
leInfo
,
err
:=
os
.
Stat
(
filePath
)
if
err
!=
nil
{
if
RunMode
==
"dev"
{
Warn
(
"Can't find the file:"
,
file
,
err
)
Warn
(
"Can't find the file:"
,
file
Path
,
err
)
}
http
.
NotFound
(
ctx
.
ResponseWriter
,
ctx
.
Request
)
return
}
//if the request is dir and DirectoryIndex is false then
if
finfo
.
IsDir
()
{
if
fi
leI
nfo
.
IsDir
()
{
if
!
DirectoryIndex
{
exception
(
"403"
,
ctx
)
return
}
else
if
ctx
.
Input
.
Request
.
URL
.
Path
[
len
(
ctx
.
Input
.
Request
.
URL
.
Path
)
-
1
]
!=
'/'
{
}
if
ctx
.
Input
.
Request
.
URL
.
Path
[
len
(
ctx
.
Input
.
Request
.
URL
.
Path
)
-
1
]
!=
'/'
{
http
.
Redirect
(
ctx
.
ResponseWriter
,
ctx
.
Request
,
ctx
.
Input
.
Request
.
URL
.
Path
+
"/"
,
302
)
return
}
}
else
if
strings
.
HasSuffix
(
requestPath
,
"/index.html"
)
{
file
:=
path
.
Join
(
staticDir
,
requestPath
)
if
utils
.
FileExists
(
file
)
{
oFile
,
err
:=
os
.
Open
(
file
)
if
err
!=
nil
{
if
RunMode
==
"dev"
{
Warn
(
"Can't open the file:"
,
file
,
err
)
}
http
.
NotFound
(
ctx
.
ResponseWriter
,
ctx
.
Request
)
}
if
strings
.
HasSuffix
(
requestPath
,
"/index.html"
)
{
fileReader
,
err
:=
os
.
Open
(
filePath
)
if
err
!=
nil
{
if
RunMode
==
"dev"
{
Warn
(
"Can't open the file:"
,
filePath
,
err
)
}
defer
oFile
.
Close
()
http
.
ServeContent
(
ctx
.
ResponseWriter
,
ctx
.
Request
,
file
,
finfo
.
ModTime
(),
oFile
)
http
.
NotFound
(
ctx
.
ResponseWriter
,
ctx
.
Request
)
return
}
defer
fileReader
.
Close
()
http
.
ServeContent
(
ctx
.
ResponseWriter
,
ctx
.
Request
,
filePath
,
fileInfo
.
ModTime
(),
fileReader
)
return
}
//This block obtained from (https://github.com/smithfox/beego) - it should probably get merged into astaxie/beego after a pull request
isStaticFileToCompress
:=
false
if
StaticExtensionsToGzip
!=
nil
&&
len
(
StaticExtensionsToGzip
)
>
0
{
for
_
,
statExtension
:=
range
StaticExtensionsToGzip
{
if
strings
.
HasSuffix
(
strings
.
ToLower
(
file
),
strings
.
ToLower
(
statExtension
))
{
isStaticFileToCompress
=
true
break
}
for
_
,
statExtension
:=
range
StaticExtensionsToGzip
{
if
strings
.
HasSuffix
(
strings
.
ToLower
(
filePath
),
strings
.
ToLower
(
statExtension
))
{
isStaticFileToCompress
=
true
break
}
}
if
isStaticFileToCompress
{
var
contentEncoding
string
if
EnableGzip
{
contentEncoding
=
getAcceptEncodingZip
(
ctx
.
Request
)
}
if
!
isStaticFileToCompress
{
http
.
ServeFile
(
ctx
.
ResponseWriter
,
ctx
.
Request
,
filePath
)
return
}
memzipfile
,
err
:=
openMemZipFile
(
file
,
contentEncoding
)
if
err
!=
nil
{
return
}
//to compress file
var
contentEncoding
string
if
EnableGzip
{
contentEncoding
=
getAcceptEncodingZip
(
ctx
.
Request
)
}
if
contentEncoding
==
"gzip"
{
ctx
.
Output
.
Header
(
"Content-Encoding"
,
"gzip"
)
}
else
if
contentEncoding
==
"deflate"
{
ctx
.
Output
.
Header
(
"Content-Encoding"
,
"deflate"
)
}
else
{
ctx
.
Output
.
Header
(
"Content-Length"
,
strconv
.
FormatInt
(
finfo
.
Size
(),
10
))
memZipFile
,
err
:=
openMemZipFile
(
filePath
,
contentEncoding
)
if
err
!=
nil
{
if
RunMode
==
"dev"
{
Warn
(
"Can't compress the file:"
,
filePath
,
err
)
}
http
.
NotFound
(
ctx
.
ResponseWriter
,
ctx
.
Request
)
return
}
http
.
ServeContent
(
ctx
.
ResponseWriter
,
ctx
.
Request
,
file
,
finfo
.
ModTime
(),
memzipfile
)
if
contentEncoding
==
"gzip"
{
ctx
.
Output
.
Header
(
"Content-Encoding"
,
"gzip"
)
}
else
if
contentEncoding
==
"deflate"
{
ctx
.
Output
.
Header
(
"Content-Encoding"
,
"deflate"
)
}
else
{
http
.
ServeFile
(
ctx
.
ResponseWriter
,
ctx
.
Request
,
file
)
ctx
.
Output
.
Header
(
"Content-Length"
,
strconv
.
FormatInt
(
fileInfo
.
Size
(),
10
)
)
}
http
.
ServeContent
(
ctx
.
ResponseWriter
,
ctx
.
Request
,
filePath
,
fileInfo
.
ModTime
(),
memZipFile
)
return
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment