Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
caddy
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
caddy
Commits
a8818388
Commit
a8818388
authored
May 25, 2015
by
Abiola Ibrahim
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #88 from zmb3/lintwarnings
Fix lint warnings
parents
e42c6bf0
e4b50aa8
Changes
27
Hide whitespace changes
Inline
Side-by-side
Showing
27 changed files
with
201 additions
and
196 deletions
+201
-196
app/app.go
app/app.go
+5
-5
config/config.go
config/config.go
+2
-1
config/parse/lexer.go
config/parse/lexer.go
+1
-2
config/setup/git.go
config/setup/git.go
+27
-27
config/setup/git_test.go
config/setup/git_test.go
+11
-11
config/setup/log.go
config/setup/log.go
+6
-5
middleware/basicauth/basicauth.go
middleware/basicauth/basicauth.go
+3
-5
middleware/basicauth/basicauth_test.go
middleware/basicauth/basicauth_test.go
+5
-13
middleware/browse/browse.go
middleware/browse/browse.go
+2
-0
middleware/extensions/ext.go
middleware/extensions/ext.go
+1
-1
middleware/fastcgi/fcgiclient.go
middleware/fastcgi/fcgiclient.go
+46
-47
middleware/git/git.go
middleware/git/git.go
+18
-18
middleware/git/git_test.go
middleware/git/git_test.go
+10
-10
middleware/gzip/gzip.go
middleware/gzip/gzip.go
+1
-2
middleware/internal/internal.go
middleware/internal/internal.go
+2
-3
middleware/log/log.go
middleware/log/log.go
+4
-2
middleware/markdown/markdown.go
middleware/markdown/markdown.go
+7
-8
middleware/markdown/metadata.go
middleware/markdown/metadata.go
+6
-6
middleware/path.go
middleware/path.go
+2
-0
middleware/proxy/policy.go
middleware/proxy/policy.go
+9
-5
middleware/proxy/proxy.go
middleware/proxy/proxy.go
+10
-6
middleware/proxy/upstream.go
middleware/proxy/upstream.go
+8
-8
middleware/rewrite/rewrite.go
middleware/rewrite/rewrite.go
+3
-2
middleware/rewrite/rewrite_test.go
middleware/rewrite/rewrite_test.go
+2
-1
middleware/websockets/websockets.go
middleware/websockets/websockets.go
+5
-3
server/fileserver.go
server/fileserver.go
+4
-3
server/server.go
server/server.go
+1
-2
No files found.
app/app.go
View file @
a8818388
...
...
@@ -16,10 +16,10 @@ import (
)
const
(
//
P
rogram name
//
Name is the p
rogram name
Name
=
"Caddy"
//
P
rogram version
//
Version is the p
rogram version
Version
=
"0.6.0"
)
...
...
@@ -27,13 +27,13 @@ var (
// Servers is a list of all the currently-listening servers
Servers
[]
*
server
.
Server
//
This m
utex protects the Servers slice during changes
//
ServersM
utex protects the Servers slice during changes
ServersMutex
sync
.
Mutex
// W
aiting on Wg will block until all listeners have shut down.
// W
g is used to wait for all servers to shut down
Wg
sync
.
WaitGroup
//
W
hether HTTP2 is enabled or not
//
Http2 indicates w
hether HTTP2 is enabled or not
Http2
bool
// TODO: temporary flag until http2 is standard
// Quiet mode hides non-error initialization output
...
...
config/config.go
View file @
a8818388
...
...
@@ -19,7 +19,8 @@ const (
DefaultPort
=
"2015"
DefaultRoot
=
"."
// The default configuration file to load if none is specified
// DefaultConfigFile is the name of the configuration file that is loaded
// by default if no other file is specified.
DefaultConfigFile
=
"Caddyfile"
)
...
...
config/parse/lexer.go
View file @
a8818388
...
...
@@ -58,9 +58,8 @@ func (l *lexer) next() bool {
}
if
err
==
io
.
EOF
{
return
false
}
else
{
panic
(
err
)
}
panic
(
err
)
}
if
quoted
{
...
...
config/setup/git.go
View file @
a8818388
...
...
@@ -57,7 +57,7 @@ func gitParse(c *Controller) (*git.Repo, error) {
repo
.
Path
=
filepath
.
Clean
(
c
.
Root
+
string
(
filepath
.
Separator
)
+
args
[
1
])
fallthrough
case
1
:
repo
.
U
rl
=
args
[
0
]
repo
.
U
RL
=
args
[
0
]
}
for
c
.
NextBlock
()
{
...
...
@@ -66,7 +66,7 @@ func gitParse(c *Controller) (*git.Repo, error) {
if
!
c
.
NextArg
()
{
return
nil
,
c
.
ArgErr
()
}
repo
.
U
rl
=
c
.
Val
()
repo
.
U
RL
=
c
.
Val
()
case
"path"
:
if
!
c
.
NextArg
()
{
return
nil
,
c
.
ArgErr
()
...
...
@@ -103,19 +103,19 @@ func gitParse(c *Controller) (*git.Repo, error) {
}
// if repo is not specified, return error
if
repo
.
U
rl
==
""
{
if
repo
.
U
RL
==
""
{
return
nil
,
c
.
ArgErr
()
}
// if private key is not specified, convert repository
url
to https
// if private key is not specified, convert repository
URL
to https
// to avoid ssh authentication
// else validate git
url
// else validate git
URL
// Note: private key support not yet available on Windows
var
err
error
if
repo
.
KeyPath
==
""
{
repo
.
U
rl
,
repo
.
Host
,
err
=
sanitizeHttp
(
repo
.
Url
)
repo
.
U
RL
,
repo
.
Host
,
err
=
sanitizeHTTP
(
repo
.
URL
)
}
else
{
repo
.
U
rl
,
repo
.
Host
,
err
=
sanitizeGit
(
repo
.
Url
)
repo
.
U
RL
,
repo
.
Host
,
err
=
sanitizeGit
(
repo
.
URL
)
// TODO add Windows support for private repos
if
runtime
.
GOOS
==
"windows"
{
return
nil
,
fmt
.
Errorf
(
"Private repository not yet supported on Windows"
)
...
...
@@ -134,12 +134,12 @@ func gitParse(c *Controller) (*git.Repo, error) {
return
repo
,
repo
.
Prepare
()
}
// sanitizeH
ttp cleans up repository url
and converts to https format
// sanitizeH
TTP cleans up repository URL
and converts to https format
// if currently in ssh format.
// Returns sanitized url, hostName (e.g. github.com, bitbucket.com)
// and possible error
func
sanitizeH
ttp
(
repoUrl
string
)
(
string
,
string
,
error
)
{
url
,
err
:=
url
.
Parse
(
repoU
rl
)
func
sanitizeH
TTP
(
repoURL
string
)
(
string
,
string
,
error
)
{
url
,
err
:=
url
.
Parse
(
repoU
RL
)
if
err
!=
nil
{
return
""
,
""
,
err
}
...
...
@@ -148,46 +148,46 @@ func sanitizeHttp(repoUrl string) (string, string, error) {
url
.
Path
=
url
.
Path
[
len
(
"git@"
)
:
]
i
:=
strings
.
Index
(
url
.
Path
,
":"
)
if
i
<
0
{
return
""
,
""
,
fmt
.
Errorf
(
"Invalid git url %s"
,
repoU
rl
)
return
""
,
""
,
fmt
.
Errorf
(
"Invalid git url %s"
,
repoU
RL
)
}
url
.
Host
=
url
.
Path
[
:
i
]
url
.
Path
=
"/"
+
url
.
Path
[
i
+
1
:
]
}
repoU
rl
=
"https://"
+
url
.
Host
+
url
.
Path
repoU
RL
=
"https://"
+
url
.
Host
+
url
.
Path
// add .git suffix if missing
if
!
strings
.
HasSuffix
(
repoU
rl
,
".git"
)
{
repoU
rl
+=
".git"
if
!
strings
.
HasSuffix
(
repoU
RL
,
".git"
)
{
repoU
RL
+=
".git"
}
return
repoU
rl
,
url
.
Host
,
nil
return
repoU
RL
,
url
.
Host
,
nil
}
// sanitizeGit cleans up repository url and converts to ssh format for private
// repositories if required.
// Returns sanitized url, hostName (e.g. github.com, bitbucket.com)
// and possible error
func
sanitizeGit
(
repoU
rl
string
)
(
string
,
string
,
error
)
{
repoU
rl
=
strings
.
TrimSpace
(
repoUrl
)
func
sanitizeGit
(
repoU
RL
string
)
(
string
,
string
,
error
)
{
repoU
RL
=
strings
.
TrimSpace
(
repoURL
)
// check if valid ssh format
if
!
strings
.
HasPrefix
(
repoU
rl
,
"git@"
)
||
strings
.
Index
(
repoUrl
,
":"
)
<
len
(
"git@a:"
)
{
if
!
strings
.
HasPrefix
(
repoU
RL
,
"git@"
)
||
strings
.
Index
(
repoURL
,
":"
)
<
len
(
"git@a:"
)
{
// check if valid http format and convert to ssh
if
url
,
err
:=
url
.
Parse
(
repoU
rl
);
err
==
nil
&&
strings
.
HasPrefix
(
url
.
Scheme
,
"http"
)
{
repoU
rl
=
fmt
.
Sprintf
(
"git@%v:%v"
,
url
.
Host
,
url
.
Path
[
1
:
])
if
url
,
err
:=
url
.
Parse
(
repoU
RL
);
err
==
nil
&&
strings
.
HasPrefix
(
url
.
Scheme
,
"http"
)
{
repoU
RL
=
fmt
.
Sprintf
(
"git@%v:%v"
,
url
.
Host
,
url
.
Path
[
1
:
])
}
else
{
return
""
,
""
,
fmt
.
Errorf
(
"Invalid git url %s"
,
repoU
rl
)
return
""
,
""
,
fmt
.
Errorf
(
"Invalid git url %s"
,
repoU
RL
)
}
}
hostU
rl
:=
repoUrl
[
len
(
"git@"
)
:
]
i
:=
strings
.
Index
(
hostU
rl
,
":"
)
host
:=
hostU
rl
[
:
i
]
hostU
RL
:=
repoURL
[
len
(
"git@"
)
:
]
i
:=
strings
.
Index
(
hostU
RL
,
":"
)
host
:=
hostU
RL
[
:
i
]
// add .git suffix if missing
if
!
strings
.
HasSuffix
(
repoU
rl
,
".git"
)
{
repoU
rl
+=
".git"
if
!
strings
.
HasSuffix
(
repoU
RL
,
".git"
)
{
repoU
RL
+=
".git"
}
return
repoU
rl
,
host
,
nil
return
repoU
RL
,
host
,
nil
}
config/setup/git_test.go
View file @
a8818388
...
...
@@ -32,29 +32,29 @@ func TestGitParse(t *testing.T) {
expected
*
git
.
Repo
}{
{
`git git@github.com:user/repo`
,
false
,
&
git
.
Repo
{
U
rl
:
"https://github.com/user/repo.git"
,
U
RL
:
"https://github.com/user/repo.git"
,
}},
{
`git github.com/user/repo`
,
false
,
&
git
.
Repo
{
U
rl
:
"https://github.com/user/repo.git"
,
U
RL
:
"https://github.com/user/repo.git"
,
}},
{
`git git@github.com/user/repo`
,
true
,
nil
},
{
`git http://github.com/user/repo`
,
false
,
&
git
.
Repo
{
U
rl
:
"https://github.com/user/repo.git"
,
U
RL
:
"https://github.com/user/repo.git"
,
}},
{
`git https://github.com/user/repo`
,
false
,
&
git
.
Repo
{
U
rl
:
"https://github.com/user/repo.git"
,
U
RL
:
"https://github.com/user/repo.git"
,
}},
{
`git http://github.com/user/repo {
key ~/.key
}`
,
false
,
&
git
.
Repo
{
KeyPath
:
"~/.key"
,
U
rl
:
"git@github.com:user/repo.git"
,
U
RL
:
"git@github.com:user/repo.git"
,
}},
{
`git git@github.com:user/repo {
key ~/.key
}`
,
false
,
&
git
.
Repo
{
KeyPath
:
"~/.key"
,
U
rl
:
"git@github.com:user/repo.git"
,
U
RL
:
"git@github.com:user/repo.git"
,
}},
{
`git `
,
true
,
nil
},
{
`git {
...
...
@@ -66,7 +66,7 @@ func TestGitParse(t *testing.T) {
key ~/.key
}`
,
false
,
&
git
.
Repo
{
KeyPath
:
"~/.key"
,
U
rl
:
"git@github.com:user/repo.git"
,
U
RL
:
"git@github.com:user/repo.git"
,
}},
{
`git {
repo git@github.com:user/repo
...
...
@@ -74,7 +74,7 @@ func TestGitParse(t *testing.T) {
interval 600
}`
,
false
,
&
git
.
Repo
{
KeyPath
:
"~/.key"
,
U
rl
:
"git@github.com:user/repo.git"
,
U
RL
:
"git@github.com:user/repo.git"
,
Interval
:
time
.
Second
*
600
,
}},
{
`git {
...
...
@@ -82,7 +82,7 @@ func TestGitParse(t *testing.T) {
branch dev
}`
,
false
,
&
git
.
Repo
{
Branch
:
"dev"
,
U
rl
:
"https://github.com/user/repo.git"
,
U
RL
:
"https://github.com/user/repo.git"
,
}},
{
`git {
key ~/.key
...
...
@@ -93,7 +93,7 @@ func TestGitParse(t *testing.T) {
then echo hello world
}`
,
false
,
&
git
.
Repo
{
KeyPath
:
"~/.key"
,
U
rl
:
"git@github.com:user/repo.git"
,
U
RL
:
"git@github.com:user/repo.git"
,
Then
:
"echo hello world"
,
}},
}
...
...
@@ -137,7 +137,7 @@ func reposEqual(expected, repo *git.Repo) bool {
if
expected
.
Then
!=
""
&&
expected
.
Then
!=
repo
.
Then
{
return
false
}
if
expected
.
U
rl
!=
""
&&
expected
.
Url
!=
repo
.
Url
{
if
expected
.
U
RL
!=
""
&&
expected
.
URL
!=
repo
.
URL
{
return
false
}
return
true
...
...
config/setup/log.go
View file @
a8818388
...
...
@@ -8,6 +8,7 @@ import (
caddylog
"github.com/mholt/caddy/middleware/log"
)
// Log sets up the logging middleware.
func
Log
(
c
*
Controller
)
(
middleware
.
Middleware
,
error
)
{
rules
,
err
:=
logParse
(
c
)
if
err
!=
nil
{
...
...
@@ -42,22 +43,22 @@ func Log(c *Controller) (middleware.Middleware, error) {
},
nil
}
func
logParse
(
c
*
Controller
)
([]
caddylog
.
Log
Rule
,
error
)
{
var
rules
[]
caddylog
.
Log
Rule
func
logParse
(
c
*
Controller
)
([]
caddylog
.
Rule
,
error
)
{
var
rules
[]
caddylog
.
Rule
for
c
.
Next
()
{
args
:=
c
.
RemainingArgs
()
if
len
(
args
)
==
0
{
// Nothing specified; use defaults
rules
=
append
(
rules
,
caddylog
.
Log
Rule
{
rules
=
append
(
rules
,
caddylog
.
Rule
{
PathScope
:
"/"
,
OutputFile
:
caddylog
.
DefaultLogFilename
,
Format
:
caddylog
.
DefaultLogFormat
,
})
}
else
if
len
(
args
)
==
1
{
// Only an output file specified
rules
=
append
(
rules
,
caddylog
.
Log
Rule
{
rules
=
append
(
rules
,
caddylog
.
Rule
{
PathScope
:
"/"
,
OutputFile
:
args
[
0
],
Format
:
caddylog
.
DefaultLogFormat
,
...
...
@@ -78,7 +79,7 @@ func logParse(c *Controller) ([]caddylog.LogRule, error) {
}
}
rules
=
append
(
rules
,
caddylog
.
Log
Rule
{
rules
=
append
(
rules
,
caddylog
.
Rule
{
PathScope
:
args
[
0
],
OutputFile
:
args
[
1
],
Format
:
format
,
...
...
middleware/basicauth/basicauth.go
View file @
a8818388
...
...
@@ -41,16 +41,14 @@ func (a BasicAuth) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error
isAuthenticated
=
true
}
}
if
hasAuth
{
if
!
isAuthenticated
{
w
.
Header
()
.
Set
(
"WWW-Authenticate"
,
"Basic"
)
return
http
.
StatusUnauthorized
,
nil
}
else
{
// "It's an older code, sir, but it checks out. I was about to clear them."
return
a
.
Next
.
ServeHTTP
(
w
,
r
)
}
// "It's an older code, sir, but it checks out. I was about to clear them."
return
a
.
Next
.
ServeHTTP
(
w
,
r
)
}
// Pass-thru when no paths match
...
...
middleware/basicauth/basicauth_test.go
View file @
a8818388
...
...
@@ -27,13 +27,10 @@ func TestBasicAuth(t *testing.T) {
{
"/testing"
,
http
.
StatusUnauthorized
,
"ttest:test"
},
{
"/testing"
,
http
.
StatusOK
,
"test:ttest"
},
{
"/testing"
,
http
.
StatusUnauthorized
,
""
},
}
for
i
,
test
:=
range
tests
{
req
,
err
:=
http
.
NewRequest
(
"GET"
,
test
.
from
,
nil
)
if
err
!=
nil
{
t
.
Fatalf
(
"Test %d: Could not create HTTP request %v"
,
i
,
err
)
...
...
@@ -54,19 +51,17 @@ func TestBasicAuth(t *testing.T) {
headers
:=
rec
.
Header
()
if
val
,
ok
:=
headers
[
"Www-Authenticate"
];
ok
{
if
val
[
0
]
!=
"Basic"
{
t
.
Errorf
(
"Test %d, Www-Authenticate should be %s provided %s"
,
i
,
"Basic"
,
val
[
0
])
t
.
Errorf
(
"Test %d, Www-Authenticate should be %s provided %s"
,
i
,
"Basic"
,
val
[
0
])
}
}
else
{
t
.
Errorf
(
"Test %d, should provide a header Www-Authenticate"
,
i
)
}
}
}
}
func
TestMultipleOverlappingRules
(
t
*
testing
.
T
)
{
rw
:=
BasicAuth
{
Next
:
middleware
.
HandlerFunc
(
contentHandler
),
...
...
@@ -75,7 +70,7 @@ func TestMultipleOverlappingRules(t *testing.T) {
{
Username
:
"t1"
,
Password
:
"p2"
,
Resources
:
[]
string
{
"/t/t"
}},
},
}
tests
:=
[]
struct
{
from
string
result
int
...
...
@@ -89,9 +84,8 @@ func TestMultipleOverlappingRules(t *testing.T) {
{
"/t"
,
http
.
StatusUnauthorized
,
"t1:p2"
},
}
for
i
,
test
:=
range
tests
{
req
,
err
:=
http
.
NewRequest
(
"GET"
,
test
.
from
,
nil
)
if
err
!=
nil
{
t
.
Fatalf
(
"Test %d: Could not create HTTP request %v"
,
i
,
err
)
...
...
@@ -108,14 +102,12 @@ func TestMultipleOverlappingRules(t *testing.T) {
t
.
Errorf
(
"Test %d: Expected Header '%d' but was '%d'"
,
i
,
test
.
result
,
result
)
}
}
}
func
contentHandler
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
(
int
,
error
)
{
fmt
.
Fprintf
(
w
,
r
.
URL
.
String
())
return
http
.
StatusOK
,
nil
}
\ No newline at end of file
}
middleware/browse/browse.go
View file @
a8818388
...
...
@@ -55,10 +55,12 @@ type FileInfo struct {
Mode
os
.
FileMode
}
// HumanSize returns the size of the file as a human-readable string.
func
(
fi
FileInfo
)
HumanSize
()
string
{
return
humanize
.
Bytes
(
uint64
(
fi
.
Size
))
}
// HumanModTime returns the modified time of the file as a human-readable string.
func
(
fi
FileInfo
)
HumanModTime
(
format
string
)
string
{
return
fi
.
ModTime
.
Format
(
format
)
}
...
...
middleware/extensions/ext.go
View file @
a8818388
// Package extension
i
s middleware for clean URLs.
// Package extension
s contain
s middleware for clean URLs.
//
// The root path of the site is passed in as well as possible extensions
// to try internally for paths requested that don't match an existing
...
...
middleware/fastcgi/fcgiclient.go
View file @
a8818388
...
...
@@ -89,10 +89,10 @@ type header struct {
// not synchronized because we don't care what the contents are
var
pad
[
maxPad
]
byte
func
(
h
*
header
)
init
(
recType
uint8
,
reqI
d
uint16
,
contentLength
int
)
{
func
(
h
*
header
)
init
(
recType
uint8
,
reqI
D
uint16
,
contentLength
int
)
{
h
.
Version
=
1
h
.
Type
=
recType
h
.
Id
=
reqI
d
h
.
Id
=
reqI
D
h
.
ContentLength
=
uint16
(
contentLength
)
h
.
PaddingLength
=
uint8
(
-
contentLength
&
7
)
}
...
...
@@ -135,7 +135,7 @@ type FCGIClient struct {
reqId
uint16
}
//
C
onnects to the fcgi responder at the specified network address.
//
Dial c
onnects to the fcgi responder at the specified network address.
// See func net.Dial for a description of the network and address parameters.
func
Dial
(
network
,
address
string
)
(
fcgi
*
FCGIClient
,
err
error
)
{
var
conn
net
.
Conn
...
...
@@ -154,43 +154,43 @@ func Dial(network, address string) (fcgi *FCGIClient, err error) {
return
}
// Close fcgi connnection
func
(
this
*
FCGIClient
)
Close
()
{
this
.
rwc
.
Close
()
// Close
closes
fcgi connnection
func
(
c
*
FCGIClient
)
Close
()
{
c
.
rwc
.
Close
()
}
func
(
this
*
FCGIClient
)
writeRecord
(
recType
uint8
,
content
[]
byte
)
(
err
error
)
{
this
.
mutex
.
Lock
()
defer
this
.
mutex
.
Unlock
()
this
.
buf
.
Reset
()
this
.
h
.
init
(
recType
,
this
.
reqId
,
len
(
content
))
if
err
:=
binary
.
Write
(
&
this
.
buf
,
binary
.
BigEndian
,
this
.
h
);
err
!=
nil
{
func
(
c
*
FCGIClient
)
writeRecord
(
recType
uint8
,
content
[]
byte
)
(
err
error
)
{
c
.
mutex
.
Lock
()
defer
c
.
mutex
.
Unlock
()
c
.
buf
.
Reset
()
c
.
h
.
init
(
recType
,
c
.
reqId
,
len
(
content
))
if
err
:=
binary
.
Write
(
&
c
.
buf
,
binary
.
BigEndian
,
c
.
h
);
err
!=
nil
{
return
err
}
if
_
,
err
:=
this
.
buf
.
Write
(
content
);
err
!=
nil
{
if
_
,
err
:=
c
.
buf
.
Write
(
content
);
err
!=
nil
{
return
err
}
if
_
,
err
:=
this
.
buf
.
Write
(
pad
[
:
this
.
h
.
PaddingLength
]);
err
!=
nil
{
if
_
,
err
:=
c
.
buf
.
Write
(
pad
[
:
c
.
h
.
PaddingLength
]);
err
!=
nil
{
return
err
}
_
,
err
=
this
.
rwc
.
Write
(
this
.
buf
.
Bytes
())
_
,
err
=
c
.
rwc
.
Write
(
c
.
buf
.
Bytes
())
return
err
}
func
(
this
*
FCGIClient
)
writeBeginRequest
(
role
uint16
,
flags
uint8
)
error
{
func
(
c
*
FCGIClient
)
writeBeginRequest
(
role
uint16
,
flags
uint8
)
error
{
b
:=
[
8
]
byte
{
byte
(
role
>>
8
),
byte
(
role
),
flags
}
return
this
.
writeRecord
(
FCGI_BEGIN_REQUEST
,
b
[
:
])
return
c
.
writeRecord
(
FCGI_BEGIN_REQUEST
,
b
[
:
])
}
func
(
this
*
FCGIClient
)
writeEndRequest
(
appStatus
int
,
protocolStatus
uint8
)
error
{
func
(
c
*
FCGIClient
)
writeEndRequest
(
appStatus
int
,
protocolStatus
uint8
)
error
{
b
:=
make
([]
byte
,
8
)
binary
.
BigEndian
.
PutUint32
(
b
,
uint32
(
appStatus
))
b
[
4
]
=
protocolStatus
return
this
.
writeRecord
(
FCGI_END_REQUEST
,
b
)
return
c
.
writeRecord
(
FCGI_END_REQUEST
,
b
)
}
func
(
this
*
FCGIClient
)
writePairs
(
recType
uint8
,
pairs
map
[
string
]
string
)
error
{
w
:=
newWriter
(
this
,
recType
)
func
(
c
*
FCGIClient
)
writePairs
(
recType
uint8
,
pairs
map
[
string
]
string
)
error
{
w
:=
newWriter
(
c
,
recType
)
b
:=
make
([]
byte
,
8
)
nn
:=
0
for
k
,
v
:=
range
pairs
{
...
...
@@ -333,32 +333,32 @@ func (w *streamReader) Read(p []byte) (n int, err error) {
// Do made the request and returns a io.Reader that translates the data read
// from fcgi responder out of fcgi packet before returning it.
func
(
this
*
FCGIClient
)
Do
(
p
map
[
string
]
string
,
req
io
.
Reader
)
(
r
io
.
Reader
,
err
error
)
{
err
=
this
.
writeBeginRequest
(
uint16
(
FCGI_RESPONDER
),
0
)
func
(
c
*
FCGIClient
)
Do
(
p
map
[
string
]
string
,
req
io
.
Reader
)
(
r
io
.
Reader
,
err
error
)
{
err
=
c
.
writeBeginRequest
(
uint16
(
FCGI_RESPONDER
),
0
)
if
err
!=
nil
{
return
}
err
=
this
.
writePairs
(
FCGI_PARAMS
,
p
)
err
=
c
.
writePairs
(
FCGI_PARAMS
,
p
)
if
err
!=
nil
{
return
}
body
:=
newWriter
(
this
,
FCGI_STDIN
)
body
:=
newWriter
(
c
,
FCGI_STDIN
)
if
req
!=
nil
{
io
.
Copy
(
body
,
req
)
}
body
.
Close
()
r
=
&
streamReader
{
c
:
this
}
r
=
&
streamReader
{
c
:
c
}
return
}
// Request returns a HTTP Response with Header and Body
// from fcgi responder
func
(
this
*
FCGIClient
)
Request
(
p
map
[
string
]
string
,
req
io
.
Reader
)
(
resp
*
http
.
Response
,
err
error
)
{
func
(
c
*
FCGIClient
)
Request
(
p
map
[
string
]
string
,
req
io
.
Reader
)
(
resp
*
http
.
Response
,
err
error
)
{
r
,
err
:=
this
.
Do
(
p
,
req
)
r
,
err
:=
c
.
Do
(
p
,
req
)
if
err
!=
nil
{
return
}
...
...
@@ -394,40 +394,39 @@ func (this *FCGIClient) Request(p map[string]string, req io.Reader) (resp *http.
}
else
{
resp
.
Body
=
ioutil
.
NopCloser
(
rb
)
}
return
}
// Get issues a GET request to the fcgi responder.
func
(
this
*
FCGIClient
)
Get
(
p
map
[
string
]
string
)
(
resp
*
http
.
Response
,
err
error
)
{
func
(
c
*
FCGIClient
)
Get
(
p
map
[
string
]
string
)
(
resp
*
http
.
Response
,
err
error
)
{
p
[
"REQUEST_METHOD"
]
=
"GET"
p
[
"CONTENT_LENGTH"
]
=
"0"
return
this
.
Request
(
p
,
nil
)
return
c
.
Request
(
p
,
nil
)
}
// Head issues a HEAD request to the fcgi responder.
func
(
this
*
FCGIClient
)
Head
(
p
map
[
string
]
string
)
(
resp
*
http
.
Response
,
err
error
)
{
func
(
c
*
FCGIClient
)
Head
(
p
map
[
string
]
string
)
(
resp
*
http
.
Response
,
err
error
)
{
p
[
"REQUEST_METHOD"
]
=
"HEAD"
p
[
"CONTENT_LENGTH"
]
=
"0"
return
this
.
Request
(
p
,
nil
)
return
c
.
Request
(
p
,
nil
)
}
// Options issues an OPTIONS request to the fcgi responder.
func
(
this
*
FCGIClient
)
Options
(
p
map
[
string
]
string
)
(
resp
*
http
.
Response
,
err
error
)
{
func
(
c
*
FCGIClient
)
Options
(
p
map
[
string
]
string
)
(
resp
*
http
.
Response
,
err
error
)
{
p
[
"REQUEST_METHOD"
]
=
"OPTIONS"
p
[
"CONTENT_LENGTH"
]
=
"0"
return
this
.
Request
(
p
,
nil
)
return
c
.
Request
(
p
,
nil
)
}
// Post issues a POST request to the fcgi responder. with request body
// in the format that bodyType specified
func
(
this
*
FCGIClient
)
Post
(
p
map
[
string
]
string
,
bodyType
string
,
body
io
.
Reader
,
l
int
)
(
resp
*
http
.
Response
,
err
error
)
{
func
(
c
*
FCGIClient
)
Post
(
p
map
[
string
]
string
,
bodyType
string
,
body
io
.
Reader
,
l
int
)
(
resp
*
http
.
Response
,
err
error
)
{
if
len
(
p
[
"REQUEST_METHOD"
])
==
0
||
p
[
"REQUEST_METHOD"
]
==
"GET"
{
p
[
"REQUEST_METHOD"
]
=
"POST"
...
...
@@ -439,44 +438,44 @@ func (this *FCGIClient) Post(p map[string]string, bodyType string, body io.Reade
p
[
"CONTENT_TYPE"
]
=
"application/x-www-form-urlencoded"
}
return
this
.
Request
(
p
,
body
)
return
c
.
Request
(
p
,
body
)
}
// Put issues a PUT request to the fcgi responder.
func
(
this
*
FCGIClient
)
Put
(
p
map
[
string
]
string
,
bodyType
string
,
body
io
.
Reader
,
l
int
)
(
resp
*
http
.
Response
,
err
error
)
{
func
(
c
*
FCGIClient
)
Put
(
p
map
[
string
]
string
,
bodyType
string
,
body
io
.
Reader
,
l
int
)
(
resp
*
http
.
Response
,
err
error
)
{
p
[
"REQUEST_METHOD"
]
=
"PUT"
return
this
.
Post
(
p
,
bodyType
,
body
,
l
)
return
c
.
Post
(
p
,
bodyType
,
body
,
l
)
}
// Patch issues a PATCH request to the fcgi responder.
func
(
this
*
FCGIClient
)
Patch
(
p
map
[
string
]
string
,
bodyType
string
,
body
io
.
Reader
,
l
int
)
(
resp
*
http
.
Response
,
err
error
)
{
func
(
c
*
FCGIClient
)
Patch
(
p
map
[
string
]
string
,
bodyType
string
,
body
io
.
Reader
,
l
int
)
(
resp
*
http
.
Response
,
err
error
)
{
p
[
"REQUEST_METHOD"
]
=
"PATCH"
return
this
.
Post
(
p
,
bodyType
,
body
,
l
)
return
c
.
Post
(
p
,
bodyType
,
body
,
l
)
}
// Delete issues a DELETE request to the fcgi responder.
func
(
this
*
FCGIClient
)
Delete
(
p
map
[
string
]
string
,
bodyType
string
,
body
io
.
Reader
,
l
int
)
(
resp
*
http
.
Response
,
err
error
)
{
func
(
c
*
FCGIClient
)
Delete
(
p
map
[
string
]
string
,
bodyType
string
,
body
io
.
Reader
,
l
int
)
(
resp
*
http
.
Response
,
err
error
)
{
p
[
"REQUEST_METHOD"
]
=
"DELETE"
return
this
.
Post
(
p
,
bodyType
,
body
,
l
)
return
c
.
Post
(
p
,
bodyType
,
body
,
l
)
}
// PostForm issues a POST to the fcgi responder, with form
// as a string key to a list values (url.Values)
func
(
this
*
FCGIClient
)
PostForm
(
p
map
[
string
]
string
,
data
url
.
Values
)
(
resp
*
http
.
Response
,
err
error
)
{
func
(
c
*
FCGIClient
)
PostForm
(
p
map
[
string
]
string
,
data
url
.
Values
)
(
resp
*
http
.
Response
,
err
error
)
{
body
:=
bytes
.
NewReader
([]
byte
(
data
.
Encode
()))
return
this
.
Post
(
p
,
"application/x-www-form-urlencoded"
,
body
,
body
.
Len
())
return
c
.
Post
(
p
,
"application/x-www-form-urlencoded"
,
body
,
body
.
Len
())
}
// PostFile issues a POST to the fcgi responder in multipart(RFC 2046) standard,
// with form as a string key to a list values (url.Values),
// and/or with file as a string key to a list file path.
func
(
this
*
FCGIClient
)
PostFile
(
p
map
[
string
]
string
,
data
url
.
Values
,
file
map
[
string
]
string
)
(
resp
*
http
.
Response
,
err
error
)
{
func
(
c
*
FCGIClient
)
PostFile
(
p
map
[
string
]
string
,
data
url
.
Values
,
file
map
[
string
]
string
)
(
resp
*
http
.
Response
,
err
error
)
{
buf
:=
&
bytes
.
Buffer
{}
writer
:=
multipart
.
NewWriter
(
buf
)
bodyType
:=
writer
.
FormDataContentType
()
...
...
@@ -509,7 +508,7 @@ func (this *FCGIClient) PostFile(p map[string]string, data url.Values, file map[
return
}
return
this
.
Post
(
p
,
bodyType
,
buf
,
buf
.
Len
())
return
c
.
Post
(
p
,
bodyType
,
buf
,
buf
.
Len
())
}
// Checks whether chunked is part of the encodings stack
...
...
middleware/git/git.go
View file @
a8818388
...
...
@@ -28,7 +28,7 @@ var shell string
// initMutex prevents parallel attempt to validate
// git requirements.
var
initMutex
sync
.
Mutex
=
sync
.
Mutex
{}
var
initMutex
=
sync
.
Mutex
{}
// Logger is used to log errors; if nil, the default log.Logger is used.
var
Logger
*
log
.
Logger
...
...
@@ -44,7 +44,7 @@ func logger() *log.Logger {
// Repo is the structure that holds required information
// of a git repository.
type
Repo
struct
{
U
rl
string
// Repository URL
U
RL
string
// Repository URL
Path
string
// Directory to pull to
Host
string
// Git domain host e.g. github.com
Branch
string
// Git branch
...
...
@@ -94,7 +94,7 @@ func (r *Repo) Pull() error {
// Pull performs git clone, or git pull if repository exists
func
(
r
*
Repo
)
pull
()
error
{
params
:=
[]
string
{
"clone"
,
"-b"
,
r
.
Branch
,
r
.
U
rl
,
r
.
Path
}
params
:=
[]
string
{
"clone"
,
"-b"
,
r
.
Branch
,
r
.
U
RL
,
r
.
Path
}
if
r
.
pulled
{
params
=
[]
string
{
"pull"
,
"origin"
,
r
.
Branch
}
}
...
...
@@ -113,7 +113,7 @@ func (r *Repo) pull() error {
if
err
=
runCmd
(
gitBinary
,
params
,
dir
);
err
==
nil
{
r
.
pulled
=
true
r
.
lastPull
=
time
.
Now
()
logger
()
.
Printf
(
"%v pulled.
\n
"
,
r
.
U
rl
)
logger
()
.
Printf
(
"%v pulled.
\n
"
,
r
.
U
RL
)
r
.
lastCommit
,
err
=
r
.
getMostRecentCommit
()
}
return
err
...
...
@@ -122,11 +122,11 @@ func (r *Repo) pull() error {
// pullWithKey is used for private repositories and requires an ssh key.
// Note: currently only limited to Linux and OSX.
func
(
r
*
Repo
)
pullWithKey
(
params
[]
string
)
error
{
var
gitS
sh
,
script
gitos
.
File
var
gitS
SH
,
script
gitos
.
File
// ensure temporary files deleted after usage
defer
func
()
{
if
gitS
sh
!=
nil
{
gos
.
Remove
(
gitS
sh
.
Name
())
if
gitS
SH
!=
nil
{
gos
.
Remove
(
gitS
SH
.
Name
())
}
if
script
!=
nil
{
gos
.
Remove
(
script
.
Name
())
...
...
@@ -135,13 +135,13 @@ func (r *Repo) pullWithKey(params []string) error {
var
err
error
// write git.sh script to temp file
gitS
sh
,
err
=
writeScriptFile
(
gitWrapperScript
())
gitS
SH
,
err
=
writeScriptFile
(
gitWrapperScript
())
if
err
!=
nil
{
return
err
}
// write git clone bash script to file
script
,
err
=
writeScriptFile
(
bashScript
(
gitS
sh
.
Name
(),
r
,
params
))
script
,
err
=
writeScriptFile
(
bashScript
(
gitS
SH
.
Name
(),
r
,
params
))
if
err
!=
nil
{
return
err
}
...
...
@@ -154,7 +154,7 @@ func (r *Repo) pullWithKey(params []string) error {
if
err
=
runCmd
(
script
.
Name
(),
nil
,
dir
);
err
==
nil
{
r
.
pulled
=
true
r
.
lastPull
=
time
.
Now
()
logger
()
.
Printf
(
"%v pulled.
\n
"
,
r
.
U
rl
)
logger
()
.
Printf
(
"%v pulled.
\n
"
,
r
.
U
RL
)
r
.
lastCommit
,
err
=
r
.
getMostRecentCommit
()
}
return
err
...
...
@@ -181,13 +181,13 @@ func (r *Repo) Prepare() error {
if
isGit
{
// check if same repository
var
repoU
rl
string
if
repoU
rl
,
err
=
r
.
getRepoUrl
();
err
==
nil
{
var
repoU
RL
string
if
repoU
RL
,
err
=
r
.
getRepoURL
();
err
==
nil
{
// add .git suffix if missing for adequate comparison.
if
!
strings
.
HasSuffix
(
repoU
rl
,
".git"
)
{
repoU
rl
+=
".git"
if
!
strings
.
HasSuffix
(
repoU
RL
,
".git"
)
{
repoU
RL
+=
".git"
}
if
repoU
rl
==
r
.
Url
{
if
repoU
RL
==
r
.
URL
{
r
.
pulled
=
true
return
nil
}
...
...
@@ -195,7 +195,7 @@ func (r *Repo) Prepare() error {
if
err
!=
nil
{
return
fmt
.
Errorf
(
"Cannot retrieve repo url for %v Error: %v"
,
r
.
Path
,
err
)
}
return
fmt
.
Errorf
(
"Another git repo '%v' exists at %v"
,
repoU
rl
,
r
.
Path
)
return
fmt
.
Errorf
(
"Another git repo '%v' exists at %v"
,
repoU
RL
,
r
.
Path
)
}
return
fmt
.
Errorf
(
"Cannot git clone into %v, directory not empty."
,
r
.
Path
)
}
...
...
@@ -211,8 +211,8 @@ func (r *Repo) getMostRecentCommit() (string, error) {
return
runCmdOutput
(
c
,
args
,
r
.
Path
)
}
// getRepoU
rl
retrieves remote origin url for the git repository at path
func
(
r
*
Repo
)
getRepoU
rl
()
(
string
,
error
)
{
// getRepoU
RL
retrieves remote origin url for the git repository at path
func
(
r
*
Repo
)
getRepoU
RL
()
(
string
,
error
)
{
_
,
err
:=
gos
.
Stat
(
r
.
Path
)
if
err
!=
nil
{
return
""
,
err
...
...
middleware/git/git_test.go
View file @
a8818388
...
...
@@ -63,7 +63,7 @@ func TestGit(t *testing.T) {
// prepare
repos
:=
[]
*
Repo
{
nil
,
&
Repo
{
Path
:
"gitdir"
,
U
rl
:
"success.git"
},
&
Repo
{
Path
:
"gitdir"
,
U
RL
:
"success.git"
},
}
for
_
,
r
:=
range
repos
{
repo
:=
createRepo
(
r
)
...
...
@@ -79,26 +79,26 @@ func TestGit(t *testing.T) {
output
string
}{
{
&
Repo
{
Path
:
"gitdir"
,
U
rl
:
"git@github.com:user/repo.git"
,
KeyPath
:
"~/.key"
,
Then
:
"echo Hello"
},
&
Repo
{
Path
:
"gitdir"
,
U
RL
:
"git@github.com:user/repo.git"
,
KeyPath
:
"~/.key"
,
Then
:
"echo Hello"
},
`git@github.com:user/repo.git pulled.
Command echo Hello successful.
`
,
},
{
&
Repo
{
Path
:
"gitdir"
,
U
rl
:
"https://github.com/user/repo.git"
,
Then
:
"echo Hello"
},
&
Repo
{
Path
:
"gitdir"
,
U
RL
:
"https://github.com/user/repo.git"
,
Then
:
"echo Hello"
},
`https://github.com/user/repo.git pulled.
Command echo Hello successful.
`
,
},
{
&
Repo
{
U
rl
:
"git@github.com:user/repo"
},
&
Repo
{
U
RL
:
"git@github.com:user/repo"
},
`git@github.com:user/repo pulled.
`
,
},
}
for
i
,
test
:=
range
tests
{
gittest
.
CmdOutput
=
test
.
repo
.
U
rl
gittest
.
CmdOutput
=
test
.
repo
.
U
RL
test
.
repo
=
createRepo
(
test
.
repo
)
...
...
@@ -117,8 +117,8 @@ Command echo Hello successful.
// pull with error
repos
=
[]
*
Repo
{
&
Repo
{
Path
:
"gitdir"
,
U
rl
:
"http://github.com:u/repo.git"
},
&
Repo
{
Path
:
"gitdir"
,
U
rl
:
"https://github.com/user/repo.git"
,
Then
:
"echo Hello"
},
&
Repo
{
Path
:
"gitdir"
,
U
RL
:
"http://github.com:u/repo.git"
},
&
Repo
{
Path
:
"gitdir"
,
U
RL
:
"https://github.com/user/repo.git"
,
Then
:
"echo Hello"
},
&
Repo
{
Path
:
"gitdir"
},
&
Repo
{
Path
:
"gitdir"
,
KeyPath
:
".key"
},
}
...
...
@@ -143,7 +143,7 @@ Command echo Hello successful.
func
createRepo
(
r
*
Repo
)
*
Repo
{
repo
:=
&
Repo
{
U
rl
:
"git@github.com/user/test"
,
U
RL
:
"git@github.com/user/test"
,
Path
:
"."
,
Host
:
"github.com"
,
Branch
:
"master"
,
...
...
@@ -170,8 +170,8 @@ func createRepo(r *Repo) *Repo {
if
r
.
Then
!=
""
{
repo
.
Then
=
r
.
Then
}
if
r
.
U
rl
!=
""
{
repo
.
U
rl
=
r
.
Url
if
r
.
U
RL
!=
""
{
repo
.
U
RL
=
r
.
URL
}
return
repo
...
...
middleware/gzip/gzip.go
View file @
a8818388
...
...
@@ -45,9 +45,8 @@ func (g Gzip) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
gz
.
WriteHeader
(
status
)
fmt
.
Fprintf
(
gz
,
"%d %s"
,
status
,
http
.
StatusText
(
status
))
return
0
,
err
}
else
{
return
status
,
err
}
return
status
,
err
}
// gzipResponeWriter wraps the underlying Write method
...
...
middleware/internal/internal.go
View file @
a8818388
//
The p
ackage internal provides a simple middleware that (a) prevents access
//
P
ackage internal provides a simple middleware that (a) prevents access
// to internal locations and (b) allows to return files from internal location
// by setting a special header, e.g. in a proxy response.
package
internal
...
...
@@ -85,7 +85,6 @@ func (w internalResponseWriter) WriteHeader(code int) {
func
(
w
internalResponseWriter
)
Write
(
b
[]
byte
)
(
int
,
error
)
{
if
isInternalRedirect
(
w
)
{
return
0
,
nil
}
else
{
return
w
.
ResponseWriter
.
Write
(
b
)
}
return
w
.
ResponseWriter
.
Write
(
b
)
}
middleware/log/log.go
View file @
a8818388
...
...
@@ -8,9 +8,10 @@ import (
"github.com/mholt/caddy/middleware"
)
// Logger is a basic request logging middleware.
type
Logger
struct
{
Next
middleware
.
Handler
Rules
[]
Log
Rule
Rules
[]
Rule
}
func
(
l
Logger
)
ServeHTTP
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
(
int
,
error
)
{
...
...
@@ -26,7 +27,8 @@ func (l Logger) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
return
l
.
Next
.
ServeHTTP
(
w
,
r
)
}
type
LogRule
struct
{
// Rule configures the logging middleware.
type
Rule
struct
{
PathScope
string
OutputFile
string
Format
string
...
...
middleware/markdown/markdown.go
View file @
a8818388
...
...
@@ -31,9 +31,9 @@ type Markdown struct {
IndexFiles
[]
string
}
//
Helper function to check
if a file is an index file
func
(
m
Markdown
)
IsIndexFile
(
file
string
)
bool
{
for
_
,
f
:=
range
m
.
IndexFiles
{
//
IsIndexFile checks to see
if a file is an index file
func
(
m
d
Markdown
)
IsIndexFile
(
file
string
)
bool
{
for
_
,
f
:=
range
m
d
.
IndexFiles
{
if
f
==
file
{
return
true
}
...
...
@@ -105,12 +105,11 @@ func (md Markdown) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error
if
html
,
err
:=
ioutil
.
ReadFile
(
filepath
);
err
==
nil
{
w
.
Write
(
html
)
return
http
.
StatusOK
,
nil
}
else
{
if
os
.
IsPermission
(
err
)
{
return
http
.
StatusForbidden
,
err
}
return
http
.
StatusNotFound
,
nil
}
if
os
.
IsPermission
(
err
)
{
return
http
.
StatusForbidden
,
err
}
return
http
.
StatusNotFound
,
nil
}
}
}
...
...
middleware/markdown/metadata.go
View file @
a8818388
...
...
@@ -88,8 +88,8 @@ func (j *JSONMetadataParser) Parse(b []byte) ([]byte, error) {
return
buf
[
:
n
],
nil
}
//
Parsed metadata.
//
Should be called after a call to Parse returns no error
//
Metadata returns parsed metadata. It should be called
//
only after a call to Parse returns without error.
func
(
j
*
JSONMetadataParser
)
Metadata
()
Metadata
{
return
j
.
metadata
}
...
...
@@ -123,8 +123,8 @@ func (t *TOMLMetadataParser) Parse(b []byte) ([]byte, error) {
return
markdown
,
nil
}
//
Parsed metadata.
//
Should be called after a call to Parse returns no error
//
Metadata returns parsed metadata. It should be called
//
only after a call to Parse returns without error.
func
(
t
*
TOMLMetadataParser
)
Metadata
()
Metadata
{
return
t
.
metadata
}
...
...
@@ -171,8 +171,8 @@ func (y *YAMLMetadataParser) Parse(b []byte) ([]byte, error) {
return
markdown
,
nil
}
//
Parsed metadata.
//
Should be called after a call to Parse returns no error
//
Metadata returns parsed metadata. It should be called
//
only after a call to Parse returns without error.
func
(
y
*
YAMLMetadataParser
)
Metadata
()
Metadata
{
return
y
.
metadata
}
...
...
middleware/path.go
View file @
a8818388
...
...
@@ -5,6 +5,8 @@ import "strings"
// Path represents a URI path, maybe with pattern characters.
type
Path
string
// Matches checks to see if other matches p.
//
// Path matching will probably not always be a direct
// comparison; this method assures that paths can be
// easily and consistently matched.
...
...
middleware/proxy/policy.go
View file @
a8818388
...
...
@@ -5,6 +5,7 @@ import (
"sync/atomic"
)
// HostPool is a collection of UpstreamHosts.
type
HostPool
[]
*
UpstreamHost
// Policy decides how a host will be selected from a pool.
...
...
@@ -12,9 +13,10 @@ type Policy interface {
Select
(
pool
HostPool
)
*
UpstreamHost
}
//
The random policy randomly selected an up host from the pool
.
//
Random is a policy that selects up hosts from a pool at random
.
type
Random
struct
{}
// Select selects an up host at random from the specified pool.
func
(
r
*
Random
)
Select
(
pool
HostPool
)
*
UpstreamHost
{
// instead of just generating a random index
// this is done to prevent selecting a down host
...
...
@@ -37,11 +39,12 @@ func (r *Random) Select(pool HostPool) *UpstreamHost {
return
randHost
}
// The least_conn policy selects a host with the least connections.
// If multiple hosts have the least amount of connections, one is randomly
// chosen.
// LeastConn is a policy that selects the host with the least connections.
type
LeastConn
struct
{}
// Select selects the up host with the least number of connections in the
// pool. If more than one host has the same least number of connections,
// one of the hosts is chosen at random.
func
(
r
*
LeastConn
)
Select
(
pool
HostPool
)
*
UpstreamHost
{
var
bestHost
*
UpstreamHost
count
:=
0
...
...
@@ -71,11 +74,12 @@ func (r *LeastConn) Select(pool HostPool) *UpstreamHost {
return
bestHost
}
//
The round_robin policy selects a host
based on round robin ordering.
//
RoundRobin is a policy that selects hosts
based on round robin ordering.
type
RoundRobin
struct
{
Robin
uint32
}
// Select selects an up host from the pool using a round robin ordering scheme.
func
(
r
*
RoundRobin
)
Select
(
pool
HostPool
)
*
UpstreamHost
{
poolLen
:=
uint32
(
len
(
pool
))
selection
:=
atomic
.
AddUint32
(
&
r
.
Robin
,
1
)
%
poolLen
...
...
middleware/proxy/proxy.go
View file @
a8818388
...
...
@@ -19,18 +19,19 @@ type Proxy struct {
Upstreams
[]
Upstream
}
//
An u
pstream manages a pool of proxy upstream hosts. Select should return a
//
U
pstream manages a pool of proxy upstream hosts. Select should return a
// suitable upstream host, or nil if no such hosts are available.
type
Upstream
interface
{
//The path this upstream host should be routed on
//
The path this upstream host should be routed on
From
()
string
// Selects an upstream host to be routed to.
Select
()
*
UpstreamHost
}
// UpstreamHostDownFunc can be used to customize how Down behaves.
type
UpstreamHostDownFunc
func
(
*
UpstreamHost
)
bool
//
An
UpstreamHost represents a single proxy upstream
// UpstreamHost represents a single proxy upstream
type
UpstreamHost
struct
{
// The hostname of this upstream host
Name
string
...
...
@@ -43,6 +44,9 @@ type UpstreamHost struct {
CheckDown
UpstreamHostDownFunc
}
// Down checks whether the upstream host is down or not.
// Down will try to use uh.CheckDown first, and will fall
// back to some default criteria if necessary.
func
(
uh
*
UpstreamHost
)
Down
()
bool
{
if
uh
.
CheckDown
==
nil
{
// Default settings
...
...
@@ -70,10 +74,10 @@ func (p Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
proxy
:=
host
.
ReverseProxy
r
.
Host
=
host
.
Name
if
baseU
rl
,
err
:=
url
.
Parse
(
host
.
Name
);
err
==
nil
{
r
.
Host
=
baseU
rl
.
Host
if
baseU
RL
,
err
:=
url
.
Parse
(
host
.
Name
);
err
==
nil
{
r
.
Host
=
baseU
RL
.
Host
if
proxy
==
nil
{
proxy
=
NewSingleHostReverseProxy
(
baseU
rl
)
proxy
=
NewSingleHostReverseProxy
(
baseU
RL
)
}
}
else
if
proxy
==
nil
{
return
http
.
StatusInternalServerError
,
err
...
...
middleware/proxy/upstream.go
View file @
a8818388
package
proxy
import
(
"github.com/mholt/caddy/config/parse"
"io"
"io/ioutil"
"net/http"
...
...
@@ -9,6 +8,8 @@ import (
"strconv"
"strings"
"time"
"github.com/mholt/caddy/config/parse"
)
type
staticUpstream
struct
{
...
...
@@ -24,7 +25,7 @@ type staticUpstream struct {
}
}
//
n
ewStaticUpstreams parses the configuration input and sets up
//
N
ewStaticUpstreams parses the configuration input and sets up
// static upstreams for the proxy middleware.
func
NewStaticUpstreams
(
c
parse
.
Dispenser
)
([]
Upstream
,
error
)
{
var
upstreams
[]
Upstream
...
...
@@ -130,8 +131,8 @@ func NewStaticUpstreams(c parse.Dispenser) ([]Upstream, error) {
}
}(
upstream
),
}
if
baseU
rl
,
err
:=
url
.
Parse
(
uh
.
Name
);
err
==
nil
{
uh
.
ReverseProxy
=
NewSingleHostReverseProxy
(
baseU
rl
)
if
baseU
RL
,
err
:=
url
.
Parse
(
uh
.
Name
);
err
==
nil
{
uh
.
ReverseProxy
=
NewSingleHostReverseProxy
(
baseU
RL
)
}
else
{
return
upstreams
,
err
}
...
...
@@ -152,8 +153,8 @@ func (u *staticUpstream) From() string {
func
(
u
*
staticUpstream
)
healthCheck
()
{
for
_
,
host
:=
range
u
.
Hosts
{
hostU
rl
:=
host
.
Name
+
u
.
HealthCheck
.
Path
if
r
,
err
:=
http
.
Get
(
hostU
rl
);
err
==
nil
{
hostU
RL
:=
host
.
Name
+
u
.
HealthCheck
.
Path
if
r
,
err
:=
http
.
Get
(
hostU
RL
);
err
==
nil
{
io
.
Copy
(
ioutil
.
Discard
,
r
.
Body
)
r
.
Body
.
Close
()
host
.
Unhealthy
=
r
.
StatusCode
<
200
||
r
.
StatusCode
>=
400
...
...
@@ -199,7 +200,6 @@ func (u *staticUpstream) Select() *UpstreamHost {
if
u
.
Policy
==
nil
{
return
(
&
Random
{})
.
Select
(
pool
)
}
else
{
return
u
.
Policy
.
Select
(
pool
)
}
return
u
.
Policy
.
Select
(
pool
)
}
middleware/rewrite/rewrite.go
View file @
a8818388
...
...
@@ -6,12 +6,13 @@ import (
"net/http"
"fmt"
"github.com/mholt/caddy/middleware"
"net/url"
"path"
"path/filepath"
"regexp"
"strings"
"github.com/mholt/caddy/middleware"
)
// Rewrite is middleware to rewrite request locations internally before being handled.
...
...
@@ -96,7 +97,7 @@ func NewRegexpRule(base, pattern, to string, ext []string) (*RegexpRule, error)
}
// regexpVars are variables that can be used for To (rewrite destination path).
var
regexpVars
[]
string
=
[]
string
{
var
regexpVars
=
[]
string
{
"{path}"
,
"{query}"
,
"{file}"
,
...
...
middleware/rewrite/rewrite_test.go
View file @
a8818388
...
...
@@ -6,8 +6,9 @@ import (
"net/http/httptest"
"testing"
"github.com/mholt/caddy/middleware"
"strings"
"github.com/mholt/caddy/middleware"
)
func
TestRewrite
(
t
*
testing
.
T
)
{
...
...
middleware/websockets/websockets.go
View file @
a8818388
...
...
@@ -22,7 +22,7 @@ type (
Sockets
[]
Config
}
//
WS
Config holds the configuration for a single websocket
// Config holds the configuration for a single websocket
// endpoint which may serve multiple websocket connections.
Config
struct
{
Path
string
...
...
@@ -50,9 +50,11 @@ func (ws WebSockets) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, err
}
var
(
// See CGI spec, 4.1.4
// GatewayInterface is the dialect of CGI being used by the server
// to communicate with the script. See CGI spec, 4.1.4
GatewayInterface
string
// See CGI spec, 4.1.17
// ServerSoftware is the name and version of the information server
// software making the CGI request. See CGI spec, 4.1.17
ServerSoftware
string
)
server/fileserver.go
View file @
a8818388
...
...
@@ -10,7 +10,7 @@ import (
"github.com/mholt/caddy/middleware/browse"
)
//
This
FileServer is adapted from the one in net/http by
// FileServer is adapted from the one in net/http by
// the Go authors. Significant modifications have been made.
//
//
...
...
@@ -28,15 +28,16 @@ type fileHandler struct {
hide
[]
string
// list of files to treat as "Not Found"
}
func
(
f
*
fileHandler
)
ServeHTTP
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
(
int
,
error
)
{
func
(
f
h
*
fileHandler
)
ServeHTTP
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
(
int
,
error
)
{
upath
:=
r
.
URL
.
Path
if
!
strings
.
HasPrefix
(
upath
,
"/"
)
{
upath
=
"/"
+
upath
r
.
URL
.
Path
=
upath
}
return
f
.
serveFile
(
w
,
r
,
path
.
Clean
(
upath
))
return
f
h
.
serveFile
(
w
,
r
,
path
.
Clean
(
upath
))
}
// serveFile writes the specified file to the HTTP response.
// name is '/'-separated, not filepath.Separator.
func
(
fh
*
fileHandler
)
serveFile
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
name
string
)
(
int
,
error
)
{
f
,
err
:=
fh
.
root
.
Open
(
name
)
...
...
server/server.go
View file @
a8818388
...
...
@@ -97,9 +97,8 @@ func (s *Server) Serve() error {
tlsConfigs
=
append
(
tlsConfigs
,
vh
.
config
.
TLS
)
}
return
ListenAndServeTLSWithSNI
(
server
,
tlsConfigs
)
}
else
{
return
server
.
ListenAndServe
()
}
return
server
.
ListenAndServe
()
}
// ListenAndServeTLSWithSNI serves TLS with Server Name Indication (SNI) support, which allows
...
...
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