mirror of
https://github.com/coredns/coredns.git
synced 2025-11-26 21:54:03 -05:00
Remove the word middleware (#1067)
* Rename middleware to plugin first pass; mostly used 'sed', few spots where I manually changed text. This still builds a coredns binary. * fmt error * Rename AddMiddleware to AddPlugin * Readd AddMiddleware to remain backwards compat
This commit is contained in:
22
plugin/errors/README.md
Normal file
22
plugin/errors/README.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# errors
|
||||
|
||||
*errors* enables error logging.
|
||||
|
||||
Any errors encountered during the query processing will be printed to standard output.
|
||||
|
||||
## Syntax
|
||||
|
||||
~~~
|
||||
errors
|
||||
~~~
|
||||
|
||||
## Examples
|
||||
|
||||
Use the *whoami* to respond to queries and Log errors to standard output.
|
||||
|
||||
~~~ corefile
|
||||
. {
|
||||
whoami
|
||||
errors
|
||||
}
|
||||
~~~
|
||||
79
plugin/errors/errors.go
Normal file
79
plugin/errors/errors.go
Normal file
@@ -0,0 +1,79 @@
|
||||
// Package errors implements an HTTP error handling plugin.
|
||||
package errors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/coredns/coredns/plugin"
|
||||
"github.com/coredns/coredns/request"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// errorHandler handles DNS errors (and errors from other plugin).
|
||||
type errorHandler struct {
|
||||
Next plugin.Handler
|
||||
LogFile string
|
||||
Log *log.Logger
|
||||
}
|
||||
|
||||
// ServeDNS implements the plugin.Handler interface.
|
||||
func (h errorHandler) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
|
||||
defer h.recovery(ctx, w, r)
|
||||
|
||||
rcode, err := plugin.NextOrFailure(h.Name(), h.Next, ctx, w, r)
|
||||
|
||||
if err != nil {
|
||||
state := request.Request{W: w, Req: r}
|
||||
errMsg := fmt.Sprintf("%s [ERROR %d %s %s] %v", time.Now().Format(timeFormat), rcode, state.Name(), state.Type(), err)
|
||||
|
||||
h.Log.Println(errMsg)
|
||||
}
|
||||
|
||||
return rcode, err
|
||||
}
|
||||
|
||||
func (h errorHandler) Name() string { return "errors" }
|
||||
|
||||
func (h errorHandler) recovery(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) {
|
||||
rec := recover()
|
||||
if rec == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Obtain source of panic
|
||||
// From: https://gist.github.com/swdunlop/9629168
|
||||
var name, file string // function name, file name
|
||||
var line int
|
||||
var pc [16]uintptr
|
||||
n := runtime.Callers(3, pc[:])
|
||||
for _, pc := range pc[:n] {
|
||||
fn := runtime.FuncForPC(pc)
|
||||
if fn == nil {
|
||||
continue
|
||||
}
|
||||
file, line = fn.FileLine(pc)
|
||||
name = fn.Name()
|
||||
if !strings.HasPrefix(name, "runtime.") {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Trim file path
|
||||
delim := "/coredns/"
|
||||
pkgPathPos := strings.Index(file, delim)
|
||||
if pkgPathPos > -1 && len(file) > pkgPathPos+len(delim) {
|
||||
file = file[pkgPathPos+len(delim):]
|
||||
}
|
||||
|
||||
panicMsg := fmt.Sprintf("%s [PANIC %s %s] %s:%d - %v", time.Now().Format(timeFormat), r.Question[0].Name, dns.Type(r.Question[0].Qtype), file, line, rec)
|
||||
// Currently we don't use the function name, since file:line is more conventional
|
||||
h.Log.Printf(panicMsg)
|
||||
}
|
||||
|
||||
const timeFormat = "02/Jan/2006:15:04:05 -0700"
|
||||
73
plugin/errors/errors_test.go
Normal file
73
plugin/errors/errors_test.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package errors
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/coredns/coredns/plugin"
|
||||
"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
|
||||
"github.com/coredns/coredns/plugin/test"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func TestErrors(t *testing.T) {
|
||||
buf := bytes.Buffer{}
|
||||
em := errorHandler{Log: log.New(&buf, "", 0)}
|
||||
|
||||
testErr := errors.New("test error")
|
||||
tests := []struct {
|
||||
next plugin.Handler
|
||||
expectedCode int
|
||||
expectedLog string
|
||||
expectedErr error
|
||||
}{
|
||||
{
|
||||
next: genErrorHandler(dns.RcodeSuccess, nil),
|
||||
expectedCode: dns.RcodeSuccess,
|
||||
expectedLog: "",
|
||||
expectedErr: nil,
|
||||
},
|
||||
{
|
||||
next: genErrorHandler(dns.RcodeNotAuth, testErr),
|
||||
expectedCode: dns.RcodeNotAuth,
|
||||
expectedLog: fmt.Sprintf("[ERROR %d %s] %v\n", dns.RcodeNotAuth, "example.org. A", testErr),
|
||||
expectedErr: testErr,
|
||||
},
|
||||
}
|
||||
|
||||
ctx := context.TODO()
|
||||
req := new(dns.Msg)
|
||||
req.SetQuestion("example.org.", dns.TypeA)
|
||||
|
||||
for i, tc := range tests {
|
||||
em.Next = tc.next
|
||||
buf.Reset()
|
||||
rec := dnsrecorder.New(&test.ResponseWriter{})
|
||||
code, err := em.ServeDNS(ctx, rec, req)
|
||||
|
||||
if err != tc.expectedErr {
|
||||
t.Errorf("Test %d: Expected error %v, but got %v",
|
||||
i, tc.expectedErr, err)
|
||||
}
|
||||
if code != tc.expectedCode {
|
||||
t.Errorf("Test %d: Expected status code %d, but got %d",
|
||||
i, tc.expectedCode, code)
|
||||
}
|
||||
if log := buf.String(); !strings.Contains(log, tc.expectedLog) {
|
||||
t.Errorf("Test %d: Expected log %q, but got %q",
|
||||
i, tc.expectedLog, log)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func genErrorHandler(rcode int, err error) plugin.Handler {
|
||||
return plugin.HandlerFunc(func(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
|
||||
return rcode, err
|
||||
})
|
||||
}
|
||||
55
plugin/errors/setup.go
Normal file
55
plugin/errors/setup.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package errors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/coredns/coredns/core/dnsserver"
|
||||
"github.com/coredns/coredns/plugin"
|
||||
|
||||
"github.com/mholt/caddy"
|
||||
)
|
||||
|
||||
func init() {
|
||||
caddy.RegisterPlugin("errors", caddy.Plugin{
|
||||
ServerType: "dns",
|
||||
Action: setup,
|
||||
})
|
||||
}
|
||||
|
||||
func setup(c *caddy.Controller) error {
|
||||
handler, err := errorsParse(c)
|
||||
if err != nil {
|
||||
return plugin.Error("errors", err)
|
||||
}
|
||||
|
||||
handler.Log = log.New(os.Stdout, "", 0)
|
||||
|
||||
dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler {
|
||||
handler.Next = next
|
||||
return handler
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func errorsParse(c *caddy.Controller) (errorHandler, error) {
|
||||
handler := errorHandler{}
|
||||
|
||||
for c.Next() {
|
||||
args := c.RemainingArgs()
|
||||
switch len(args) {
|
||||
case 0:
|
||||
handler.LogFile = "stdout"
|
||||
case 1:
|
||||
if args[0] != "stdout" {
|
||||
return handler, fmt.Errorf("invalid log file: %s", args[0])
|
||||
}
|
||||
handler.LogFile = args[0]
|
||||
default:
|
||||
return handler, c.ArgErr()
|
||||
}
|
||||
}
|
||||
return handler, nil
|
||||
}
|
||||
45
plugin/errors/setup_test.go
Normal file
45
plugin/errors/setup_test.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package errors
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/mholt/caddy"
|
||||
)
|
||||
|
||||
func TestErrorsParse(t *testing.T) {
|
||||
tests := []struct {
|
||||
inputErrorsRules string
|
||||
shouldErr bool
|
||||
expectedErrorHandler errorHandler
|
||||
}{
|
||||
{`errors`, false, errorHandler{
|
||||
LogFile: "stdout",
|
||||
}},
|
||||
{`errors stdout`, false, errorHandler{
|
||||
LogFile: "stdout",
|
||||
}},
|
||||
{`errors errors.txt`, true, errorHandler{
|
||||
LogFile: "",
|
||||
}},
|
||||
{`errors visible`, true, errorHandler{
|
||||
LogFile: "",
|
||||
}},
|
||||
{`errors { log visible }`, true, errorHandler{
|
||||
LogFile: "stdout",
|
||||
}},
|
||||
}
|
||||
for i, test := range tests {
|
||||
c := caddy.NewTestController("dns", test.inputErrorsRules)
|
||||
actualErrorsRule, err := errorsParse(c)
|
||||
|
||||
if err == nil && test.shouldErr {
|
||||
t.Errorf("Test %d didn't error, but it should have", i)
|
||||
} else if err != nil && !test.shouldErr {
|
||||
t.Errorf("Test %d errored, but it shouldn't have; got '%v'", i, err)
|
||||
}
|
||||
if actualErrorsRule.LogFile != test.expectedErrorHandler.LogFile {
|
||||
t.Errorf("Test %d expected LogFile to be %s, but got %s",
|
||||
i, test.expectedErrorHandler.LogFile, actualErrorsRule.LogFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user