Skip to content

Commit

Permalink
Merge branch 'master' into feat/1xx
Browse files Browse the repository at this point in the history
  • Loading branch information
mholt authored Aug 4, 2022
2 parents aca8ba0 + 2642bd7 commit 222c801
Show file tree
Hide file tree
Showing 100 changed files with 1,800 additions and 1,201 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.go text eol=lf
10 changes: 5 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@ jobs:
fail-fast: false
matrix:
os: [ ubuntu-latest, macos-latest, windows-latest ]
go: [ '1.17', '1.18' ]
go: [ '1.18', '1.19' ]

include:
# Set the minimum Go patch version for the given Go minor
# Usable via ${{ matrix.GO_SEMVER }}
- go: '1.17'
GO_SEMVER: '~1.17.9'

- go: '1.18'
GO_SEMVER: '~1.18.1'
GO_SEMVER: '~1.18.4'

- go: '1.19'
GO_SEMVER: '~1.19.0'

# Set some variables per OS, usable via ${{ matrix.VAR }}
# CADDY_BIN_PATH: the path to the compiled Caddy binary, for artifact publishing
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/cross-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ jobs:
fail-fast: false
matrix:
goos: ['android', 'linux', 'solaris', 'illumos', 'dragonfly', 'freebsd', 'openbsd', 'plan9', 'windows', 'darwin', 'netbsd']
go: [ '1.18' ]
go: [ '1.19' ]

include:
# Set the minimum Go patch version for the given Go minor
# Usable via ${{ matrix.GO_SEMVER }}
- go: '1.18'
GO_SEMVER: '~1.18.1'
- go: '1.19'
GO_SEMVER: '~1.19.0'

runs-on: ubuntu-latest
continue-on-error: true
Expand Down
9 changes: 6 additions & 3 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,20 @@ jobs:
# From https://github.com/golangci/golangci-lint-action
golangci:
name: lint
runs-on: ubuntu-latest
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: '~1.17.9'
go-version: '~1.18.4'
check-latest: true

- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
version: v1.44
version: v1.47
# Optional: show only new issues if it's a pull request. The default value is `false`.
# only-new-issues: true
6 changes: 3 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ jobs:
strategy:
matrix:
os: [ ubuntu-latest ]
go: [ '1.18' ]
go: [ '1.19' ]

include:
# Set the minimum Go patch version for the given Go minor
# Usable via ${{ matrix.GO_SEMVER }}
- go: '1.18'
GO_SEMVER: '~1.18.1'
- go: '1.19'
GO_SEMVER: '~1.19.0'

runs-on: ${{ matrix.os }}

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ For other install options, see https://caddyserver.com/docs/install.

Requirements:

- [Go 1.17 or newer](https://golang.org/dl/)
- [Go 1.18 or newer](https://golang.org/dl/)

### For development

Expand Down
39 changes: 22 additions & 17 deletions admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"crypto/tls"
"crypto/x509"
"encoding/base64"
"encoding/hex"
"encoding/json"
"errors"
"expvar"
Expand Down Expand Up @@ -442,7 +441,7 @@ func manageIdentity(ctx Context, cfg *Config) error {
if err != nil {
return fmt.Errorf("loading identity issuer modules: %s", err)
}
for _, issVal := range val.([]interface{}) {
for _, issVal := range val.([]any) {
cfg.Admin.Identity.issuers = append(cfg.Admin.Identity.issuers, issVal.(certmagic.Issuer))
}
}
Expand Down Expand Up @@ -901,6 +900,12 @@ func (h adminHandler) originAllowed(origin *url.URL) bool {
// produce and verify ETags.
func etagHasher() hash.Hash32 { return fnv.New32a() }

// makeEtag returns an Etag header value (including quotes) for
// the given config path and hash of contents at that path.
func makeEtag(path string, hash hash.Hash) string {
return fmt.Sprintf(`"%s %x"`, path, hash.Sum(nil))
}

func handleConfig(w http.ResponseWriter, r *http.Request) error {
switch r.Method {
case http.MethodGet:
Expand All @@ -919,7 +924,7 @@ func handleConfig(w http.ResponseWriter, r *http.Request) error {

// we could consider setting up a sync.Pool for the summed
// hashes to reduce GC pressure.
w.Header().Set("ETag", r.URL.Path+" "+hex.EncodeToString(hash.Sum(nil)))
w.Header().Set("Etag", makeEtag(r.URL.Path, hash))

return nil

Expand Down Expand Up @@ -988,9 +993,9 @@ func handleConfigID(w http.ResponseWriter, r *http.Request) error {
id := parts[2]

// map the ID to the expanded path
currentCfgMu.RLock()
currentCtxMu.RLock()
expanded, ok := rawCfgIndex[id]
defer currentCfgMu.RUnlock()
defer currentCtxMu.RUnlock()
if !ok {
return APIError{
HTTPStatus: http.StatusNotFound,
Expand Down Expand Up @@ -1025,11 +1030,11 @@ func handleStop(w http.ResponseWriter, r *http.Request) error {
// the operation at path according to method, using body and out as
// needed. This is a low-level, unsynchronized function; most callers
// will want to use changeConfig or readConfig instead. This requires a
// read or write lock on currentCfgMu, depending on method (GET needs
// read or write lock on currentCtxMu, depending on method (GET needs
// only a read lock; all others need a write lock).
func unsyncedConfigAccess(method, path string, body []byte, out io.Writer) error {
var err error
var val interface{}
var val any

// if there is a request body, decode it into the
// variable that will be set in the config according
Expand Down Expand Up @@ -1066,16 +1071,16 @@ func unsyncedConfigAccess(method, path string, body []byte, out io.Writer) error
parts = parts[:len(parts)-1]
}

var ptr interface{} = rawCfg
var ptr any = rawCfg

traverseLoop:
for i, part := range parts {
switch v := ptr.(type) {
case map[string]interface{}:
case map[string]any:
// if the next part enters a slice, and the slice is our destination,
// handle it specially (because appending to the slice copies the slice
// header, which does not replace the original one like we want)
if arr, ok := v[part].([]interface{}); ok && i == len(parts)-2 {
if arr, ok := v[part].([]any); ok && i == len(parts)-2 {
var idx int
if method != http.MethodPost {
idxStr := parts[len(parts)-1]
Expand All @@ -1097,7 +1102,7 @@ traverseLoop:
}
case http.MethodPost:
if ellipses {
valArray, ok := val.([]interface{})
valArray, ok := val.([]any)
if !ok {
return fmt.Errorf("final element is not an array")
}
Expand Down Expand Up @@ -1132,9 +1137,9 @@ traverseLoop:
case http.MethodPost:
// if the part is an existing list, POST appends to
// it, otherwise it just sets or creates the value
if arr, ok := v[part].([]interface{}); ok {
if arr, ok := v[part].([]any); ok {
if ellipses {
valArray, ok := val.([]interface{})
valArray, ok := val.([]any)
if !ok {
return fmt.Errorf("final element is not an array")
}
Expand Down Expand Up @@ -1165,12 +1170,12 @@ traverseLoop:
// might not exist yet; that's OK but we need to make them as
// we go, while we still have a pointer from the level above
if v[part] == nil && method == http.MethodPut {
v[part] = make(map[string]interface{})
v[part] = make(map[string]any)
}
ptr = v[part]
}

case []interface{}:
case []any:
partInt, err := strconv.Atoi(part)
if err != nil {
return fmt.Errorf("[/%s] invalid array index '%s': %v",
Expand All @@ -1192,7 +1197,7 @@ traverseLoop:

// RemoveMetaFields removes meta fields like "@id" from a JSON message
// by using a simple regular expression. (An alternate way to do this
// would be to delete them from the raw, map[string]interface{}
// would be to delete them from the raw, map[string]any
// representation as they are indexed, then iterate the index we made
// and add them back after encoding as JSON, but this is simpler.)
func RemoveMetaFields(rawJSON []byte) []byte {
Expand Down Expand Up @@ -1324,7 +1329,7 @@ const (
)

var bufPool = sync.Pool{
New: func() interface{} {
New: func() any {
return new(bytes.Buffer)
},
}
Expand Down
10 changes: 5 additions & 5 deletions admin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
package caddy

import (
"encoding/hex"
"encoding/json"
"fmt"
"net/http"
"reflect"
"sync"
Expand Down Expand Up @@ -115,7 +115,7 @@ func TestUnsyncedConfigAccess(t *testing.T) {
}

// decode the expected config so we can do a convenient DeepEqual
var expectedDecoded interface{}
var expectedDecoded any
err = json.Unmarshal([]byte(tc.expect), &expectedDecoded)
if err != nil {
t.Fatalf("Test %d: Unmarshaling expected config: %v", i, err)
Expand Down Expand Up @@ -168,7 +168,7 @@ func TestETags(t *testing.T) {
const key = "/" + rawConfigKey + "/apps/foo"

// try update the config with the wrong etag
err := changeConfig(http.MethodPost, key, []byte(`{"strField": "abc", "intField": 1}}`), "/"+rawConfigKey+" not_an_etag", false)
err := changeConfig(http.MethodPost, key, []byte(`{"strField": "abc", "intField": 1}}`), fmt.Sprintf(`"/%s not_an_etag"`, rawConfigKey), false)
if apiErr, ok := err.(APIError); !ok || apiErr.HTTPStatus != http.StatusPreconditionFailed {
t.Fatalf("expected precondition failed; got %v", err)
}
Expand All @@ -180,13 +180,13 @@ func TestETags(t *testing.T) {
}

// do the same update with the correct key
err = changeConfig(http.MethodPost, key, []byte(`{"strField": "abc", "intField": 1}`), key+" "+hex.EncodeToString(hash.Sum(nil)), false)
err = changeConfig(http.MethodPost, key, []byte(`{"strField": "abc", "intField": 1}`), makeEtag(key, hash), false)
if err != nil {
t.Fatalf("expected update to work; got %v", err)
}

// now try another update. The hash should no longer match and we should get precondition failed
err = changeConfig(http.MethodPost, key, []byte(`{"strField": "abc", "intField": 2}`), key+" "+hex.EncodeToString(hash.Sum(nil)), false)
err = changeConfig(http.MethodPost, key, []byte(`{"strField": "abc", "intField": 2}`), makeEtag(key, hash), false)
if apiErr, ok := err.(APIError); !ok || apiErr.HTTPStatus != http.StatusPreconditionFailed {
t.Fatalf("expected precondition failed; got %v", err)
}
Expand Down
Loading

0 comments on commit 222c801

Please sign in to comment.