mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-01 21:24:23 +08:00
Merge branch 'master' into getcertificate
This commit is contained in:
commit
178c4d11d9
|
@ -25,6 +25,7 @@ func saveRSAPrivateKey(key *rsa.PrivateKey, file string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
keyOut.Chmod(0600)
|
||||||
defer keyOut.Close()
|
defer keyOut.Close()
|
||||||
return pem.Encode(keyOut, &pemKey)
|
return pem.Encode(keyOut, &pemKey)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -28,13 +29,26 @@ func TestSaveAndLoadRSAPrivateKey(t *testing.T) {
|
||||||
t.Fatal("error saving private key:", err)
|
t.Fatal("error saving private key:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// it doesn't make sense to test file permission on windows
|
||||||
|
if runtime.GOOS != "windows" {
|
||||||
|
// get info of the key file
|
||||||
|
info, err := os.Stat(keyFile)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("error stating private key:", err)
|
||||||
|
}
|
||||||
|
// verify permission of key file is correct
|
||||||
|
if info.Mode().Perm() != 0600 {
|
||||||
|
t.Error("Expected key file to have permission 0600, but it wasn't")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// test load
|
// test load
|
||||||
loadedKey, err := loadRSAPrivateKey(keyFile)
|
loadedKey, err := loadRSAPrivateKey(keyFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("error loading private key:", err)
|
t.Error("error loading private key:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// very loaded key is correct
|
// verify loaded key is correct
|
||||||
if !rsaPrivateKeysSame(privateKey, loadedKey) {
|
if !rsaPrivateKeysSame(privateKey, loadedKey) {
|
||||||
t.Error("Expected key bytes to be the same, but they weren't")
|
t.Error("Expected key bytes to be the same, but they weren't")
|
||||||
}
|
}
|
||||||
|
|
|
@ -322,7 +322,7 @@ func newClientPort(leEmail, port string) (*acme.Client, error) {
|
||||||
client.SetHTTPAddress(":" + port)
|
client.SetHTTPAddress(":" + port)
|
||||||
client.SetTLSAddress(":" + port)
|
client.SetTLSAddress(":" + port)
|
||||||
}
|
}
|
||||||
client.ExcludeChallenges([]string{"tls-sni-01", "dns-01"}) // We can only guarantee http-01 at this time, but tls-01 should work if port is not custom!
|
client.ExcludeChallenges([]acme.Challenge{acme.TLSSNI01, acme.DNS01}) // We can only guarantee http-01 at this time, but tls-01 should work if port is not custom!
|
||||||
|
|
||||||
// If not registered, the user must register an account with the CA
|
// If not registered, the user must register an account with the CA
|
||||||
// and agree to terms
|
// and agree to terms
|
||||||
|
|
|
@ -32,6 +32,8 @@ func init() {
|
||||||
// work if executing with `go run`, since the binary is cleaned up
|
// work if executing with `go run`, since the binary is cleaned up
|
||||||
// when `go run` sees the initial parent process exit.
|
// when `go run` sees the initial parent process exit.
|
||||||
func Restart(newCaddyfile Input) error {
|
func Restart(newCaddyfile Input) error {
|
||||||
|
log.Println("[INFO] Restarting")
|
||||||
|
|
||||||
if newCaddyfile == nil {
|
if newCaddyfile == nil {
|
||||||
caddyfileMu.Lock()
|
caddyfileMu.Lock()
|
||||||
newCaddyfile = caddyfile
|
newCaddyfile = caddyfile
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
package caddy
|
package caddy
|
||||||
|
|
||||||
|
import "log"
|
||||||
|
|
||||||
// Restart restarts Caddy forcefully using newCaddyfile,
|
// Restart restarts Caddy forcefully using newCaddyfile,
|
||||||
// or, if nil, the current/existing Caddyfile is reused.
|
// or, if nil, the current/existing Caddyfile is reused.
|
||||||
func Restart(newCaddyfile Input) error {
|
func Restart(newCaddyfile Input) error {
|
||||||
|
log.Println("[INFO] Restarting")
|
||||||
|
|
||||||
if newCaddyfile == nil {
|
if newCaddyfile == nil {
|
||||||
caddyfileMu.Lock()
|
caddyfileMu.Lock()
|
||||||
newCaddyfile = caddyfile
|
newCaddyfile = caddyfile
|
||||||
|
|
|
@ -214,6 +214,7 @@ td .name {
|
||||||
margin-left: 1.75em;
|
margin-left: 1.75em;
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
|
white-space: pre-wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
footer {
|
footer {
|
||||||
|
|
|
@ -47,7 +47,7 @@ func gzipParse(c *Controller) ([]gzip.Config, error) {
|
||||||
return configs, c.ArgErr()
|
return configs, c.ArgErr()
|
||||||
}
|
}
|
||||||
for _, e := range exts {
|
for _, e := range exts {
|
||||||
if !strings.HasPrefix(e, ".") && e != gzip.ExtWildCard {
|
if !strings.HasPrefix(e, ".") && e != gzip.ExtWildCard && e != "" {
|
||||||
return configs, fmt.Errorf(`gzip: invalid extension "%v" (must start with dot)`, e)
|
return configs, fmt.Errorf(`gzip: invalid extension "%v" (must start with dot)`, e)
|
||||||
}
|
}
|
||||||
extFilter.Exts.Add(e)
|
extFilter.Exts.Add(e)
|
||||||
|
|
|
@ -50,6 +50,9 @@ func TestGzip(t *testing.T) {
|
||||||
level 1
|
level 1
|
||||||
}
|
}
|
||||||
gzip`, false},
|
gzip`, false},
|
||||||
|
{`gzip {
|
||||||
|
ext ""
|
||||||
|
}`, false},
|
||||||
{`gzip { not /file
|
{`gzip { not /file
|
||||||
ext .html
|
ext .html
|
||||||
level 1
|
level 1
|
||||||
|
|
342
dist/CHANGES.txt
vendored
342
dist/CHANGES.txt
vendored
|
@ -1,171 +1,171 @@
|
||||||
CHANGES
|
CHANGES
|
||||||
|
|
||||||
<master>
|
0.8.1 (January 12, 2016)
|
||||||
- Improved OCSP stapling
|
- Improved OCSP stapling
|
||||||
- Can reload config with new hosts that need certs from Let's Encrypt
|
- Better graceful reload when new hosts need certificates from Let's Encrypt
|
||||||
- If pidfile is created, it is deleted when Caddy exits
|
- Current pidfile is now deleted when Caddy exits
|
||||||
- browse: New default template
|
- browse: New default template
|
||||||
- gzip: Added min_length setting
|
- gzip: Added min_length setting
|
||||||
- import: Support for glob patterns (*) to import multiple files
|
- import: Support for glob patterns (*) to import multiple files
|
||||||
- rewrite: New complex rules with conditions, regex captures, and status code
|
- rewrite: New complex rules with conditions, regex captures, and status code
|
||||||
- tls: Removed DES ciphers from default cipher suite list
|
- tls: Removed DES ciphers from default cipher suite list
|
||||||
- tls: All supported certificates are OCSP-stapled
|
- tls: All supported certificates are OCSP-stapled
|
||||||
- tls: Allow custom configuration without specifying certificate and key
|
- tls: Allow custom configuration without specifying certificate and key
|
||||||
- tls: No longer allow HTTPS over port 80
|
- tls: No longer allow HTTPS over port 80
|
||||||
- Dozens of bug fixes, improvements, and more tests across the board
|
- Dozens of bug fixes, improvements, and more tests across the board
|
||||||
|
|
||||||
0.8.0 (December 4, 2015)
|
0.8.0 (December 4, 2015)
|
||||||
- HTTPS by default via Let's Encrypt (certs & keys are fully managed)
|
- HTTPS by default via Let's Encrypt (certs & keys are fully managed)
|
||||||
- Graceful restarts (on POSIX-compliant systems)
|
- Graceful restarts (on POSIX-compliant systems)
|
||||||
- Major internal refactoring to allow use of Caddy as library
|
- Major internal refactoring to allow use of Caddy as library
|
||||||
- New directive 'mime' to customize Content-Type based on file extension
|
- New directive 'mime' to customize Content-Type based on file extension
|
||||||
- New -accept flag to accept Let's Encrypt SA without prompt
|
- New -accept flag to accept Let's Encrypt SA without prompt
|
||||||
- New -email flag to customize default email used for ACME transactions
|
- New -email flag to customize default email used for ACME transactions
|
||||||
- New -ca flag to customize ACME CA server URL
|
- New -ca flag to customize ACME CA server URL
|
||||||
- New -revoke flag to revoke a certificate
|
- New -revoke flag to revoke a certificate
|
||||||
- New -log flag to enable process log
|
- New -log flag to enable process log
|
||||||
- New -pidfile flag to enable writing pidfile
|
- New -pidfile flag to enable writing pidfile
|
||||||
- New -grace flag to customize the graceful shutdown timeout
|
- New -grace flag to customize the graceful shutdown timeout
|
||||||
- New support for SIGHUP, SIGTERM, and SIGQUIT signals
|
- New support for SIGHUP, SIGTERM, and SIGQUIT signals
|
||||||
- browse: Render filenames with multiple whitespace properly
|
- browse: Render filenames with multiple whitespace properly
|
||||||
- core: Use environment variables in Caddyfile
|
- core: Use environment variables in Caddyfile
|
||||||
- markdown: Include Last-Modified header in response
|
- markdown: Include Last-Modified header in response
|
||||||
- markdown: Render tables, strikethrough, and fenced code blocks
|
- markdown: Render tables, strikethrough, and fenced code blocks
|
||||||
- proxy: Ability to exclude/ignore paths from proxying
|
- proxy: Ability to exclude/ignore paths from proxying
|
||||||
- startup, shutdown: Better Windows support
|
- startup, shutdown: Better Windows support
|
||||||
- templates: Bug fix for .Host when port is absent
|
- templates: Bug fix for .Host when port is absent
|
||||||
- templates: Include Last-Modified header in response
|
- templates: Include Last-Modified header in response
|
||||||
- templates: Support for custom delimiters
|
- templates: Support for custom delimiters
|
||||||
- tls: For non-local hosts, default port is now 443 unless specified
|
- tls: For non-local hosts, default port is now 443 unless specified
|
||||||
- tls: Force-disable HTTPS
|
- tls: Force-disable HTTPS
|
||||||
- tls: Specify Let's Encrypt email address
|
- tls: Specify Let's Encrypt email address
|
||||||
- Many, many more tests and numerous bug fixes and improvements
|
- Many, many more tests and numerous bug fixes and improvements
|
||||||
|
|
||||||
|
|
||||||
0.7.6 (September 28, 2015)
|
0.7.6 (September 28, 2015)
|
||||||
- Pass in simple Caddyfile as command line arguments
|
- Pass in simple Caddyfile as command line arguments
|
||||||
- basicauth: Support for legacy htpasswd files
|
- basicauth: Support for legacy htpasswd files
|
||||||
- browse: JSON response with file listing
|
- browse: JSON response with file listing
|
||||||
- core: Caddyfile as command line argument
|
- core: Caddyfile as command line argument
|
||||||
- errors: Can write full stack trace to HTTP response for debugging
|
- errors: Can write full stack trace to HTTP response for debugging
|
||||||
- errors, log: Roll log files after certain size or age
|
- errors, log: Roll log files after certain size or age
|
||||||
- proxy: Fix for 32-bit architectures
|
- proxy: Fix for 32-bit architectures
|
||||||
- rewrite: Better compatibility with fastcgi and PHP apps
|
- rewrite: Better compatibility with fastcgi and PHP apps
|
||||||
- templates: Added .StripExt and .StripHTML methods
|
- templates: Added .StripExt and .StripHTML methods
|
||||||
- Internal improvements and minor bug fixes
|
- Internal improvements and minor bug fixes
|
||||||
|
|
||||||
|
|
||||||
0.7.5 (August 5, 2015)
|
0.7.5 (August 5, 2015)
|
||||||
- core: All listeners bind to 0.0.0.0 unless 'bind' directive is used
|
- core: All listeners bind to 0.0.0.0 unless 'bind' directive is used
|
||||||
- fastcgi: Set HTTPS env variable if connection is secure
|
- fastcgi: Set HTTPS env variable if connection is secure
|
||||||
- log: Output to system log (except Windows)
|
- log: Output to system log (except Windows)
|
||||||
- markdown: Added dev command to disable caching during development
|
- markdown: Added dev command to disable caching during development
|
||||||
- markdown: Fixed error reporting during initial site generation
|
- markdown: Fixed error reporting during initial site generation
|
||||||
- markdown: Fixed crash if path does not exist when server starts
|
- markdown: Fixed crash if path does not exist when server starts
|
||||||
- markdown: Fixed site generation and link indexing when files change
|
- markdown: Fixed site generation and link indexing when files change
|
||||||
- templates: Added .NowDate for use in date-related functions
|
- templates: Added .NowDate for use in date-related functions
|
||||||
- Several bug fixes related to startup and shutdown functions
|
- Several bug fixes related to startup and shutdown functions
|
||||||
|
|
||||||
|
|
||||||
0.7.4 (July 30, 2015)
|
0.7.4 (July 30, 2015)
|
||||||
- browse: Sorting preference persisted in cookie
|
- browse: Sorting preference persisted in cookie
|
||||||
- browse: Added index.txt and default.txt to list of default files
|
- browse: Added index.txt and default.txt to list of default files
|
||||||
- browse: Template files may now use Caddy template actions
|
- browse: Template files may now use Caddy template actions
|
||||||
- markdown: Template files may now use Caddy template actions
|
- markdown: Template files may now use Caddy template actions
|
||||||
- markdown: Several bug fixes, especially for large and empty Markdown files
|
- markdown: Several bug fixes, especially for large and empty Markdown files
|
||||||
- markdown: Generate index pages to link to markdown pages (sitegen only)
|
- markdown: Generate index pages to link to markdown pages (sitegen only)
|
||||||
- markdown: Flatten structure of front matter, changed template variables
|
- markdown: Flatten structure of front matter, changed template variables
|
||||||
- redir: Can use variables (placeholders) like log formats can
|
- redir: Can use variables (placeholders) like log formats can
|
||||||
- redir: Catch-all redirects no longer preserve path; use {uri} instead
|
- redir: Catch-all redirects no longer preserve path; use {uri} instead
|
||||||
- redir: Syntax supports redirect tables by opening a block
|
- redir: Syntax supports redirect tables by opening a block
|
||||||
- templates: Renamed .Date to .Now and added .Truncate, .Replace actions
|
- templates: Renamed .Date to .Now and added .Truncate, .Replace actions
|
||||||
- Other minor internal improvements and more tests
|
- Other minor internal improvements and more tests
|
||||||
|
|
||||||
|
|
||||||
0.7.3 (July 15, 2015)
|
0.7.3 (July 15, 2015)
|
||||||
- errors: Error log now shows timestamp with each entry
|
- errors: Error log now shows timestamp with each entry
|
||||||
- gzip: Fixed; Default filtering is by extension; removed MIME type filter
|
- gzip: Fixed; Default filtering is by extension; removed MIME type filter
|
||||||
- import: Fixed; works inside and outside server blocks
|
- import: Fixed; works inside and outside server blocks
|
||||||
- redir: Query string preserved on catch-all redirects
|
- redir: Query string preserved on catch-all redirects
|
||||||
- templates: Proper 403 or 404 errors for restricted or missing files
|
- templates: Proper 403 or 404 errors for restricted or missing files
|
||||||
|
|
||||||
|
|
||||||
0.7.2 (July 1, 2015)
|
0.7.2 (July 1, 2015)
|
||||||
- Custom builds through caddyserver.com - extend Caddy by writing addons
|
- Custom builds through caddyserver.com - extend Caddy by writing addons
|
||||||
- browse: Sort by clicking column heading or using query string
|
- browse: Sort by clicking column heading or using query string
|
||||||
- core: Serving hostname that doesn't resolve issues warning then listens on 0.0.0.0
|
- core: Serving hostname that doesn't resolve issues warning then listens on 0.0.0.0
|
||||||
- errors: Missing error page during parse time is warning, not error
|
- errors: Missing error page during parse time is warning, not error
|
||||||
- ext: Extension only appended if request path does not end in /
|
- ext: Extension only appended if request path does not end in /
|
||||||
- fastcgi: Fix for backend responding without status text
|
- fastcgi: Fix for backend responding without status text
|
||||||
- fastcgi: Fix PATH_TRANSLATED when PATH_INFO is empty (RFC 3875)
|
- fastcgi: Fix PATH_TRANSLATED when PATH_INFO is empty (RFC 3875)
|
||||||
- git: Removed from core (available as add-on)
|
- git: Removed from core (available as add-on)
|
||||||
- gzip: Enable by file path and/or extension
|
- gzip: Enable by file path and/or extension
|
||||||
- gzip: Customize compression level
|
- gzip: Customize compression level
|
||||||
- log: Fix for missing status in log entry when error unhandled
|
- log: Fix for missing status in log entry when error unhandled
|
||||||
- proxy: Strip prefix from path for proxy to path
|
- proxy: Strip prefix from path for proxy to path
|
||||||
- redir: Meta tag redirects
|
- redir: Meta tag redirects
|
||||||
- templates: Support for nested includes
|
- templates: Support for nested includes
|
||||||
- Internal improvements and more tests
|
- Internal improvements and more tests
|
||||||
|
|
||||||
|
|
||||||
0.7.1 (June 2, 2015)
|
0.7.1 (June 2, 2015)
|
||||||
- basicauth: Patched timing vulnerability
|
- basicauth: Patched timing vulnerability
|
||||||
- proxy: Support for WebSocket backends
|
- proxy: Support for WebSocket backends
|
||||||
- tls: Client authentication
|
- tls: Client authentication
|
||||||
|
|
||||||
|
|
||||||
0.7.0 (May 25, 2015)
|
0.7.0 (May 25, 2015)
|
||||||
- New directive 'internal' to protect resources with X-Accel-Redirect
|
- New directive 'internal' to protect resources with X-Accel-Redirect
|
||||||
- New -version flag to show program name and version
|
- New -version flag to show program name and version
|
||||||
- core: Fixed escaped backslash characters inside quoted strings
|
- core: Fixed escaped backslash characters inside quoted strings
|
||||||
- core: Fixed parsing Caddyfile for IPv6 addresses missing ports
|
- core: Fixed parsing Caddyfile for IPv6 addresses missing ports
|
||||||
- core: A notice is shown when non-local address resolves to loopback interface
|
- core: A notice is shown when non-local address resolves to loopback interface
|
||||||
- core: Warns if file descriptor limit is too low for production site (Mac/Linux)
|
- core: Warns if file descriptor limit is too low for production site (Mac/Linux)
|
||||||
- fastcgi: Support for Unix sockets
|
- fastcgi: Support for Unix sockets
|
||||||
- git: Fixed issue that prevented pulling at designated interval
|
- git: Fixed issue that prevented pulling at designated interval
|
||||||
- header: Remove a header field by prefixing field name with "-"
|
- header: Remove a header field by prefixing field name with "-"
|
||||||
- markdown: Simple static site generation
|
- markdown: Simple static site generation
|
||||||
- markdown: Support for metadata ("front matter") at beginning of files
|
- markdown: Support for metadata ("front matter") at beginning of files
|
||||||
- rewrite: Experimental support for regular expressions
|
- rewrite: Experimental support for regular expressions
|
||||||
- tls: Customize cipher suites and protocols
|
- tls: Customize cipher suites and protocols
|
||||||
- tls: Removed RC4 ciphers
|
- tls: Removed RC4 ciphers
|
||||||
- Other internal improvements that are not user-facing (more tests, etc.)
|
- Other internal improvements that are not user-facing (more tests, etc.)
|
||||||
|
|
||||||
|
|
||||||
0.6.0 (May 7, 2015)
|
0.6.0 (May 7, 2015)
|
||||||
- New directive 'git' to automatically pull changes
|
- New directive 'git' to automatically pull changes
|
||||||
- New directive 'bind' to override host server binds to
|
- New directive 'bind' to override host server binds to
|
||||||
- New -root flag to specify root path to default site
|
- New -root flag to specify root path to default site
|
||||||
- Ability to receive config data piped through stdin
|
- Ability to receive config data piped through stdin
|
||||||
- core: Warning if root directory doesn't exist at startup
|
- core: Warning if root directory doesn't exist at startup
|
||||||
- core: Entire process dies if any server fails to start
|
- core: Entire process dies if any server fails to start
|
||||||
- gzip: Fixed Content-Length value when proxying requests
|
- gzip: Fixed Content-Length value when proxying requests
|
||||||
- errors: Error log now includes file and line number of panics
|
- errors: Error log now includes file and line number of panics
|
||||||
- fastcgi: Pass custom environment variables
|
- fastcgi: Pass custom environment variables
|
||||||
- fastcgi: Support for HEAD, OPTIONS, PUT, PATCH, and DELETE methods
|
- fastcgi: Support for HEAD, OPTIONS, PUT, PATCH, and DELETE methods
|
||||||
- fastcgi: Fixed SERVER_SOFTWARE variables
|
- fastcgi: Fixed SERVER_SOFTWARE variables
|
||||||
- markdown: Support for index files when URL points to a directory
|
- markdown: Support for index files when URL points to a directory
|
||||||
- proxy: Load balancing with multiple backends, health checks, failovers, and multiple policies
|
- proxy: Load balancing with multiple backends, health checks, failovers, and multiple policies
|
||||||
- proxy: Add custom headers
|
- proxy: Add custom headers
|
||||||
- startup/shutdown: Run command in background with '&' at end
|
- startup/shutdown: Run command in background with '&' at end
|
||||||
- templates: Added .tpl and .tmpl as default extensions
|
- templates: Added .tpl and .tmpl as default extensions
|
||||||
- templates: Support for index files when URL points to a directory
|
- templates: Support for index files when URL points to a directory
|
||||||
- templates: Changed .RemoteAddr to .IP and stripped out remote port
|
- templates: Changed .RemoteAddr to .IP and stripped out remote port
|
||||||
- tls: TLS disabled (with warning) for servers that are explicitly http://
|
- tls: TLS disabled (with warning) for servers that are explicitly http://
|
||||||
- websocket: Fixed SERVER_SOFTWARE and GATEWAY_INTERFACE variables
|
- websocket: Fixed SERVER_SOFTWARE and GATEWAY_INTERFACE variables
|
||||||
- Many internal improvements
|
- Many internal improvements
|
||||||
|
|
||||||
|
|
||||||
0.5.1 (April 30, 2015)
|
0.5.1 (April 30, 2015)
|
||||||
- Default host is now 0.0.0.0 (wildcard)
|
- Default host is now 0.0.0.0 (wildcard)
|
||||||
- New -host and -port flags to override default host and port
|
- New -host and -port flags to override default host and port
|
||||||
- core: Support for binding to 0.0.0.0
|
- core: Support for binding to 0.0.0.0
|
||||||
- core: Graceful error handling during heavy load; proper error responses
|
- core: Graceful error handling during heavy load; proper error responses
|
||||||
- errors: Fixed file path handling
|
- errors: Fixed file path handling
|
||||||
- errors: Fixed panic due to nil log file
|
- errors: Fixed panic due to nil log file
|
||||||
- fastcgi: Support for index files
|
- fastcgi: Support for index files
|
||||||
- fastcgi: Fix for handling errors that come from responder
|
- fastcgi: Fix for handling errors that come from responder
|
||||||
|
|
||||||
|
|
||||||
0.5.0 (April 28, 2015)
|
0.5.0 (April 28, 2015)
|
||||||
- Initial release
|
- Initial release
|
||||||
|
|
1078
dist/LICENSES.txt
vendored
1078
dist/LICENSES.txt
vendored
File diff suppressed because it is too large
Load Diff
42
dist/README.txt
vendored
42
dist/README.txt
vendored
|
@ -1,21 +1,21 @@
|
||||||
CADDY 0.8
|
CADDY 0.8.1
|
||||||
|
|
||||||
Website
|
Website
|
||||||
https://caddyserver.com
|
https://caddyserver.com
|
||||||
@caddyserver
|
@caddyserver
|
||||||
|
|
||||||
Source Code
|
Source Code
|
||||||
https://github.com/mholt/caddy
|
https://github.com/mholt/caddy
|
||||||
|
|
||||||
|
|
||||||
For instructions on using Caddy, please see the user guide on the website. For a list of what's new in this version, see CHANGES.txt.
|
For instructions on using Caddy, please see the user guide on the website. For a list of what's new in this version, see CHANGES.txt.
|
||||||
|
|
||||||
If you have a question, bug report, or would like to contribute, please open an issue or submit a pull request on GitHub. Your contributions do not go unnoticed!
|
If you have a question, bug report, or would like to contribute, please open an issue or submit a pull request on GitHub. Your contributions do not go unnoticed!
|
||||||
|
|
||||||
For a good time, follow @mholt6 on Twitter.
|
For a good time, follow @mholt6 on Twitter.
|
||||||
|
|
||||||
And thanks - you're awesome!
|
And thanks - you're awesome!
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
(c) 2015 Matthew Holt
|
(c) 2015 Matthew Holt
|
||||||
|
|
2
main.go
2
main.go
|
@ -27,7 +27,7 @@ var (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
appName = "Caddy"
|
appName = "Caddy"
|
||||||
appVersion = "0.8"
|
appVersion = "0.8.1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
|
@ -196,7 +196,7 @@ func directoryListing(files []os.FileInfo, r *http.Request, canGoUp bool, root s
|
||||||
fileCount++
|
fileCount++
|
||||||
}
|
}
|
||||||
|
|
||||||
url := url.URL{Path: name}
|
url := url.URL{Path: "./" + name} // prepend with "./" to fix paths with ':' in the name
|
||||||
|
|
||||||
fileinfos = append(fileinfos, FileInfo{
|
fileinfos = append(fileinfos, FileInfo{
|
||||||
IsDir: f.IsDir(),
|
IsDir: f.IsDir(),
|
||||||
|
|
|
@ -147,11 +147,11 @@ func TestBrowseTemplate(t *testing.T) {
|
||||||
|
|
||||||
<h1>/photos/</h1>
|
<h1>/photos/</h1>
|
||||||
|
|
||||||
<a href="test.html">test.html</a><br>
|
<a href="./test.html">test.html</a><br>
|
||||||
|
|
||||||
<a href="test2.html">test2.html</a><br>
|
<a href="./test2.html">test2.html</a><br>
|
||||||
|
|
||||||
<a href="test3.html">test3.html</a><br>
|
<a href="./test3.html">test3.html</a><br>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -209,7 +209,7 @@ func TestBrowseJson(t *testing.T) {
|
||||||
name += "/"
|
name += "/"
|
||||||
}
|
}
|
||||||
|
|
||||||
url := url.URL{Path: name}
|
url := url.URL{Path: "./" + name}
|
||||||
|
|
||||||
fileinfos = append(fileinfos, FileInfo{
|
fileinfos = append(fileinfos, FileInfo{
|
||||||
IsDir: f.IsDir(),
|
IsDir: f.IsDir(),
|
||||||
|
|
|
@ -15,7 +15,7 @@ type RequestFilter interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaultExtensions is the list of default extensions for which to enable gzipping.
|
// defaultExtensions is the list of default extensions for which to enable gzipping.
|
||||||
var defaultExtensions = []string{"", ".txt", ".htm", ".html", ".css", ".php", ".js", ".json", ".md", ".xml"}
|
var defaultExtensions = []string{"", ".txt", ".htm", ".html", ".css", ".php", ".js", ".json", ".md", ".xml", ".svg"}
|
||||||
|
|
||||||
// DefaultExtFilter creates an ExtFilter with default extensions.
|
// DefaultExtFilter creates an ExtFilter with default extensions.
|
||||||
func DefaultExtFilter() ExtFilter {
|
func DefaultExtFilter() ExtFilter {
|
||||||
|
|
|
@ -57,6 +57,10 @@ func (uh *UpstreamHost) Down() bool {
|
||||||
return uh.CheckDown(uh)
|
return uh.CheckDown(uh)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tryDuration is how long to try upstream hosts; failures result in
|
||||||
|
// immediate retries until this duration ends or we get a nil host.
|
||||||
|
var tryDuration = 60 * time.Second
|
||||||
|
|
||||||
// ServeHTTP satisfies the middleware.Handler interface.
|
// ServeHTTP satisfies the middleware.Handler interface.
|
||||||
func (p Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
|
func (p Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
|
||||||
|
|
||||||
|
@ -68,7 +72,7 @@ func (p Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
|
||||||
|
|
||||||
// Since Select() should give us "up" hosts, keep retrying
|
// Since Select() should give us "up" hosts, keep retrying
|
||||||
// hosts until timeout (or until we get a nil host).
|
// hosts until timeout (or until we get a nil host).
|
||||||
for time.Now().Sub(start) < (60 * time.Second) {
|
for time.Now().Sub(start) < tryDuration {
|
||||||
host := upstream.Select()
|
host := upstream.Select()
|
||||||
if host == nil {
|
if host == nil {
|
||||||
return http.StatusBadGateway, errUnreachable
|
return http.StatusBadGateway, errUnreachable
|
||||||
|
|
|
@ -4,10 +4,13 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
@ -15,6 +18,70 @@ import (
|
||||||
"golang.org/x/net/websocket"
|
"golang.org/x/net/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
tryDuration = 50 * time.Millisecond // prevent tests from hanging
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReverseProxy(t *testing.T) {
|
||||||
|
log.SetOutput(ioutil.Discard)
|
||||||
|
defer log.SetOutput(os.Stderr)
|
||||||
|
|
||||||
|
var requestReceived bool
|
||||||
|
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
requestReceived = true
|
||||||
|
w.Write([]byte("Hello, client"))
|
||||||
|
}))
|
||||||
|
defer backend.Close()
|
||||||
|
|
||||||
|
// set up proxy
|
||||||
|
p := &Proxy{
|
||||||
|
Upstreams: []Upstream{newFakeUpstream(backend.URL, false)},
|
||||||
|
}
|
||||||
|
|
||||||
|
// create request and response recorder
|
||||||
|
r, err := http.NewRequest("GET", "/", nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create request: %v", err)
|
||||||
|
}
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
p.ServeHTTP(w, r)
|
||||||
|
|
||||||
|
if !requestReceived {
|
||||||
|
t.Error("Expected backend to receive request, but it didn't")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReverseProxyInsecureSkipVerify(t *testing.T) {
|
||||||
|
log.SetOutput(ioutil.Discard)
|
||||||
|
defer log.SetOutput(os.Stderr)
|
||||||
|
|
||||||
|
var requestReceived bool
|
||||||
|
backend := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
requestReceived = true
|
||||||
|
w.Write([]byte("Hello, client"))
|
||||||
|
}))
|
||||||
|
defer backend.Close()
|
||||||
|
|
||||||
|
// set up proxy
|
||||||
|
p := &Proxy{
|
||||||
|
Upstreams: []Upstream{newFakeUpstream(backend.URL, true)},
|
||||||
|
}
|
||||||
|
|
||||||
|
// create request and response recorder
|
||||||
|
r, err := http.NewRequest("GET", "/", nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create request: %v", err)
|
||||||
|
}
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
p.ServeHTTP(w, r)
|
||||||
|
|
||||||
|
if !requestReceived {
|
||||||
|
t.Error("Even with insecure HTTPS, expected backend to receive request, but it didn't")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestWebSocketReverseProxyServeHTTPHandler(t *testing.T) {
|
func TestWebSocketReverseProxyServeHTTPHandler(t *testing.T) {
|
||||||
// No-op websocket backend simply allows the WS connection to be
|
// No-op websocket backend simply allows the WS connection to be
|
||||||
// accepted then it will be immediately closed. Perfect for testing.
|
// accepted then it will be immediately closed. Perfect for testing.
|
||||||
|
@ -93,18 +160,24 @@ func TestWebSocketReverseProxyFromWSClient(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// newWebSocketTestProxy returns a test proxy that will
|
func newFakeUpstream(name string, insecure bool) *fakeUpstream {
|
||||||
// redirect to the specified backendAddr. The function
|
uri, _ := url.Parse(name)
|
||||||
// also sets up the rules/environment for testing WebSocket
|
u := &fakeUpstream{
|
||||||
// proxy.
|
name: name,
|
||||||
func newWebSocketTestProxy(backendAddr string) *Proxy {
|
host: &UpstreamHost{
|
||||||
return &Proxy{
|
Name: name,
|
||||||
Upstreams: []Upstream{&fakeUpstream{name: backendAddr}},
|
ReverseProxy: NewSingleHostReverseProxy(uri, ""),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
if insecure {
|
||||||
|
u.host.ReverseProxy.Transport = InsecureTransport
|
||||||
|
}
|
||||||
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
type fakeUpstream struct {
|
type fakeUpstream struct {
|
||||||
name string
|
name string
|
||||||
|
host *UpstreamHost
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *fakeUpstream) From() string {
|
func (u *fakeUpstream) From() string {
|
||||||
|
@ -112,6 +185,32 @@ func (u *fakeUpstream) From() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *fakeUpstream) Select() *UpstreamHost {
|
func (u *fakeUpstream) Select() *UpstreamHost {
|
||||||
|
return u.host
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *fakeUpstream) IsAllowedPath(requestPath string) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// newWebSocketTestProxy returns a test proxy that will
|
||||||
|
// redirect to the specified backendAddr. The function
|
||||||
|
// also sets up the rules/environment for testing WebSocket
|
||||||
|
// proxy.
|
||||||
|
func newWebSocketTestProxy(backendAddr string) *Proxy {
|
||||||
|
return &Proxy{
|
||||||
|
Upstreams: []Upstream{&fakeWsUpstream{name: backendAddr}},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type fakeWsUpstream struct {
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *fakeWsUpstream) From() string {
|
||||||
|
return "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *fakeWsUpstream) Select() *UpstreamHost {
|
||||||
uri, _ := url.Parse(u.name)
|
uri, _ := url.Parse(u.name)
|
||||||
return &UpstreamHost{
|
return &UpstreamHost{
|
||||||
Name: u.name,
|
Name: u.name,
|
||||||
|
@ -122,7 +221,7 @@ func (u *fakeUpstream) Select() *UpstreamHost {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *fakeUpstream) IsAllowedPath(requestPath string) bool {
|
func (u *fakeWsUpstream) IsAllowedPath(requestPath string) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
package proxy
|
package proxy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -103,6 +104,16 @@ var hopHeaders = []string{
|
||||||
"Upgrade",
|
"Upgrade",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var InsecureTransport http.RoundTripper = &http.Transport{
|
||||||
|
Proxy: http.ProxyFromEnvironment,
|
||||||
|
Dial: (&net.Dialer{
|
||||||
|
Timeout: 30 * time.Second,
|
||||||
|
KeepAlive: 30 * time.Second,
|
||||||
|
}).Dial,
|
||||||
|
TLSHandshakeTimeout: 10 * time.Second,
|
||||||
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
|
}
|
||||||
|
|
||||||
func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request, extraHeaders http.Header) error {
|
func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request, extraHeaders http.Header) error {
|
||||||
transport := p.Transport
|
transport := p.Transport
|
||||||
if transport == nil {
|
if transport == nil {
|
||||||
|
|
|
@ -19,10 +19,11 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
type staticUpstream struct {
|
type staticUpstream struct {
|
||||||
from string
|
from string
|
||||||
proxyHeaders http.Header
|
proxyHeaders http.Header
|
||||||
Hosts HostPool
|
Hosts HostPool
|
||||||
Policy Policy
|
Policy Policy
|
||||||
|
insecureSkipVerify bool
|
||||||
|
|
||||||
FailTimeout time.Duration
|
FailTimeout time.Duration
|
||||||
MaxFails int32
|
MaxFails int32
|
||||||
|
@ -90,6 +91,9 @@ func NewStaticUpstreams(c parse.Dispenser) ([]Upstream, error) {
|
||||||
}
|
}
|
||||||
if baseURL, err := url.Parse(uh.Name); err == nil {
|
if baseURL, err := url.Parse(uh.Name); err == nil {
|
||||||
uh.ReverseProxy = NewSingleHostReverseProxy(baseURL, uh.WithoutPathPrefix)
|
uh.ReverseProxy = NewSingleHostReverseProxy(baseURL, uh.WithoutPathPrefix)
|
||||||
|
if upstream.insecureSkipVerify {
|
||||||
|
uh.ReverseProxy.Transport = InsecureTransport
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return upstreams, err
|
return upstreams, err
|
||||||
}
|
}
|
||||||
|
@ -175,6 +179,8 @@ func parseBlock(c *parse.Dispenser, u *staticUpstream) error {
|
||||||
return c.ArgErr()
|
return c.ArgErr()
|
||||||
}
|
}
|
||||||
u.IgnoredSubPaths = ignoredPaths
|
u.IgnoredSubPaths = ignoredPaths
|
||||||
|
case "insecure_skip_verify":
|
||||||
|
u.insecureSkipVerify = true
|
||||||
default:
|
default:
|
||||||
return c.Errf("unknown property '%s'", c.Val())
|
return c.Errf("unknown property '%s'", c.Val())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user