summaryrefslogtreecommitdiff
path: root/modules/caddyhttp/caddyhttp.go
diff options
context:
space:
mode:
authorMatthew Holt <mholt@users.noreply.github.com>2019-08-09 12:05:47 -0600
committerMatthew Holt <mholt@users.noreply.github.com>2019-08-09 12:05:47 -0600
commitab885f07b844fd60adb9d49ed7884f3cd2d939a7 (patch)
tree8827ad88cf3da8982154e2fda46f53274342785d /modules/caddyhttp/caddyhttp.go
parent4950ce485f7d931890fcfd2ee287b6df1b5db435 (diff)
Implement config adapters and beginning of Caddyfile adapter
Along with several other changes, such as renaming caddyhttp.ServerRoute to caddyhttp.Route, exporting some types that were not exported before, and tweaking the caddytls TLS values to be more consistent. Notably, we also now disable automatic cert management for names which already have a cert (manually) loaded into the cache. These names no longer need to be specified in the "skip_certificates" field of the automatic HTTPS config, because they will be skipped automatically.
Diffstat (limited to 'modules/caddyhttp/caddyhttp.go')
-rw-r--r--modules/caddyhttp/caddyhttp.go86
1 files changed, 84 insertions, 2 deletions
diff --git a/modules/caddyhttp/caddyhttp.go b/modules/caddyhttp/caddyhttp.go
index 467b40f..21c5b6d 100644
--- a/modules/caddyhttp/caddyhttp.go
+++ b/modules/caddyhttp/caddyhttp.go
@@ -15,9 +15,12 @@
package caddyhttp
import (
+ "bytes"
"context"
"crypto/tls"
+ "encoding/json"
"fmt"
+ "io"
"log"
weakrand "math/rand"
"net"
@@ -244,6 +247,14 @@ func (app *App) automaticHTTPS() error {
for d := range domainSet {
domains = append(domains, d)
if !srv.AutoHTTPS.Skipped(d, srv.AutoHTTPS.SkipCerts) {
+ // if a certificate for this name is already loaded,
+ // don't obtain another one for it, unless we are
+ // supposed to ignore loaded certificates
+ if !srv.AutoHTTPS.IgnoreLoadedCerts &&
+ len(tlsApp.CertificatesWithSAN(d)) > 0 {
+ log.Printf("[INFO][%s] Skipping automatic certificate management because a certificate with that SAN is already loaded", d)
+ continue
+ }
domainsForCerts = append(domainsForCerts, d)
}
}
@@ -319,7 +330,7 @@ func (app *App) automaticHTTPS() error {
}
redirTo += "{http.request.uri}"
- redirRoutes = append(redirRoutes, ServerRoute{
+ redirRoutes = append(redirRoutes, Route{
matcherSets: []MatcherSet{
{
MatchProtocol("http"),
@@ -328,7 +339,7 @@ func (app *App) automaticHTTPS() error {
},
handlers: []MiddlewareHandler{
StaticResponse{
- StatusCode: weakString(strconv.Itoa(http.StatusTemporaryRedirect)), // TODO: use permanent redirect instead
+ StatusCode: WeakString(strconv.Itoa(http.StatusTemporaryRedirect)), // TODO: use permanent redirect instead
Headers: http.Header{
"Location": []string{redirTo},
"Connection": []string{"close"},
@@ -431,6 +442,77 @@ type MiddlewareHandler interface {
// emptyHandler is used as a no-op handler.
var emptyHandler HandlerFunc = func(http.ResponseWriter, *http.Request) error { return nil }
+// WeakString is a type that unmarshals any JSON value
+// as a string literal, with the following exceptions:
+// 1) actual string values are decoded as strings, and
+// 2) null is decoded as empty string
+// and provides methods for getting the value as various
+// primitive types. However, using this type removes any
+// type safety as far as deserializing JSON is concerned.
+type WeakString string
+
+// UnmarshalJSON satisfies json.Unmarshaler according to
+// this type's documentation.
+func (ws *WeakString) UnmarshalJSON(b []byte) error {
+ if len(b) == 0 {
+ return io.EOF
+ }
+ if b[0] == byte('"') && b[len(b)-1] == byte('"') {
+ var s string
+ err := json.Unmarshal(b, &s)
+ if err != nil {
+ return err
+ }
+ *ws = WeakString(s)
+ return nil
+ }
+ if bytes.Equal(b, []byte("null")) {
+ return nil
+ }
+ *ws = WeakString(b)
+ return nil
+}
+
+// MarshalJSON marshals was a boolean if true or false,
+// a number if an integer, or a string otherwise.
+func (ws WeakString) MarshalJSON() ([]byte, error) {
+ if ws == "true" {
+ return []byte("true"), nil
+ }
+ if ws == "false" {
+ return []byte("false"), nil
+ }
+ if num, err := strconv.Atoi(string(ws)); err == nil {
+ return json.Marshal(num)
+ }
+ return json.Marshal(string(ws))
+}
+
+// Int returns ws as an integer. If ws is not an
+// integer, 0 is returned.
+func (ws WeakString) Int() int {
+ num, _ := strconv.Atoi(string(ws))
+ return num
+}
+
+// Float64 returns ws as a float64. If ws is not a
+// float value, the zero value is returned.
+func (ws WeakString) Float64() float64 {
+ num, _ := strconv.ParseFloat(string(ws), 64)
+ return num
+}
+
+// Bool returns ws as a boolean. If ws is not a
+// boolean, false is returned.
+func (ws WeakString) Bool() bool {
+ return string(ws) == "true"
+}
+
+// String returns ws as a string.
+func (ws WeakString) String() string {
+ return string(ws)
+}
+
const (
// DefaultHTTPPort is the default port for HTTP.
DefaultHTTPPort = 80