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
Łukasz Nowak
caddy
Commits
9e12c45d
Commit
9e12c45d
authored
Apr 25, 2015
by
Thomas Hansen
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
https://github.com/mholt/caddy
parents
96985fb3
24d9d237
Changes
18
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
269 additions
and
91 deletions
+269
-91
config/config.go
config/config.go
+1
-4
config/directives.go
config/directives.go
+0
-43
config/dispenser.go
config/dispenser.go
+1
-1
config/middleware.go
config/middleware.go
+2
-0
config/parser.go
config/parser.go
+1
-0
config/parser_test.go
config/parser_test.go
+47
-0
config/parsing.go
config/parsing.go
+23
-6
main.go
main.go
+57
-3
middleware/basicauth/basicauth.go
middleware/basicauth/basicauth.go
+101
-0
middleware/browse/browse.go
middleware/browse/browse.go
+6
-4
middleware/browse/template.go
middleware/browse/template.go
+7
-7
middleware/log/log.go
middleware/log/log.go
+2
-0
middleware/markdown/markdown.go
middleware/markdown/markdown.go
+1
-1
middleware/recorder.go
middleware/recorder.go
+6
-1
middleware/replacer.go
middleware/replacer.go
+3
-2
middleware/templates/templates.go
middleware/templates/templates.go
+4
-1
server/server.go
server/server.go
+6
-17
server/virtualhost.go
server/virtualhost.go
+1
-1
No files found.
config/config.go
View file @
9e12c45d
...
@@ -12,7 +12,7 @@ import (
...
@@ -12,7 +12,7 @@ import (
const
(
const
(
defaultHost
=
"localhost"
defaultHost
=
"localhost"
defaultPort
=
"
8080
"
defaultPort
=
"
2015
"
defaultRoot
=
"."
defaultRoot
=
"."
// The default configuration file to load if none is specified
// The default configuration file to load if none is specified
...
@@ -47,9 +47,6 @@ type Config struct {
...
@@ -47,9 +47,6 @@ type Config struct {
// these are executed in response to SIGINT and are blocking
// these are executed in response to SIGINT and are blocking
Shutdown
[]
func
()
error
Shutdown
[]
func
()
error
// MaxCPU is the maximum number of cores for the whole process to use
MaxCPU
int
// The path to the configuration file from which this was loaded
// The path to the configuration file from which this was loaded
ConfigFile
string
ConfigFile
string
}
}
...
...
config/directives.go
View file @
9e12c45d
...
@@ -3,9 +3,6 @@ package config
...
@@ -3,9 +3,6 @@ package config
import
(
import
(
"os"
"os"
"os/exec"
"os/exec"
"runtime"
"strconv"
"strings"
"github.com/mholt/caddy/middleware"
"github.com/mholt/caddy/middleware"
)
)
...
@@ -74,46 +71,6 @@ func init() {
...
@@ -74,46 +71,6 @@ func init() {
p
.
cfg
.
TLS
=
tls
p
.
cfg
.
TLS
=
tls
return
nil
return
nil
},
},
"cpu"
:
func
(
p
*
parser
)
error
{
sysCores
:=
runtime
.
NumCPU
()
if
!
p
.
nextArg
()
{
return
p
.
argErr
()
}
strNum
:=
p
.
tkn
()
setCPU
:=
func
(
val
int
)
{
if
val
<
1
{
val
=
1
}
if
val
>
sysCores
{
val
=
sysCores
}
if
val
>
p
.
cfg
.
MaxCPU
{
p
.
cfg
.
MaxCPU
=
val
}
}
if
strings
.
HasSuffix
(
strNum
,
"%"
)
{
// Percent
var
percent
float32
pctStr
:=
strNum
[
:
len
(
strNum
)
-
1
]
pctInt
,
err
:=
strconv
.
Atoi
(
pctStr
)
if
err
!=
nil
||
pctInt
<
1
||
pctInt
>
100
{
return
p
.
err
(
"Parse"
,
"Invalid number '"
+
strNum
+
"' (must be a positive percentage between 1 and 100)"
)
}
percent
=
float32
(
pctInt
)
/
100
setCPU
(
int
(
float32
(
sysCores
)
*
percent
))
}
else
{
// Number
num
,
err
:=
strconv
.
Atoi
(
strNum
)
if
err
!=
nil
||
num
<
0
{
return
p
.
err
(
"Parse"
,
"Invalid number '"
+
strNum
+
"' (requires positive integer or percent)"
)
}
setCPU
(
num
)
}
return
nil
},
"startup"
:
func
(
p
*
parser
)
error
{
"startup"
:
func
(
p
*
parser
)
error
{
// TODO: This code is duplicated with the shutdown directive below
// TODO: This code is duplicated with the shutdown directive below
...
...
config/dispenser.go
View file @
9e12c45d
...
@@ -149,7 +149,7 @@ func (d *dispenser) ArgErr() error {
...
@@ -149,7 +149,7 @@ func (d *dispenser) ArgErr() error {
if
d
.
Val
()
==
"{"
{
if
d
.
Val
()
==
"{"
{
return
d
.
Err
(
"Unexpected token '{', expecting argument"
)
return
d
.
Err
(
"Unexpected token '{', expecting argument"
)
}
}
return
d
.
Err
(
"
Unexpected line ending after '"
+
d
.
Val
()
+
"' (missing arguments?)
"
)
return
d
.
Err
(
"
Wrong argument count or unexpected line ending after '"
+
d
.
Val
()
+
"'
"
)
}
}
// Err generates a custom parse error with a message of msg.
// Err generates a custom parse error with a message of msg.
...
...
config/middleware.go
View file @
9e12c45d
...
@@ -2,6 +2,7 @@ package config
...
@@ -2,6 +2,7 @@ package config
import
(
import
(
"github.com/mholt/caddy/middleware"
"github.com/mholt/caddy/middleware"
"github.com/mholt/caddy/middleware/basicauth"
"github.com/mholt/caddy/middleware/browse"
"github.com/mholt/caddy/middleware/browse"
"github.com/mholt/caddy/middleware/errors"
"github.com/mholt/caddy/middleware/errors"
"github.com/mholt/caddy/middleware/extensions"
"github.com/mholt/caddy/middleware/extensions"
...
@@ -45,6 +46,7 @@ func init() {
...
@@ -45,6 +46,7 @@ func init() {
register
(
"rewrite"
,
rewrite
.
New
)
register
(
"rewrite"
,
rewrite
.
New
)
register
(
"redir"
,
redirect
.
New
)
register
(
"redir"
,
redirect
.
New
)
register
(
"ext"
,
extensions
.
New
)
register
(
"ext"
,
extensions
.
New
)
register
(
"basicauth"
,
basicauth
.
New
)
register
(
"proxy"
,
proxy
.
New
)
register
(
"proxy"
,
proxy
.
New
)
register
(
"fastcgi"
,
fastcgi
.
New
)
register
(
"fastcgi"
,
fastcgi
.
New
)
register
(
"websocket"
,
websockets
.
New
)
register
(
"websocket"
,
websockets
.
New
)
...
...
config/parser.go
View file @
9e12c45d
...
@@ -19,6 +19,7 @@ type (
...
@@ -19,6 +19,7 @@ type (
other
[]
locationContext
// tokens to be 'parsed' later by middleware generators
other
[]
locationContext
// tokens to be 'parsed' later by middleware generators
scope
*
locationContext
// the current location context (path scope) being populated
scope
*
locationContext
// the current location context (path scope) being populated
unused
*
token
// sometimes a token will be read but not immediately consumed
unused
*
token
// sometimes a token will be read but not immediately consumed
eof
bool
// if we encounter a valid EOF in a hard place
}
}
// locationContext represents a location context
// locationContext represents a location context
...
...
config/parser_test.go
View file @
9e12c45d
...
@@ -211,6 +211,53 @@ func TestParserBasicWithAlternateAddressStyles(t *testing.T) {
...
@@ -211,6 +211,53 @@ func TestParserBasicWithAlternateAddressStyles(t *testing.T) {
t
.
Fatalf
(
"Expected root for conf of %s to be '/test/www', but got: %s"
,
conf
.
Address
(),
conf
.
Root
)
t
.
Fatalf
(
"Expected root for conf of %s to be '/test/www', but got: %s"
,
conf
.
Address
(),
conf
.
Root
)
}
}
}
}
p
=
&
parser
{
filename
:
"test"
}
input
=
`host:port, http://host:port, http://host, https://host:port, host`
p
.
lexer
.
load
(
strings
.
NewReader
(
input
))
confs
,
err
=
p
.
parse
()
if
err
!=
nil
{
t
.
Fatalf
(
"Expected no errors, but got '%s'"
,
err
)
}
if
len
(
confs
)
!=
5
{
t
.
Fatalf
(
"Expected 5 configurations, but got %d: %#v"
,
len
(
confs
),
confs
)
}
if
confs
[
0
]
.
Host
!=
"host"
{
t
.
Errorf
(
"Expected conf[0] Host='host', got '%#v'"
,
confs
[
0
])
}
if
confs
[
0
]
.
Port
!=
"port"
{
t
.
Errorf
(
"Expected conf[0] Port='port', got '%#v'"
,
confs
[
0
])
}
if
confs
[
1
]
.
Host
!=
"host"
{
t
.
Errorf
(
"Expected conf[1] Host='host', got '%#v'"
,
confs
[
1
])
}
if
confs
[
1
]
.
Port
!=
"port"
{
t
.
Errorf
(
"Expected conf[1] Port='port', got '%#v'"
,
confs
[
1
])
}
if
confs
[
2
]
.
Host
!=
"host"
{
t
.
Errorf
(
"Expected conf[2] Host='host', got '%#v'"
,
confs
[
2
])
}
if
confs
[
2
]
.
Port
!=
"http"
{
t
.
Errorf
(
"Expected conf[2] Port='http', got '%#v'"
,
confs
[
2
])
}
if
confs
[
3
]
.
Host
!=
"host"
{
t
.
Errorf
(
"Expected conf[3] Host='host', got '%#v'"
,
confs
[
3
])
}
if
confs
[
3
]
.
Port
!=
"port"
{
t
.
Errorf
(
"Expected conf[3] Port='port', got '%#v'"
,
confs
[
3
])
}
if
confs
[
4
]
.
Host
!=
"host"
{
t
.
Errorf
(
"Expected conf[4] Host='host', got '%#v'"
,
confs
[
4
])
}
if
confs
[
4
]
.
Port
!=
defaultPort
{
t
.
Errorf
(
"Expected conf[4] Port='%s', got '%#v'"
,
defaultPort
,
confs
[
4
]
.
Port
)
}
}
}
func
TestParserImport
(
t
*
testing
.
T
)
{
func
TestParserImport
(
t
*
testing
.
T
)
{
...
...
config/parsing.go
View file @
9e12c45d
...
@@ -38,18 +38,25 @@ func (p *parser) addresses() error {
...
@@ -38,18 +38,25 @@ func (p *parser) addresses() error {
// address gets host and port in a format accepted by net.Dial
// address gets host and port in a format accepted by net.Dial
address
:=
func
(
str
string
)
(
host
,
port
string
,
err
error
)
{
address
:=
func
(
str
string
)
(
host
,
port
string
,
err
error
)
{
var
schemePort
string
if
strings
.
HasPrefix
(
str
,
"https://"
)
{
if
strings
.
HasPrefix
(
str
,
"https://"
)
{
port
=
"https"
schemePort
=
"https"
host
=
str
[
8
:
]
str
=
str
[
8
:
]
return
}
else
if
strings
.
HasPrefix
(
str
,
"http://"
)
{
}
else
if
strings
.
HasPrefix
(
str
,
"http://"
)
{
port
=
"http"
schemePort
=
"http"
host
=
str
[
7
:
]
str
=
str
[
7
:
]
return
}
else
if
!
strings
.
Contains
(
str
,
":"
)
{
}
else
if
!
strings
.
Contains
(
str
,
":"
)
{
str
+=
":"
+
defaultPort
str
+=
":"
+
defaultPort
}
}
host
,
port
,
err
=
net
.
SplitHostPort
(
str
)
host
,
port
,
err
=
net
.
SplitHostPort
(
str
)
if
err
!=
nil
&&
schemePort
!=
""
{
host
=
str
port
=
schemePort
// assume port from scheme
err
=
nil
}
return
return
}
}
...
@@ -88,6 +95,10 @@ func (p *parser) addresses() error {
...
@@ -88,6 +95,10 @@ func (p *parser) addresses() error {
if
!
expectingAnother
&&
p
.
line
()
>
startLine
{
if
!
expectingAnother
&&
p
.
line
()
>
startLine
{
break
break
}
}
if
!
hasNext
{
p
.
eof
=
true
break
// EOF
}
}
}
return
nil
return
nil
...
@@ -115,6 +126,12 @@ func (p *parser) addressBlock() error {
...
@@ -115,6 +126,12 @@ func (p *parser) addressBlock() error {
})
})
p
.
scope
=
&
p
.
other
[
0
]
p
.
scope
=
&
p
.
other
[
0
]
if
p
.
eof
{
// this happens if the Caddyfile consists of only
// a line of addresses and nothing else
return
nil
}
err
:=
p
.
directives
()
err
:=
p
.
directives
()
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
...
...
main.go
View file @
9e12c45d
package
main
package
main
import
(
import
(
"errors"
"flag"
"flag"
"fmt"
"fmt"
"log"
"log"
"net"
"net"
"runtime"
"strconv"
"strings"
"sync"
"sync"
"github.com/mholt/caddy/config"
"github.com/mholt/caddy/config"
...
@@ -13,18 +17,27 @@ import (
...
@@ -13,18 +17,27 @@ import (
var
(
var
(
conf
string
conf
string
http2
bool
http2
bool
// TODO: temporary flag until http2 is standard
quiet
bool
cpu
string
)
)
func
init
()
{
func
init
()
{
flag
.
StringVar
(
&
conf
,
"conf"
,
config
.
DefaultConfigFile
,
"the configuration file to use"
)
flag
.
StringVar
(
&
conf
,
"conf"
,
config
.
DefaultConfigFile
,
"the configuration file to use"
)
flag
.
BoolVar
(
&
http2
,
"http2"
,
true
,
"enable HTTP/2 support"
)
// temporary flag until http2 merged into std lib
flag
.
BoolVar
(
&
http2
,
"http2"
,
true
,
"enable HTTP/2 support"
)
// TODO: temporary flag until http2 merged into std lib
flag
.
BoolVar
(
&
quiet
,
"quiet"
,
false
,
"quiet mode (no initialization output)"
)
flag
.
StringVar
(
&
cpu
,
"cpu"
,
"100%"
,
"CPU cap"
)
flag
.
Parse
()
}
}
func
main
()
{
func
main
()
{
var
wg
sync
.
WaitGroup
var
wg
sync
.
WaitGroup
flag
.
Parse
()
// Set CPU cap
err
:=
setCPU
(
cpu
)
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
// Load config from file
// Load config from file
allConfigs
,
err
:=
config
.
Load
(
conf
)
allConfigs
,
err
:=
config
.
Load
(
conf
)
...
@@ -60,6 +73,12 @@ func main() {
...
@@ -60,6 +73,12 @@ func main() {
log
.
Println
(
err
)
log
.
Println
(
err
)
}
}
}(
s
)
}(
s
)
if
!
quiet
{
for
_
,
config
:=
range
configs
{
fmt
.
Println
(
config
.
Address
())
}
}
}
}
wg
.
Wait
()
wg
.
Wait
()
...
@@ -102,3 +121,38 @@ func arrangeBindings(allConfigs []config.Config) (map[string][]config.Config, er
...
@@ -102,3 +121,38 @@ func arrangeBindings(allConfigs []config.Config) (map[string][]config.Config, er
return
addresses
,
nil
return
addresses
,
nil
}
}
// setCPU parses string cpu and sets GOMAXPROCS
// according to its value. It accepts either
// a number (e.g. 3) or a percent (e.g. 50%).
func
setCPU
(
cpu
string
)
error
{
var
numCPU
int
availCPU
:=
runtime
.
NumCPU
()
if
strings
.
HasSuffix
(
cpu
,
"%"
)
{
// Percent
var
percent
float32
pctStr
:=
cpu
[
:
len
(
cpu
)
-
1
]
pctInt
,
err
:=
strconv
.
Atoi
(
pctStr
)
if
err
!=
nil
||
pctInt
<
1
||
pctInt
>
100
{
return
errors
.
New
(
"Invalid CPU value: percentage must be between 1-100"
)
}
percent
=
float32
(
pctInt
)
/
100
numCPU
=
int
(
float32
(
availCPU
)
*
percent
)
}
else
{
// Number
num
,
err
:=
strconv
.
Atoi
(
cpu
)
if
err
!=
nil
||
num
<
1
{
return
errors
.
New
(
"Invalid CPU value: provide a number or percent greater than 0"
)
}
numCPU
=
num
}
if
numCPU
>
availCPU
{
numCPU
=
availCPU
}
runtime
.
GOMAXPROCS
(
numCPU
)
return
nil
}
middleware/basicauth/basicauth.go
0 → 100644
View file @
9e12c45d
package
basicauth
import
(
"net/http"
"github.com/mholt/caddy/middleware"
)
// New constructs a new BasicAuth middleware instance.
func
New
(
c
middleware
.
Controller
)
(
middleware
.
Middleware
,
error
)
{
rules
,
err
:=
parse
(
c
)
if
err
!=
nil
{
return
nil
,
err
}
basic
:=
BasicAuth
{
Rules
:
rules
,
}
return
func
(
next
middleware
.
Handler
)
middleware
.
Handler
{
basic
.
Next
=
next
return
basic
},
nil
}
// ServeHTTP implements the middleware.Handler interface.
func
(
a
BasicAuth
)
ServeHTTP
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
(
int
,
error
)
{
for
_
,
rule
:=
range
a
.
Rules
{
for
_
,
res
:=
range
rule
.
Resources
{
if
!
middleware
.
Path
(
r
.
URL
.
Path
)
.
Matches
(
res
)
{
continue
}
// Path matches; parse auth header
username
,
password
,
ok
:=
r
.
BasicAuth
()
// Check credentials
if
!
ok
||
username
!=
rule
.
Username
||
password
!=
rule
.
Password
{
w
.
Header
()
.
Set
(
"WWW-Authenticate"
,
"Basic"
)
return
http
.
StatusUnauthorized
,
nil
}
// "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
return
a
.
Next
.
ServeHTTP
(
w
,
r
)
}
func
parse
(
c
middleware
.
Controller
)
([]
Rule
,
error
)
{
var
rules
[]
Rule
for
c
.
Next
()
{
var
rule
Rule
args
:=
c
.
RemainingArgs
()
switch
len
(
args
)
{
case
2
:
rule
.
Username
=
args
[
0
]
rule
.
Password
=
args
[
1
]
for
c
.
NextBlock
()
{
rule
.
Resources
=
append
(
rule
.
Resources
,
c
.
Val
())
if
c
.
NextArg
()
{
return
rules
,
c
.
Err
(
"Expecting only one resource per line (extra '"
+
c
.
Val
()
+
"')"
)
}
}
case
3
:
rule
.
Resources
=
append
(
rule
.
Resources
,
args
[
0
])
rule
.
Username
=
args
[
1
]
rule
.
Password
=
args
[
2
]
default
:
return
rules
,
c
.
ArgErr
()
}
rules
=
append
(
rules
,
rule
)
}
return
rules
,
nil
}
// BasicAuth is middleware to protect resources with a username and password.
// Note that HTTP Basic Authentication is not secure by itself and should
// not be used to protect important assets without HTTPS. Even then, the
// security of HTTP Basic Auth is disputed. Use discretion when deciding
// what to protect with BasicAuth.
type
BasicAuth
struct
{
Next
middleware
.
Handler
Rules
[]
Rule
}
// Rule represents a BasicAuth rule. A username and password
// combination protect the associated resources, which are
// file or directory paths.
type
Rule
struct
{
Username
string
Password
string
Resources
[]
string
}
middleware/browse/browse.go
View file @
9e12c45d
...
@@ -3,6 +3,7 @@
...
@@ -3,6 +3,7 @@
package
browse
package
browse
import
(
import
(
"bytes"
"fmt"
"fmt"
"html/template"
"html/template"
"io/ioutil"
"io/ioutil"
...
@@ -122,8 +123,6 @@ func (b Browse) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
...
@@ -122,8 +123,6 @@ func (b Browse) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
}
}
defer
file
.
Close
()
defer
file
.
Close
()
w
.
Header
()
.
Set
(
"Content-Type"
,
"text/html; charset=utf-8"
)
files
,
err
:=
file
.
Readdir
(
-
1
)
files
,
err
:=
file
.
Readdir
(
-
1
)
if
err
!=
nil
{
if
err
!=
nil
{
return
http
.
StatusForbidden
,
err
return
http
.
StatusForbidden
,
err
...
@@ -182,12 +181,15 @@ func (b Browse) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
...
@@ -182,12 +181,15 @@ func (b Browse) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
Items
:
fileinfos
,
Items
:
fileinfos
,
}
}
// TODO: Don't write to w until we know there wasn't an erro
r
var
buf
bytes
.
Buffe
r
err
=
bc
.
Template
.
Execute
(
w
,
listing
)
err
=
bc
.
Template
.
Execute
(
&
buf
,
listing
)
if
err
!=
nil
{
if
err
!=
nil
{
return
http
.
StatusInternalServerError
,
err
return
http
.
StatusInternalServerError
,
err
}
}
w
.
Header
()
.
Set
(
"Content-Type"
,
"text/html; charset=utf-8"
)
buf
.
WriteTo
(
w
)
return
http
.
StatusOK
,
nil
return
http
.
StatusOK
,
nil
}
}
...
...
middleware/browse/template.go
View file @
9e12c45d
...
@@ -11,7 +11,7 @@ const defaultTemplate = `<!DOCTYPE html>
...
@@ -11,7 +11,7 @@ const defaultTemplate = `<!DOCTYPE html>
body {
body {
padding: 1% 2%;
padding: 1% 2%;
font: 16px
sans-serif
;
font: 16px
Arial
;
}
}
header {
header {
...
@@ -60,7 +60,7 @@ th {
...
@@ -60,7 +60,7 @@ th {
text-align: left;
text-align: left;
}
}
@media (max-width:
65
0px) {
@media (max-width:
70
0px) {
.hideable {
.hideable {
display: none;
display: none;
}
}
...
@@ -71,7 +71,7 @@ th {
...
@@ -71,7 +71,7 @@ th {
header,
header,
header h1 {
header h1 {
font-size: 1
4
px;
font-size: 1
6
px;
}
}
header {
header {
...
@@ -80,7 +80,7 @@ th {
...
@@ -80,7 +80,7 @@ th {
width: 100%;
width: 100%;
background: #333;
background: #333;
color: #FFF;
color: #FFF;
padding: 1
0
px;
padding: 1
5
px;
text-align: center;
text-align: center;
}
}
...
@@ -95,8 +95,8 @@ th {
...
@@ -95,8 +95,8 @@ th {
position: absolute;
position: absolute;
left: 0;
left: 0;
top: 0;
top: 0;
width:
35
px;
width:
40
px;
height:
2
8px;
height:
4
8px;
font-size: 35px;
font-size: 35px;
}
}
...
@@ -105,7 +105,7 @@ th {
...
@@ -105,7 +105,7 @@ th {
}
}
main {
main {
margin-top:
5
0px;
margin-top:
7
0px;
}
}
}
}
</style>
</style>
...
...
middleware/log/log.go
View file @
9e12c45d
...
@@ -88,6 +88,8 @@ func parse(c middleware.Controller) ([]LogRule, error) {
...
@@ -88,6 +88,8 @@ func parse(c middleware.Controller) ([]LogRule, error) {
format
=
commonLogFormat
format
=
commonLogFormat
case
"{combined}"
:
case
"{combined}"
:
format
=
combinedLogFormat
format
=
combinedLogFormat
default
:
format
=
args
[
2
]
}
}
}
}
...
...
middleware/markdown/markdown.go
View file @
9e12c45d
...
@@ -135,7 +135,7 @@ func parse(c middleware.Controller) ([]MarkdownConfig, error) {
...
@@ -135,7 +135,7 @@ func parse(c middleware.Controller) ([]MarkdownConfig, error) {
}
}
// Get the path scope
// Get the path scope
if
!
c
.
NextArg
()
{
if
!
c
.
NextArg
()
||
c
.
Val
()
==
"{"
{
return
mdconfigs
,
c
.
ArgErr
()
return
mdconfigs
,
c
.
ArgErr
()
}
}
md
.
PathScope
=
c
.
Val
()
md
.
PathScope
=
c
.
Val
()
...
...
middleware/recorder.go
View file @
9e12c45d
package
middleware
package
middleware
import
"net/http"
import
(
"net/http"
"time"
)
// responseRecorder is a type of ResponseWriter that captures
// responseRecorder is a type of ResponseWriter that captures
// the status code written to it and also the size of the body
// the status code written to it and also the size of the body
...
@@ -12,6 +15,7 @@ type responseRecorder struct {
...
@@ -12,6 +15,7 @@ type responseRecorder struct {
http
.
ResponseWriter
http
.
ResponseWriter
status
int
status
int
size
int
size
int
start
time
.
Time
}
}
// NewResponseRecorder makes and returns a new responseRecorder,
// NewResponseRecorder makes and returns a new responseRecorder,
...
@@ -24,6 +28,7 @@ func NewResponseRecorder(w http.ResponseWriter) *responseRecorder {
...
@@ -24,6 +28,7 @@ func NewResponseRecorder(w http.ResponseWriter) *responseRecorder {
return
&
responseRecorder
{
return
&
responseRecorder
{
ResponseWriter
:
w
,
ResponseWriter
:
w
,
status
:
http
.
StatusOK
,
status
:
http
.
StatusOK
,
start
:
time
.
Now
(),
}
}
}
}
...
...
middleware/replacer.go
View file @
9e12c45d
...
@@ -50,8 +50,9 @@ func NewReplacer(r *http.Request, rr *responseRecorder) replacer {
...
@@ -50,8 +50,9 @@ func NewReplacer(r *http.Request, rr *responseRecorder) replacer {
"{when}"
:
func
()
string
{
"{when}"
:
func
()
string
{
return
time
.
Now
()
.
Format
(
timeFormat
)
return
time
.
Now
()
.
Format
(
timeFormat
)
}(),
}(),
"{status}"
:
strconv
.
Itoa
(
rr
.
status
),
"{status}"
:
strconv
.
Itoa
(
rr
.
status
),
"{size}"
:
strconv
.
Itoa
(
rr
.
size
),
"{size}"
:
strconv
.
Itoa
(
rr
.
size
),
"{latency}"
:
time
.
Since
(
rr
.
start
)
.
String
(),
}
}
// Header placeholders
// Header placeholders
...
...
middleware/templates/templates.go
View file @
9e12c45d
package
templates
package
templates
import
(
import
(
"bytes"
"net/http"
"net/http"
"path"
"path"
"text/template"
"text/template"
...
@@ -47,10 +48,12 @@ func (t Templates) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error
...
@@ -47,10 +48,12 @@ func (t Templates) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error
}
}
// Execute it
// Execute it
err
=
tpl
.
Execute
(
w
,
ctx
)
var
buf
bytes
.
Buffer
err
=
tpl
.
Execute
(
&
buf
,
ctx
)
if
err
!=
nil
{
if
err
!=
nil
{
return
http
.
StatusInternalServerError
,
err
return
http
.
StatusInternalServerError
,
err
}
}
buf
.
WriteTo
(
w
)
return
http
.
StatusOK
,
nil
return
http
.
StatusOK
,
nil
}
}
...
...
server/server.go
View file @
9e12c45d
...
@@ -11,7 +11,6 @@ import (
...
@@ -11,7 +11,6 @@ import (
"net/http"
"net/http"
"os"
"os"
"os/signal"
"os/signal"
"runtime"
"github.com/bradfitz/http2"
"github.com/bradfitz/http2"
"github.com/mholt/caddy/config"
"github.com/mholt/caddy/config"
...
@@ -20,10 +19,10 @@ import (
...
@@ -20,10 +19,10 @@ import (
// Server represents an instance of a server, which serves
// Server represents an instance of a server, which serves
// static content at a particular address (host and port).
// static content at a particular address (host and port).
type
Server
struct
{
type
Server
struct
{
HTTP2
bool
// temporary while http2 is not in std lib (TODO: remove flag when part of std lib)
HTTP2
bool
// temporary while http2 is not in std lib (TODO: remove flag when part of std lib)
address
string
address
string
// the actual address for net.Listen to listen on
tls
bool
tls
bool
// whether this server is serving all HTTPS hosts or not
vhosts
map
[
string
]
virtualHost
vhosts
map
[
string
]
virtualHost
// virtual hosts keyed by their address
}
}
// New creates a new Server which will bind to addr and serve
// New creates a new Server which will bind to addr and serve
...
@@ -41,11 +40,6 @@ func New(addr string, configs []config.Config, tls bool) (*Server, error) {
...
@@ -41,11 +40,6 @@ func New(addr string, configs []config.Config, tls bool) (*Server, error) {
return
nil
,
fmt
.
Errorf
(
"Cannot serve %s - host already defined for address %s"
,
conf
.
Address
(),
s
.
address
)
return
nil
,
fmt
.
Errorf
(
"Cannot serve %s - host already defined for address %s"
,
conf
.
Address
(),
s
.
address
)
}
}
// Use all CPUs (if needed) by default
if
conf
.
MaxCPU
==
0
{
conf
.
MaxCPU
=
runtime
.
NumCPU
()
}
vh
:=
virtualHost
{
config
:
conf
}
vh
:=
virtualHost
{
config
:
conf
}
// Build middleware stack
// Build middleware stack
...
@@ -73,7 +67,7 @@ func (s *Server) Serve() error {
...
@@ -73,7 +67,7 @@ func (s *Server) Serve() error {
}
}
for
_
,
vh
:=
range
s
.
vhosts
{
for
_
,
vh
:=
range
s
.
vhosts
{
// Execute startup functions
// Execute startup functions
now
for
_
,
start
:=
range
vh
.
config
.
Startup
{
for
_
,
start
:=
range
vh
.
config
.
Startup
{
err
:=
start
()
err
:=
start
()
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -81,13 +75,8 @@ func (s *Server) Serve() error {
...
@@ -81,13 +75,8 @@ func (s *Server) Serve() error {
}
}
}
}
// Use highest procs value across all configurations
// Execute shutdown commands on exit
if
vh
.
config
.
MaxCPU
>
0
&&
vh
.
config
.
MaxCPU
>
runtime
.
GOMAXPROCS
(
0
)
{
runtime
.
GOMAXPROCS
(
vh
.
config
.
MaxCPU
)
}
if
len
(
vh
.
config
.
Shutdown
)
>
0
{
if
len
(
vh
.
config
.
Shutdown
)
>
0
{
// Execute shutdown commands on exit
go
func
()
{
go
func
()
{
interrupt
:=
make
(
chan
os
.
Signal
,
1
)
interrupt
:=
make
(
chan
os
.
Signal
,
1
)
signal
.
Notify
(
interrupt
,
os
.
Interrupt
,
os
.
Kill
)
// TODO: syscall.SIGQUIT? (Ctrl+\, Unix-only)
signal
.
Notify
(
interrupt
,
os
.
Interrupt
,
os
.
Kill
)
// TODO: syscall.SIGQUIT? (Ctrl+\, Unix-only)
...
...
server/virtualhost.go
View file @
9e12c45d
...
@@ -9,7 +9,7 @@ import (
...
@@ -9,7 +9,7 @@ import (
// virtualHost represents a virtual host/server. While a Server
// virtualHost represents a virtual host/server. While a Server
// is what actually binds to the address, a user may want to serve
// is what actually binds to the address, a user may want to serve
// multiple sites on a single address, and
what
is what a
// multiple sites on a single address, and
this
is what a
// virtualHost allows us to do.
// virtualHost allows us to do.
type
virtualHost
struct
{
type
virtualHost
struct
{
config
config
.
Config
config
config
.
Config
...
...
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