core: Implement FastAbs to avoid repeated os.Getwd calls (#6687)

* core: Implement FastAbs to avoid repeated os.Getwd calls

* Lint

* Rename files
This commit is contained in:
Francis Lavoie 2024-11-13 03:55:51 -05:00 committed by GitHub
parent 238f1108e6
commit 315715e90f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 90 additions and 16 deletions

View file

@ -423,7 +423,7 @@ func (p *parser) doImport(nesting int) error {
// make path relative to the file of the _token_ being processed rather // make path relative to the file of the _token_ being processed rather
// than current working directory (issue #867) and then use glob to get // than current working directory (issue #867) and then use glob to get
// list of matching filenames // list of matching filenames
absFile, err := filepath.Abs(p.Dispenser.File()) absFile, err := caddy.FastAbs(p.Dispenser.File())
if err != nil { if err != nil {
return p.Errf("Failed to get absolute path of file: %s: %v", p.Dispenser.File(), err) return p.Errf("Failed to get absolute path of file: %s: %v", p.Dispenser.File(), err)
} }
@ -622,7 +622,7 @@ func (p *parser) doSingleImport(importFile string) ([]Token, error) {
// Tack the file path onto these tokens so errors show the imported file's name // Tack the file path onto these tokens so errors show the imported file's name
// (we use full, absolute path to avoid bugs: issue #1892) // (we use full, absolute path to avoid bugs: issue #1892)
filename, err := filepath.Abs(importFile) filename, err := caddy.FastAbs(importFile)
if err != nil { if err != nil {
return nil, p.Errf("Failed to get absolute path of file: %s: %v", importFile, err) return nil, p.Errf("Failed to get absolute path of file: %s: %v", importFile, err)
} }

37
filepath.go Normal file
View file

@ -0,0 +1,37 @@
// Copyright 2015 Matthew Holt and The Caddy Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !windows
package caddy
import (
"os"
"path/filepath"
)
// FastAbs is an optimized version of filepath.Abs for Unix systems,
// since we don't expect the working directory to ever change once
// Caddy is running. Avoid the os.Getwd() syscall overhead.
func FastAbs(path string) (string, error) {
if filepath.IsAbs(path) {
return filepath.Clean(path), nil
}
if wderr != nil {
return "", wderr
}
return filepath.Join(wd, path), nil
}
var wd, wderr = os.Getwd()

25
filepath_windows.go Normal file
View file

@ -0,0 +1,25 @@
// Copyright 2015 Matthew Holt and The Caddy Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package caddy
import (
"path/filepath"
)
// FastAbs can't be optimized on Windows because the
// syscall.FullPath function takes an input.
func FastAbs(path string) (string, error) {
return filepath.Abs(path)
}

View file

@ -1,3 +1,17 @@
// Copyright 2015 Matthew Holt and The Caddy Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package caddy package caddy
import "io/fs" import "io/fs"

View file

@ -30,7 +30,7 @@ import (
"go.uber.org/zap" "go.uber.org/zap"
) )
func reuseUnixSocket(network, addr string) (any, error) { func reuseUnixSocket(_, _ string) (any, error) {
return nil, nil return nil, nil
} }

View file

@ -204,7 +204,7 @@ func (fsrv *FileServer) Provision(ctx caddy.Context) error {
// absolute paths before the server starts for very slight performance improvement // absolute paths before the server starts for very slight performance improvement
for i, h := range fsrv.Hide { for i, h := range fsrv.Hide {
if !strings.Contains(h, "{") && strings.Contains(h, separator) { if !strings.Contains(h, "{") && strings.Contains(h, separator) {
if abs, err := filepath.Abs(h); err == nil { if abs, err := caddy.FastAbs(h); err == nil {
fsrv.Hide[i] = abs fsrv.Hide[i] = abs
} }
} }
@ -636,7 +636,7 @@ func (fsrv *FileServer) transformHidePaths(repl *caddy.Replacer) []string {
for i := range fsrv.Hide { for i := range fsrv.Hide {
hide[i] = repl.ReplaceAll(fsrv.Hide[i], "") hide[i] = repl.ReplaceAll(fsrv.Hide[i], "")
if strings.Contains(hide[i], separator) { if strings.Contains(hide[i], separator) {
abs, err := filepath.Abs(hide[i]) abs, err := caddy.FastAbs(hide[i])
if err == nil { if err == nil {
hide[i] = abs hide[i] = abs
} }
@ -655,7 +655,7 @@ func fileHidden(filename string, hide []string) bool {
} }
// all path comparisons use the complete absolute path if possible // all path comparisons use the complete absolute path if possible
filenameAbs, err := filepath.Abs(filename) filenameAbs, err := caddy.FastAbs(filename)
if err == nil { if err == nil {
filename = filenameAbs filename = filenameAbs
} }

View file

@ -228,7 +228,7 @@ func (t Transport) buildEnv(r *http.Request) (envVars, error) {
ip = strings.Replace(ip, "]", "", 1) ip = strings.Replace(ip, "]", "", 1)
// make sure file root is absolute // make sure file root is absolute
root, err := filepath.Abs(repl.ReplaceAll(t.Root, ".")) root, err := caddy.FastAbs(repl.ReplaceAll(t.Root, "."))
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -549,7 +549,7 @@ func (h *Handler) proxyLoopIteration(r *http.Request, origReq *http.Request, w h
// ding the health status of the upstream (an error can still // ding the health status of the upstream (an error can still
// occur after the roundtrip if, for example, a response handler // occur after the roundtrip if, for example, a response handler
// after the roundtrip returns an error) // after the roundtrip returns an error)
if succ, ok := proxyErr.(roundtripSucceeded); ok { if succ, ok := proxyErr.(roundtripSucceededError); ok {
return true, succ.error return true, succ.error
} }
@ -953,10 +953,10 @@ func (h *Handler) reverseProxy(rw http.ResponseWriter, req *http.Request, origRe
res.Body.Close() res.Body.Close()
} }
// wrap any route error in roundtripSucceeded so caller knows that // wrap any route error in roundtripSucceededError so caller knows that
// the roundtrip was successful and to not retry // the roundtrip was successful and to not retry
if routeErr != nil { if routeErr != nil {
return roundtripSucceeded{routeErr} return roundtripSucceededError{routeErr}
} }
// we're done handling the response, and we don't want to // we're done handling the response, and we don't want to
@ -1433,9 +1433,9 @@ type TLSTransport interface {
EnableTLS(base *TLSConfig) error EnableTLS(base *TLSConfig) error
} }
// roundtripSucceeded is an error type that is returned if the // roundtripSucceededError is an error type that is returned if the
// roundtrip succeeded, but an error occurred after-the-fact. // roundtrip succeeded, but an error occurred after-the-fact.
type roundtripSucceeded struct{ error } type roundtripSucceededError struct{ error }
// bodyReadCloser is a reader that, upon closing, will return // bodyReadCloser is a reader that, upon closing, will return
// its buffer to the pool and close the underlying body reader. // its buffer to the pool and close the underlying body reader.

View file

@ -24,7 +24,6 @@ import (
"fmt" "fmt"
"io" "io"
"os" "os"
"path/filepath"
"strings" "strings"
"github.com/mholt/acmez/v2" "github.com/mholt/acmez/v2"
@ -358,7 +357,7 @@ func (p *ConnectionPolicy) buildStandardTLSConfig(ctx caddy.Context) error {
if err != nil { if err != nil {
return err return err
} }
filename, err = filepath.Abs(filename) filename, err = caddy.FastAbs(filename)
if err != nil { if err != nil {
return err return err
} }

View file

@ -20,7 +20,6 @@ import (
"io" "io"
"math" "math"
"os" "os"
"path/filepath"
"strconv" "strconv"
"github.com/dustin/go-humanize" "github.com/dustin/go-humanize"
@ -133,7 +132,7 @@ func (fw *FileWriter) Provision(ctx caddy.Context) error {
} }
func (fw FileWriter) String() string { func (fw FileWriter) String() string {
fpath, err := filepath.Abs(fw.Filename) fpath, err := caddy.FastAbs(fw.Filename)
if err == nil { if err == nil {
return fpath return fpath
} }