Rewrote Caddy from the ground up; initial commit of 0.9 branch
These changes span work from the last ~4 months in an effort to make
Caddy more extensible, reduce the coupling between its components, and
lay a more robust foundation of code going forward into 1.0. A bunch of
new features have been added, too, with even higher future potential.
The most significant design change is an overall inversion of
dependencies. Instead of the caddy package knowing about the server
and the notion of middleware and config, the caddy package exposes an
interface that other components plug into. This does introduce more
indirection when reading the code, but every piece is very modular and
pluggable. Even the HTTP server is pluggable.
The caddy package has been moved to the top level, and main has been
pushed into a subfolder called caddy. The actual logic of the main
file has been pushed even further into caddy/caddymain/run.go so that
custom builds of Caddy can be 'go get'able.
The HTTPS logic was surgically separated into two parts to divide the
TLS-specific code and the HTTPS-specific code. The caddytls package can
now be used by any type of server that needs TLS, not just HTTP. I also
added the ability to customize nearly every aspect of TLS at the site
level rather than all sites sharing the same TLS configuration. Not all
of this flexibility is exposed in the Caddyfile yet, but it may be in
the future. Caddy can also generate self-signed certificates in memory
for the convenience of a developer working on localhost who wants HTTPS.
And Caddy now supports the DNS challenge, assuming at least one DNS
provider is plugged in.
Dozens, if not hundreds, of other minor changes swept through the code
base as I literally started from an empty main function, copying over
functions or files as needed, then adjusting them to fit in the new
design. Most tests have been restored and adapted to the new API,
but more work is needed there.
A lot of what was "impossible" before is now possible, or can be made
possible with minimal disruption of the code. For example, it's fairly
easy to make plugins hook into another part of the code via callbacks.
Plugins can do more than just be directives; we now have plugins that
customize how the Caddyfile is loaded (useful when you need to get your
configuration from a remote store).
Site addresses no longer need be just a host and port. They can have a
path, allowing you to scope a configuration to a specific path. There is
no inheretance, however; each site configuration is distinct.
Thanks to amazing work by Lucas Clemente, this commit adds experimental
QUIC support. Turn it on using the -quic flag; your browser may have
to be configured to enable it.
Almost everything is here, but you will notice that most of the middle-
ware are missing. After those are transferred over, we'll be ready for
beta tests.
I'm very excited to get this out. Thanks for everyone's help and
patience these last few months. I hope you like it!!
2016-06-04 18:00:29 -05:00
|
|
|
// Package httpserver implements an HTTP server on top of Caddy.
|
|
|
|
package httpserver
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/tls"
|
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
"net"
|
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
"path"
|
|
|
|
"runtime"
|
|
|
|
"strings"
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/lucas-clemente/quic-go/h2quic"
|
|
|
|
"github.com/mholt/caddy"
|
|
|
|
"github.com/mholt/caddy/caddyhttp/staticfiles"
|
|
|
|
"github.com/mholt/caddy/caddytls"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Server is the HTTP server implementation.
|
|
|
|
type Server struct {
|
|
|
|
Server *http.Server
|
|
|
|
quicServer *h2quic.Server
|
|
|
|
listener net.Listener
|
|
|
|
listenerMu sync.Mutex
|
|
|
|
sites []*SiteConfig
|
|
|
|
connTimeout time.Duration // max time to wait for a connection before force stop
|
|
|
|
connWg sync.WaitGroup // one increment per connection
|
|
|
|
tlsGovChan chan struct{} // close to stop the TLS maintenance goroutine
|
|
|
|
vhosts *vhostTrie
|
|
|
|
}
|
|
|
|
|
|
|
|
// ensure it satisfies the interface
|
|
|
|
var _ caddy.GracefulServer = new(Server)
|
|
|
|
|
|
|
|
// NewServer creates a new Server instance that will listen on addr
|
|
|
|
// and will serve the sites configured in group.
|
|
|
|
func NewServer(addr string, group []*SiteConfig) (*Server, error) {
|
|
|
|
s := &Server{
|
|
|
|
Server: &http.Server{
|
|
|
|
Addr: addr,
|
|
|
|
// TODO: Make these values configurable?
|
|
|
|
// ReadTimeout: 2 * time.Minute,
|
|
|
|
// WriteTimeout: 2 * time.Minute,
|
|
|
|
// MaxHeaderBytes: 1 << 16,
|
|
|
|
},
|
|
|
|
vhosts: newVHostTrie(),
|
|
|
|
sites: group,
|
|
|
|
connTimeout: GracefulTimeout,
|
|
|
|
}
|
|
|
|
s.Server.Handler = s // this is weird, but whatever
|
2016-06-07 00:01:03 -05:00
|
|
|
s.Server.ConnState = func(c net.Conn, cs http.ConnState) {
|
|
|
|
if cs == http.StateIdle {
|
|
|
|
s.listenerMu.Lock()
|
|
|
|
// server stopped, close idle connection
|
|
|
|
if s.listener == nil {
|
|
|
|
c.Close()
|
|
|
|
}
|
|
|
|
s.listenerMu.Unlock()
|
|
|
|
}
|
|
|
|
}
|
Rewrote Caddy from the ground up; initial commit of 0.9 branch
These changes span work from the last ~4 months in an effort to make
Caddy more extensible, reduce the coupling between its components, and
lay a more robust foundation of code going forward into 1.0. A bunch of
new features have been added, too, with even higher future potential.
The most significant design change is an overall inversion of
dependencies. Instead of the caddy package knowing about the server
and the notion of middleware and config, the caddy package exposes an
interface that other components plug into. This does introduce more
indirection when reading the code, but every piece is very modular and
pluggable. Even the HTTP server is pluggable.
The caddy package has been moved to the top level, and main has been
pushed into a subfolder called caddy. The actual logic of the main
file has been pushed even further into caddy/caddymain/run.go so that
custom builds of Caddy can be 'go get'able.
The HTTPS logic was surgically separated into two parts to divide the
TLS-specific code and the HTTPS-specific code. The caddytls package can
now be used by any type of server that needs TLS, not just HTTP. I also
added the ability to customize nearly every aspect of TLS at the site
level rather than all sites sharing the same TLS configuration. Not all
of this flexibility is exposed in the Caddyfile yet, but it may be in
the future. Caddy can also generate self-signed certificates in memory
for the convenience of a developer working on localhost who wants HTTPS.
And Caddy now supports the DNS challenge, assuming at least one DNS
provider is plugged in.
Dozens, if not hundreds, of other minor changes swept through the code
base as I literally started from an empty main function, copying over
functions or files as needed, then adjusting them to fit in the new
design. Most tests have been restored and adapted to the new API,
but more work is needed there.
A lot of what was "impossible" before is now possible, or can be made
possible with minimal disruption of the code. For example, it's fairly
easy to make plugins hook into another part of the code via callbacks.
Plugins can do more than just be directives; we now have plugins that
customize how the Caddyfile is loaded (useful when you need to get your
configuration from a remote store).
Site addresses no longer need be just a host and port. They can have a
path, allowing you to scope a configuration to a specific path. There is
no inheretance, however; each site configuration is distinct.
Thanks to amazing work by Lucas Clemente, this commit adds experimental
QUIC support. Turn it on using the -quic flag; your browser may have
to be configured to enable it.
Almost everything is here, but you will notice that most of the middle-
ware are missing. After those are transferred over, we'll be ready for
beta tests.
I'm very excited to get this out. Thanks for everyone's help and
patience these last few months. I hope you like it!!
2016-06-04 18:00:29 -05:00
|
|
|
|
|
|
|
// Disable HTTP/2 if desired
|
|
|
|
if !HTTP2 {
|
|
|
|
s.Server.TLSNextProto = make(map[string]func(*http.Server, *tls.Conn, http.Handler))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Enable QUIC if desired
|
|
|
|
if QUIC {
|
|
|
|
s.quicServer = &h2quic.Server{Server: s.Server}
|
|
|
|
}
|
|
|
|
|
|
|
|
// We have to bound our wg with one increment
|
|
|
|
// to prevent a "race condition" that is hard-coded
|
|
|
|
// into sync.WaitGroup.Wait() - basically, an add
|
|
|
|
// with a positive delta must be guaranteed to
|
|
|
|
// occur before Wait() is called on the wg.
|
|
|
|
// In a way, this kind of acts as a safety barrier.
|
|
|
|
s.connWg.Add(1)
|
|
|
|
|
|
|
|
// Set up TLS configuration
|
|
|
|
var tlsConfigs []*caddytls.Config
|
|
|
|
var err error
|
|
|
|
for _, site := range group {
|
|
|
|
tlsConfigs = append(tlsConfigs, site.TLS)
|
|
|
|
}
|
|
|
|
s.Server.TLSConfig, err = caddytls.MakeTLSConfig(tlsConfigs)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compile custom middleware for every site (enables virtual hosting)
|
|
|
|
for _, site := range group {
|
|
|
|
stack := Handler(staticfiles.FileServer{Root: http.Dir(site.Root), Hide: site.HiddenFiles})
|
|
|
|
for i := len(site.middleware) - 1; i >= 0; i-- {
|
|
|
|
stack = site.middleware[i](stack)
|
|
|
|
}
|
|
|
|
site.middlewareChain = stack
|
|
|
|
s.vhosts.Insert(site.Addr.VHost(), site)
|
|
|
|
}
|
|
|
|
|
|
|
|
return s, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Listen creates an active listener for s that can be
|
|
|
|
// used to serve requests.
|
|
|
|
func (s *Server) Listen() (net.Listener, error) {
|
|
|
|
if s.Server == nil {
|
|
|
|
return nil, fmt.Errorf("Server field is nil")
|
|
|
|
}
|
|
|
|
|
|
|
|
ln, err := net.Listen("tcp", s.Server.Addr)
|
|
|
|
if err != nil {
|
|
|
|
var succeeded bool
|
|
|
|
if runtime.GOOS == "windows" {
|
|
|
|
// Windows has been known to keep sockets open even after closing the listeners.
|
|
|
|
// Tests reveal this error case easily because they call Start() then Stop()
|
|
|
|
// in succession. TODO: Better way to handle this? And why limit this to Windows?
|
|
|
|
for i := 0; i < 20; i++ {
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
ln, err = net.Listen("tcp", s.Server.Addr)
|
|
|
|
if err == nil {
|
|
|
|
succeeded = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !succeeded {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Very important to return a concrete caddy.Listener
|
|
|
|
// implementation for graceful restarts.
|
|
|
|
return ln.(*net.TCPListener), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Serve serves requests on ln. It blocks until ln is closed.
|
|
|
|
func (s *Server) Serve(ln net.Listener) error {
|
|
|
|
if tcpLn, ok := ln.(*net.TCPListener); ok {
|
|
|
|
ln = tcpKeepAliveListener{TCPListener: tcpLn}
|
|
|
|
}
|
|
|
|
|
|
|
|
ln = newGracefulListener(ln, &s.connWg)
|
|
|
|
|
|
|
|
s.listenerMu.Lock()
|
|
|
|
s.listener = ln
|
|
|
|
s.listenerMu.Unlock()
|
|
|
|
|
|
|
|
if s.Server.TLSConfig != nil {
|
|
|
|
// Create TLS listener - note that we do not replace s.listener
|
|
|
|
// with this TLS listener; tls.listener is unexported and does
|
|
|
|
// not implement the File() method we need for graceful restarts
|
|
|
|
// on POSIX systems.
|
|
|
|
// TODO: Is this ^ still relevant anymore? Maybe we can now that it's a net.Listener...
|
|
|
|
ln = tls.NewListener(ln, s.Server.TLSConfig)
|
|
|
|
|
|
|
|
// Rotate TLS session ticket keys
|
|
|
|
s.tlsGovChan = caddytls.RotateSessionTicketKeys(s.Server.TLSConfig)
|
|
|
|
}
|
|
|
|
|
|
|
|
if QUIC {
|
|
|
|
go func() {
|
|
|
|
err := s.quicServer.ListenAndServe()
|
|
|
|
if err != nil {
|
|
|
|
log.Printf("[ERROR] listening for QUIC connections: %v", err)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
|
|
|
|
err := s.Server.Serve(ln)
|
|
|
|
if QUIC {
|
|
|
|
s.quicServer.Close()
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// ServeHTTP is the entry point of all HTTP requests.
|
|
|
|
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
|
|
defer func() {
|
|
|
|
// We absolutely need to be sure we stay alive up here,
|
|
|
|
// even though, in theory, the errors middleware does this.
|
|
|
|
if rec := recover(); rec != nil {
|
|
|
|
log.Printf("[PANIC] %v", rec)
|
|
|
|
DefaultErrorFunc(w, r, http.StatusInternalServerError)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
w.Header().Set("Server", "Caddy")
|
|
|
|
|
|
|
|
sanitizePath(r)
|
|
|
|
|
|
|
|
status, _ := s.serveHTTP(w, r)
|
|
|
|
|
|
|
|
// Fallback error response in case error handling wasn't chained in
|
|
|
|
if status >= 400 {
|
|
|
|
DefaultErrorFunc(w, r, status)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Server) serveHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
|
|
|
|
// strip out the port because it's not used in virtual
|
|
|
|
// hosting; the port is irrelevant because each listener
|
|
|
|
// is on a different port.
|
|
|
|
hostname, _, err := net.SplitHostPort(r.Host)
|
|
|
|
if err != nil {
|
|
|
|
hostname = r.Host
|
|
|
|
}
|
|
|
|
|
|
|
|
// look up the virtualhost; if no match, serve error
|
|
|
|
vhost, pathPrefix := s.vhosts.Match(hostname + r.URL.Path)
|
|
|
|
|
|
|
|
if vhost == nil {
|
|
|
|
// check for ACME challenge even if vhost is nil;
|
|
|
|
// could be a new host coming online soon
|
|
|
|
if caddytls.HTTPChallengeHandler(w, r, caddytls.DefaultHTTPAlternatePort) {
|
|
|
|
return 0, nil
|
|
|
|
}
|
|
|
|
// otherwise, log the error and write a message to the client
|
|
|
|
remoteHost, _, err := net.SplitHostPort(r.RemoteAddr)
|
|
|
|
if err != nil {
|
|
|
|
remoteHost = r.RemoteAddr
|
|
|
|
}
|
2016-06-04 23:48:27 -05:00
|
|
|
WriteTextResponse(w, http.StatusNotFound, "No such site at "+s.Server.Addr)
|
Rewrote Caddy from the ground up; initial commit of 0.9 branch
These changes span work from the last ~4 months in an effort to make
Caddy more extensible, reduce the coupling between its components, and
lay a more robust foundation of code going forward into 1.0. A bunch of
new features have been added, too, with even higher future potential.
The most significant design change is an overall inversion of
dependencies. Instead of the caddy package knowing about the server
and the notion of middleware and config, the caddy package exposes an
interface that other components plug into. This does introduce more
indirection when reading the code, but every piece is very modular and
pluggable. Even the HTTP server is pluggable.
The caddy package has been moved to the top level, and main has been
pushed into a subfolder called caddy. The actual logic of the main
file has been pushed even further into caddy/caddymain/run.go so that
custom builds of Caddy can be 'go get'able.
The HTTPS logic was surgically separated into two parts to divide the
TLS-specific code and the HTTPS-specific code. The caddytls package can
now be used by any type of server that needs TLS, not just HTTP. I also
added the ability to customize nearly every aspect of TLS at the site
level rather than all sites sharing the same TLS configuration. Not all
of this flexibility is exposed in the Caddyfile yet, but it may be in
the future. Caddy can also generate self-signed certificates in memory
for the convenience of a developer working on localhost who wants HTTPS.
And Caddy now supports the DNS challenge, assuming at least one DNS
provider is plugged in.
Dozens, if not hundreds, of other minor changes swept through the code
base as I literally started from an empty main function, copying over
functions or files as needed, then adjusting them to fit in the new
design. Most tests have been restored and adapted to the new API,
but more work is needed there.
A lot of what was "impossible" before is now possible, or can be made
possible with minimal disruption of the code. For example, it's fairly
easy to make plugins hook into another part of the code via callbacks.
Plugins can do more than just be directives; we now have plugins that
customize how the Caddyfile is loaded (useful when you need to get your
configuration from a remote store).
Site addresses no longer need be just a host and port. They can have a
path, allowing you to scope a configuration to a specific path. There is
no inheretance, however; each site configuration is distinct.
Thanks to amazing work by Lucas Clemente, this commit adds experimental
QUIC support. Turn it on using the -quic flag; your browser may have
to be configured to enable it.
Almost everything is here, but you will notice that most of the middle-
ware are missing. After those are transferred over, we'll be ready for
beta tests.
I'm very excited to get this out. Thanks for everyone's help and
patience these last few months. I hope you like it!!
2016-06-04 18:00:29 -05:00
|
|
|
log.Printf("[INFO] %s - No such site at %s (Remote: %s, Referer: %s)",
|
|
|
|
hostname, s.Server.Addr, remoteHost, r.Header.Get("Referer"))
|
|
|
|
return 0, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// we still check for ACME challenge if the vhost exists,
|
|
|
|
// because we must apply its HTTP challenge config settings
|
|
|
|
if s.proxyHTTPChallenge(vhost, w, r) {
|
|
|
|
return 0, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// trim the path portion of the site address from the beginning of
|
|
|
|
// the URL path, so a request to example.com/foo/blog on the site
|
|
|
|
// defined as example.com/foo appears as /blog instead of /foo/blog.
|
|
|
|
if pathPrefix != "/" {
|
|
|
|
r.URL.Path = strings.TrimPrefix(r.URL.Path, pathPrefix)
|
|
|
|
if !strings.HasPrefix(r.URL.Path, "/") {
|
|
|
|
r.URL.Path = "/" + r.URL.Path
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return vhost.middlewareChain.ServeHTTP(w, r)
|
|
|
|
}
|
|
|
|
|
|
|
|
// proxyHTTPChallenge solves the ACME HTTP challenge if r is the HTTP
|
|
|
|
// request for the challenge. If it is, and if the request has been
|
|
|
|
// fulfilled (response written), true is returned; false otherwise.
|
|
|
|
// If you don't have a vhost, just call the challenge handler directly.
|
|
|
|
func (s *Server) proxyHTTPChallenge(vhost *SiteConfig, w http.ResponseWriter, r *http.Request) bool {
|
|
|
|
if vhost.Addr.Port != caddytls.HTTPChallengePort {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if vhost.TLS != nil && vhost.TLS.Manual {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
altPort := caddytls.DefaultHTTPAlternatePort
|
|
|
|
if vhost.TLS != nil && vhost.TLS.AltHTTPPort != "" {
|
|
|
|
altPort = vhost.TLS.AltHTTPPort
|
|
|
|
}
|
|
|
|
return caddytls.HTTPChallengeHandler(w, r, altPort)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Address returns the address s was assigned to listen on.
|
|
|
|
func (s *Server) Address() string {
|
|
|
|
return s.Server.Addr
|
|
|
|
}
|
|
|
|
|
|
|
|
// Stop stops s gracefully (or forcefully after timeout) and
|
|
|
|
// closes its listener.
|
|
|
|
func (s *Server) Stop() (err error) {
|
|
|
|
s.Server.SetKeepAlivesEnabled(false)
|
|
|
|
|
|
|
|
if runtime.GOOS != "windows" {
|
|
|
|
// force connections to close after timeout
|
|
|
|
done := make(chan struct{})
|
|
|
|
go func() {
|
|
|
|
s.connWg.Done() // decrement our initial increment used as a barrier
|
|
|
|
s.connWg.Wait()
|
|
|
|
close(done)
|
|
|
|
}()
|
|
|
|
|
|
|
|
// Wait for remaining connections to finish or
|
|
|
|
// force them all to close after timeout
|
|
|
|
select {
|
|
|
|
case <-time.After(s.connTimeout):
|
|
|
|
case <-done:
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Close the listener now; this stops the server without delay
|
|
|
|
s.listenerMu.Lock()
|
|
|
|
if s.listener != nil {
|
|
|
|
err = s.listener.Close()
|
2016-06-07 00:01:03 -05:00
|
|
|
s.listener = nil
|
Rewrote Caddy from the ground up; initial commit of 0.9 branch
These changes span work from the last ~4 months in an effort to make
Caddy more extensible, reduce the coupling between its components, and
lay a more robust foundation of code going forward into 1.0. A bunch of
new features have been added, too, with even higher future potential.
The most significant design change is an overall inversion of
dependencies. Instead of the caddy package knowing about the server
and the notion of middleware and config, the caddy package exposes an
interface that other components plug into. This does introduce more
indirection when reading the code, but every piece is very modular and
pluggable. Even the HTTP server is pluggable.
The caddy package has been moved to the top level, and main has been
pushed into a subfolder called caddy. The actual logic of the main
file has been pushed even further into caddy/caddymain/run.go so that
custom builds of Caddy can be 'go get'able.
The HTTPS logic was surgically separated into two parts to divide the
TLS-specific code and the HTTPS-specific code. The caddytls package can
now be used by any type of server that needs TLS, not just HTTP. I also
added the ability to customize nearly every aspect of TLS at the site
level rather than all sites sharing the same TLS configuration. Not all
of this flexibility is exposed in the Caddyfile yet, but it may be in
the future. Caddy can also generate self-signed certificates in memory
for the convenience of a developer working on localhost who wants HTTPS.
And Caddy now supports the DNS challenge, assuming at least one DNS
provider is plugged in.
Dozens, if not hundreds, of other minor changes swept through the code
base as I literally started from an empty main function, copying over
functions or files as needed, then adjusting them to fit in the new
design. Most tests have been restored and adapted to the new API,
but more work is needed there.
A lot of what was "impossible" before is now possible, or can be made
possible with minimal disruption of the code. For example, it's fairly
easy to make plugins hook into another part of the code via callbacks.
Plugins can do more than just be directives; we now have plugins that
customize how the Caddyfile is loaded (useful when you need to get your
configuration from a remote store).
Site addresses no longer need be just a host and port. They can have a
path, allowing you to scope a configuration to a specific path. There is
no inheretance, however; each site configuration is distinct.
Thanks to amazing work by Lucas Clemente, this commit adds experimental
QUIC support. Turn it on using the -quic flag; your browser may have
to be configured to enable it.
Almost everything is here, but you will notice that most of the middle-
ware are missing. After those are transferred over, we'll be ready for
beta tests.
I'm very excited to get this out. Thanks for everyone's help and
patience these last few months. I hope you like it!!
2016-06-04 18:00:29 -05:00
|
|
|
}
|
|
|
|
s.listenerMu.Unlock()
|
|
|
|
|
|
|
|
// Closing this signals any TLS governor goroutines to exit
|
|
|
|
if s.tlsGovChan != nil {
|
|
|
|
close(s.tlsGovChan)
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// sanitizePath collapses any ./ ../ /// madness
|
|
|
|
// which helps prevent path traversal attacks.
|
|
|
|
// Note to middleware: use URL.RawPath If you need
|
|
|
|
// the "original" URL.Path value.
|
|
|
|
func sanitizePath(r *http.Request) {
|
|
|
|
if r.URL.Path == "/" {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
cleanedPath := path.Clean(r.URL.Path)
|
|
|
|
if cleanedPath == "." {
|
|
|
|
r.URL.Path = "/"
|
|
|
|
} else {
|
|
|
|
if !strings.HasPrefix(cleanedPath, "/") {
|
|
|
|
cleanedPath = "/" + cleanedPath
|
|
|
|
}
|
|
|
|
if strings.HasSuffix(r.URL.Path, "/") && !strings.HasSuffix(cleanedPath, "/") {
|
|
|
|
cleanedPath = cleanedPath + "/"
|
|
|
|
}
|
|
|
|
r.URL.Path = cleanedPath
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// OnStartupComplete lists the sites served by this server
|
|
|
|
// and any relevant information, assuming caddy.Quiet == false.
|
|
|
|
func (s *Server) OnStartupComplete() {
|
|
|
|
if caddy.Quiet {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
for _, site := range s.sites {
|
|
|
|
output := site.Addr.String()
|
2016-06-04 23:48:27 -05:00
|
|
|
if caddy.IsLoopback(s.Address()) && !caddy.IsLoopback(site.Addr.Host) {
|
Rewrote Caddy from the ground up; initial commit of 0.9 branch
These changes span work from the last ~4 months in an effort to make
Caddy more extensible, reduce the coupling between its components, and
lay a more robust foundation of code going forward into 1.0. A bunch of
new features have been added, too, with even higher future potential.
The most significant design change is an overall inversion of
dependencies. Instead of the caddy package knowing about the server
and the notion of middleware and config, the caddy package exposes an
interface that other components plug into. This does introduce more
indirection when reading the code, but every piece is very modular and
pluggable. Even the HTTP server is pluggable.
The caddy package has been moved to the top level, and main has been
pushed into a subfolder called caddy. The actual logic of the main
file has been pushed even further into caddy/caddymain/run.go so that
custom builds of Caddy can be 'go get'able.
The HTTPS logic was surgically separated into two parts to divide the
TLS-specific code and the HTTPS-specific code. The caddytls package can
now be used by any type of server that needs TLS, not just HTTP. I also
added the ability to customize nearly every aspect of TLS at the site
level rather than all sites sharing the same TLS configuration. Not all
of this flexibility is exposed in the Caddyfile yet, but it may be in
the future. Caddy can also generate self-signed certificates in memory
for the convenience of a developer working on localhost who wants HTTPS.
And Caddy now supports the DNS challenge, assuming at least one DNS
provider is plugged in.
Dozens, if not hundreds, of other minor changes swept through the code
base as I literally started from an empty main function, copying over
functions or files as needed, then adjusting them to fit in the new
design. Most tests have been restored and adapted to the new API,
but more work is needed there.
A lot of what was "impossible" before is now possible, or can be made
possible with minimal disruption of the code. For example, it's fairly
easy to make plugins hook into another part of the code via callbacks.
Plugins can do more than just be directives; we now have plugins that
customize how the Caddyfile is loaded (useful when you need to get your
configuration from a remote store).
Site addresses no longer need be just a host and port. They can have a
path, allowing you to scope a configuration to a specific path. There is
no inheretance, however; each site configuration is distinct.
Thanks to amazing work by Lucas Clemente, this commit adds experimental
QUIC support. Turn it on using the -quic flag; your browser may have
to be configured to enable it.
Almost everything is here, but you will notice that most of the middle-
ware are missing. After those are transferred over, we'll be ready for
beta tests.
I'm very excited to get this out. Thanks for everyone's help and
patience these last few months. I hope you like it!!
2016-06-04 18:00:29 -05:00
|
|
|
output += " (only accessible on this machine)"
|
|
|
|
}
|
|
|
|
fmt.Println(output)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// tcpKeepAliveListener sets TCP keep-alive timeouts on accepted
|
|
|
|
// connections. It's used by ListenAndServe and ListenAndServeTLS so
|
|
|
|
// dead TCP connections (e.g. closing laptop mid-download) eventually
|
|
|
|
// go away.
|
|
|
|
//
|
|
|
|
// Borrowed from the Go standard library.
|
|
|
|
type tcpKeepAliveListener struct {
|
|
|
|
*net.TCPListener
|
|
|
|
}
|
|
|
|
|
|
|
|
// Accept accepts the connection with a keep-alive enabled.
|
|
|
|
func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
|
|
|
|
tc, err := ln.AcceptTCP()
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
tc.SetKeepAlive(true)
|
|
|
|
tc.SetKeepAlivePeriod(3 * time.Minute)
|
|
|
|
return tc, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// File implements caddy.Listener; it returns the underlying file of the listener.
|
|
|
|
func (ln tcpKeepAliveListener) File() (*os.File, error) {
|
|
|
|
return ln.TCPListener.File()
|
|
|
|
}
|
|
|
|
|
|
|
|
// DefaultErrorFunc responds to an HTTP request with a simple description
|
|
|
|
// of the specified HTTP status code.
|
|
|
|
func DefaultErrorFunc(w http.ResponseWriter, r *http.Request, status int) {
|
2016-06-04 23:48:27 -05:00
|
|
|
WriteTextResponse(w, status, fmt.Sprintf("%d %s\n", status, http.StatusText(status)))
|
Rewrote Caddy from the ground up; initial commit of 0.9 branch
These changes span work from the last ~4 months in an effort to make
Caddy more extensible, reduce the coupling between its components, and
lay a more robust foundation of code going forward into 1.0. A bunch of
new features have been added, too, with even higher future potential.
The most significant design change is an overall inversion of
dependencies. Instead of the caddy package knowing about the server
and the notion of middleware and config, the caddy package exposes an
interface that other components plug into. This does introduce more
indirection when reading the code, but every piece is very modular and
pluggable. Even the HTTP server is pluggable.
The caddy package has been moved to the top level, and main has been
pushed into a subfolder called caddy. The actual logic of the main
file has been pushed even further into caddy/caddymain/run.go so that
custom builds of Caddy can be 'go get'able.
The HTTPS logic was surgically separated into two parts to divide the
TLS-specific code and the HTTPS-specific code. The caddytls package can
now be used by any type of server that needs TLS, not just HTTP. I also
added the ability to customize nearly every aspect of TLS at the site
level rather than all sites sharing the same TLS configuration. Not all
of this flexibility is exposed in the Caddyfile yet, but it may be in
the future. Caddy can also generate self-signed certificates in memory
for the convenience of a developer working on localhost who wants HTTPS.
And Caddy now supports the DNS challenge, assuming at least one DNS
provider is plugged in.
Dozens, if not hundreds, of other minor changes swept through the code
base as I literally started from an empty main function, copying over
functions or files as needed, then adjusting them to fit in the new
design. Most tests have been restored and adapted to the new API,
but more work is needed there.
A lot of what was "impossible" before is now possible, or can be made
possible with minimal disruption of the code. For example, it's fairly
easy to make plugins hook into another part of the code via callbacks.
Plugins can do more than just be directives; we now have plugins that
customize how the Caddyfile is loaded (useful when you need to get your
configuration from a remote store).
Site addresses no longer need be just a host and port. They can have a
path, allowing you to scope a configuration to a specific path. There is
no inheretance, however; each site configuration is distinct.
Thanks to amazing work by Lucas Clemente, this commit adds experimental
QUIC support. Turn it on using the -quic flag; your browser may have
to be configured to enable it.
Almost everything is here, but you will notice that most of the middle-
ware are missing. After those are transferred over, we'll be ready for
beta tests.
I'm very excited to get this out. Thanks for everyone's help and
patience these last few months. I hope you like it!!
2016-06-04 18:00:29 -05:00
|
|
|
}
|
|
|
|
|
2016-06-04 23:48:27 -05:00
|
|
|
// WriteTextResponse writes body with code status to w. The body will
|
Rewrote Caddy from the ground up; initial commit of 0.9 branch
These changes span work from the last ~4 months in an effort to make
Caddy more extensible, reduce the coupling between its components, and
lay a more robust foundation of code going forward into 1.0. A bunch of
new features have been added, too, with even higher future potential.
The most significant design change is an overall inversion of
dependencies. Instead of the caddy package knowing about the server
and the notion of middleware and config, the caddy package exposes an
interface that other components plug into. This does introduce more
indirection when reading the code, but every piece is very modular and
pluggable. Even the HTTP server is pluggable.
The caddy package has been moved to the top level, and main has been
pushed into a subfolder called caddy. The actual logic of the main
file has been pushed even further into caddy/caddymain/run.go so that
custom builds of Caddy can be 'go get'able.
The HTTPS logic was surgically separated into two parts to divide the
TLS-specific code and the HTTPS-specific code. The caddytls package can
now be used by any type of server that needs TLS, not just HTTP. I also
added the ability to customize nearly every aspect of TLS at the site
level rather than all sites sharing the same TLS configuration. Not all
of this flexibility is exposed in the Caddyfile yet, but it may be in
the future. Caddy can also generate self-signed certificates in memory
for the convenience of a developer working on localhost who wants HTTPS.
And Caddy now supports the DNS challenge, assuming at least one DNS
provider is plugged in.
Dozens, if not hundreds, of other minor changes swept through the code
base as I literally started from an empty main function, copying over
functions or files as needed, then adjusting them to fit in the new
design. Most tests have been restored and adapted to the new API,
but more work is needed there.
A lot of what was "impossible" before is now possible, or can be made
possible with minimal disruption of the code. For example, it's fairly
easy to make plugins hook into another part of the code via callbacks.
Plugins can do more than just be directives; we now have plugins that
customize how the Caddyfile is loaded (useful when you need to get your
configuration from a remote store).
Site addresses no longer need be just a host and port. They can have a
path, allowing you to scope a configuration to a specific path. There is
no inheretance, however; each site configuration is distinct.
Thanks to amazing work by Lucas Clemente, this commit adds experimental
QUIC support. Turn it on using the -quic flag; your browser may have
to be configured to enable it.
Almost everything is here, but you will notice that most of the middle-
ware are missing. After those are transferred over, we'll be ready for
beta tests.
I'm very excited to get this out. Thanks for everyone's help and
patience these last few months. I hope you like it!!
2016-06-04 18:00:29 -05:00
|
|
|
// be interpreted as plain text.
|
2016-06-04 23:48:27 -05:00
|
|
|
func WriteTextResponse(w http.ResponseWriter, status int, body string) {
|
Rewrote Caddy from the ground up; initial commit of 0.9 branch
These changes span work from the last ~4 months in an effort to make
Caddy more extensible, reduce the coupling between its components, and
lay a more robust foundation of code going forward into 1.0. A bunch of
new features have been added, too, with even higher future potential.
The most significant design change is an overall inversion of
dependencies. Instead of the caddy package knowing about the server
and the notion of middleware and config, the caddy package exposes an
interface that other components plug into. This does introduce more
indirection when reading the code, but every piece is very modular and
pluggable. Even the HTTP server is pluggable.
The caddy package has been moved to the top level, and main has been
pushed into a subfolder called caddy. The actual logic of the main
file has been pushed even further into caddy/caddymain/run.go so that
custom builds of Caddy can be 'go get'able.
The HTTPS logic was surgically separated into two parts to divide the
TLS-specific code and the HTTPS-specific code. The caddytls package can
now be used by any type of server that needs TLS, not just HTTP. I also
added the ability to customize nearly every aspect of TLS at the site
level rather than all sites sharing the same TLS configuration. Not all
of this flexibility is exposed in the Caddyfile yet, but it may be in
the future. Caddy can also generate self-signed certificates in memory
for the convenience of a developer working on localhost who wants HTTPS.
And Caddy now supports the DNS challenge, assuming at least one DNS
provider is plugged in.
Dozens, if not hundreds, of other minor changes swept through the code
base as I literally started from an empty main function, copying over
functions or files as needed, then adjusting them to fit in the new
design. Most tests have been restored and adapted to the new API,
but more work is needed there.
A lot of what was "impossible" before is now possible, or can be made
possible with minimal disruption of the code. For example, it's fairly
easy to make plugins hook into another part of the code via callbacks.
Plugins can do more than just be directives; we now have plugins that
customize how the Caddyfile is loaded (useful when you need to get your
configuration from a remote store).
Site addresses no longer need be just a host and port. They can have a
path, allowing you to scope a configuration to a specific path. There is
no inheretance, however; each site configuration is distinct.
Thanks to amazing work by Lucas Clemente, this commit adds experimental
QUIC support. Turn it on using the -quic flag; your browser may have
to be configured to enable it.
Almost everything is here, but you will notice that most of the middle-
ware are missing. After those are transferred over, we'll be ready for
beta tests.
I'm very excited to get this out. Thanks for everyone's help and
patience these last few months. I hope you like it!!
2016-06-04 18:00:29 -05:00
|
|
|
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
|
|
|
w.Header().Set("X-Content-Type-Options", "nosniff")
|
|
|
|
w.WriteHeader(status)
|
|
|
|
w.Write([]byte(body))
|
|
|
|
}
|