mirror of
				https://github.com/coredns/coredns.git
				synced 2025-11-03 18:53:13 -05:00 
			
		
		
		
	@@ -9,6 +9,7 @@ import (
 | 
				
			|||||||
	"github.com/miekg/coredns/middleware"
 | 
						"github.com/miekg/coredns/middleware"
 | 
				
			||||||
	caddylog "github.com/miekg/coredns/middleware/log"
 | 
						caddylog "github.com/miekg/coredns/middleware/log"
 | 
				
			||||||
	"github.com/miekg/coredns/server"
 | 
						"github.com/miekg/coredns/server"
 | 
				
			||||||
 | 
						"github.com/miekg/dns"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Log sets up the logging middleware.
 | 
					// Log sets up the logging middleware.
 | 
				
			||||||
@@ -88,7 +89,7 @@ func logParse(c *Controller) ([]caddylog.Rule, error) {
 | 
				
			|||||||
		if len(args) == 0 {
 | 
							if len(args) == 0 {
 | 
				
			||||||
			// Nothing specified; use defaults
 | 
								// Nothing specified; use defaults
 | 
				
			||||||
			rules = append(rules, caddylog.Rule{
 | 
								rules = append(rules, caddylog.Rule{
 | 
				
			||||||
				PathScope:  "/",
 | 
									NameScope:  ".",
 | 
				
			||||||
				OutputFile: caddylog.DefaultLogFilename,
 | 
									OutputFile: caddylog.DefaultLogFilename,
 | 
				
			||||||
				Format:     caddylog.DefaultLogFormat,
 | 
									Format:     caddylog.DefaultLogFormat,
 | 
				
			||||||
				Roller:     logRoller,
 | 
									Roller:     logRoller,
 | 
				
			||||||
@@ -96,13 +97,13 @@ func logParse(c *Controller) ([]caddylog.Rule, error) {
 | 
				
			|||||||
		} else if len(args) == 1 {
 | 
							} else if len(args) == 1 {
 | 
				
			||||||
			// Only an output file specified
 | 
								// Only an output file specified
 | 
				
			||||||
			rules = append(rules, caddylog.Rule{
 | 
								rules = append(rules, caddylog.Rule{
 | 
				
			||||||
				PathScope:  "/",
 | 
									NameScope:  ".",
 | 
				
			||||||
				OutputFile: args[0],
 | 
									OutputFile: args[0],
 | 
				
			||||||
				Format:     caddylog.DefaultLogFormat,
 | 
									Format:     caddylog.DefaultLogFormat,
 | 
				
			||||||
				Roller:     logRoller,
 | 
									Roller:     logRoller,
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			// Path scope, output file, and maybe a format specified
 | 
								// Name scope, output file, and maybe a format specified
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			format := caddylog.DefaultLogFormat
 | 
								format := caddylog.DefaultLogFormat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -118,7 +119,7 @@ func logParse(c *Controller) ([]caddylog.Rule, error) {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			rules = append(rules, caddylog.Rule{
 | 
								rules = append(rules, caddylog.Rule{
 | 
				
			||||||
				PathScope:  args[0],
 | 
									NameScope:  dns.Fqdn(args[0]),
 | 
				
			||||||
				OutputFile: args[1],
 | 
									OutputFile: args[1],
 | 
				
			||||||
				Format:     format,
 | 
									Format:     format,
 | 
				
			||||||
				Roller:     logRoller,
 | 
									Roller:     logRoller,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										81
									
								
								directives.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								directives.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,81 @@
 | 
				
			|||||||
 | 
					# Log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					log enables request logging. The request log is also known from some vernaculars as an access log.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Syntax
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					~~~
 | 
				
			||||||
 | 
					log
 | 
				
			||||||
 | 
					~~~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* With no arguments, an query log is written to query.log in the common log format for all requests
 | 
				
			||||||
 | 
					    (base name = .).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					~~~
 | 
				
			||||||
 | 
					log file
 | 
				
			||||||
 | 
					~~~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* file is the log file to create (or append to). The base path is assumed to be . .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					~~~
 | 
				
			||||||
 | 
					log name file [format]
 | 
				
			||||||
 | 
					~~~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `name` is the base name to match in order to be logged
 | 
				
			||||||
 | 
					* `file` is the log file to create (or append to)
 | 
				
			||||||
 | 
					* `format` is the log format to use (default is Common Log Format)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Log File
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The log file can be any filename. It could also be stdout or stderr to write the log to the console,
 | 
				
			||||||
 | 
					or syslog to write to the system log (except on Windows). If the log file does not exist beforehand,
 | 
				
			||||||
 | 
					CoreDNS will create it before appending to it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Log Format
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can specify a custom log format with any placeholder values. Log supports both request and response placeholders.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Log Rotation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you enable log rotation, log files will be automatically maintained when they get large or old.
 | 
				
			||||||
 | 
					You can use rotation by opening a block on your first line, which can be any of the variations
 | 
				
			||||||
 | 
					described above:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					~~~
 | 
				
			||||||
 | 
					log ... {
 | 
				
			||||||
 | 
					    rotate {
 | 
				
			||||||
 | 
					    size maxsize
 | 
				
			||||||
 | 
					    age  maxage
 | 
				
			||||||
 | 
					    keep maxkeep
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					~~~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `maxsize` is the maximum size of a log file in megabytes (MB) before it gets rotated. Default is 100 MB.
 | 
				
			||||||
 | 
					* `maxage` is the maximum age of a rotated log file in days, after which it will be deleted. Default is to never delete old files because of age.
 | 
				
			||||||
 | 
					* `maxkeep` is the maximum number of rotated log files to keep. Default is to retain all old log files.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Examples
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Log all requests to a file:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					~~~
 | 
				
			||||||
 | 
					log /var/log/query.log
 | 
				
			||||||
 | 
					~~~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Custom log format:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					~~~
 | 
				
			||||||
 | 
					log . ../query.log "{proto} Request: {name} {type} {>id}"
 | 
				
			||||||
 | 
					~~~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					With rotation:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					~~~
 | 
				
			||||||
 | 
					log query.log {
 | 
				
			||||||
 | 
					    rotate {
 | 
				
			||||||
 | 
					        100 # Rotate after 100 MB
 | 
				
			||||||
 | 
					        age  14  # Keep log files for 14 days
 | 
				
			||||||
 | 
					        keep 10  # Keep at most 10 log files
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -18,36 +18,36 @@ type Logger struct {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (l Logger) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
 | 
					func (l Logger) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
 | 
				
			||||||
 | 
						state := middleware.State{W: w, Req: r}
 | 
				
			||||||
	for _, rule := range l.Rules {
 | 
						for _, rule := range l.Rules {
 | 
				
			||||||
		/*
 | 
							if middleware.Name(state.Name()).Matches(rule.NameScope) {
 | 
				
			||||||
			if middleware.Path(r.URL.Path).Matches(rule.PathScope) {
 | 
								responseRecorder := middleware.NewResponseRecorder(w)
 | 
				
			||||||
				responseRecorder := middleware.NewResponseRecorder(w)
 | 
								rcode, err := l.Next.ServeDNS(ctx, responseRecorder, r)
 | 
				
			||||||
				status, err := l.Next.ServeHTTP(responseRecorder, r)
 | 
								if rcode > 0 {
 | 
				
			||||||
				if status >= 400 {
 | 
									// There was an error up the chain, but no response has been written yet.
 | 
				
			||||||
					// There was an error up the chain, but no response has been written yet.
 | 
									// The error must be handled here so the log entry will record the response size.
 | 
				
			||||||
					// The error must be handled here so the log entry will record the response size.
 | 
									if l.ErrorFunc != nil {
 | 
				
			||||||
					if l.ErrorFunc != nil {
 | 
										l.ErrorFunc(responseRecorder, r, rcode)
 | 
				
			||||||
						l.ErrorFunc(responseRecorder, r, status)
 | 
									} else {
 | 
				
			||||||
					} else {
 | 
										// Default failover error handler
 | 
				
			||||||
						// Default failover error handler
 | 
										answer := new(dns.Msg)
 | 
				
			||||||
						responseRecorder.WriteHeader(status)
 | 
										answer.SetRcode(r, rcode)
 | 
				
			||||||
						fmt.Fprintf(responseRecorder, "%d %s", status, http.StatusText(status))
 | 
										w.WriteMsg(answer)
 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					status = 0
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				rep := middleware.NewReplacer(r, responseRecorder, CommonLogEmptyValue)
 | 
									rcode = 0
 | 
				
			||||||
				rule.Log.Println(rep.Replace(rule.Format))
 | 
					 | 
				
			||||||
				return status, err
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		*/
 | 
								rep := middleware.NewReplacer(r, responseRecorder, CommonLogEmptyValue)
 | 
				
			||||||
		rule = rule
 | 
								rule.Log.Println(rep.Replace(rule.Format))
 | 
				
			||||||
 | 
								return rcode, err
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return l.Next.ServeDNS(ctx, w, r)
 | 
						return l.Next.ServeDNS(ctx, w, r)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Rule configures the logging middleware.
 | 
					// Rule configures the logging middleware.
 | 
				
			||||||
type Rule struct {
 | 
					type Rule struct {
 | 
				
			||||||
	PathScope  string
 | 
						NameScope  string
 | 
				
			||||||
	OutputFile string
 | 
						OutputFile string
 | 
				
			||||||
	Format     string
 | 
						Format     string
 | 
				
			||||||
	Log        *log.Logger
 | 
						Log        *log.Logger
 | 
				
			||||||
@@ -56,13 +56,13 @@ type Rule struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	// DefaultLogFilename is the default log filename.
 | 
						// DefaultLogFilename is the default log filename.
 | 
				
			||||||
	DefaultLogFilename = "access.log"
 | 
						DefaultLogFilename = "query.log"
 | 
				
			||||||
	// CommonLogFormat is the common log format.
 | 
						// CommonLogFormat is the common log format.
 | 
				
			||||||
	CommonLogFormat = `{remote} ` + CommonLogEmptyValue + ` [{when}] "{type} {name} {proto}" {rcode} {size}`
 | 
						CommonLogFormat = `{remote} ` + CommonLogEmptyValue + ` [{when}] "{type} {name} {proto}" {rcode} {size}`
 | 
				
			||||||
	// CommonLogEmptyValue is the common empty log value.
 | 
						// CommonLogEmptyValue is the common empty log value.
 | 
				
			||||||
	CommonLogEmptyValue = "-"
 | 
						CommonLogEmptyValue = "-"
 | 
				
			||||||
	// CombinedLogFormat is the combined log format.
 | 
						// CombinedLogFormat is the combined log format.
 | 
				
			||||||
	CombinedLogFormat = CommonLogFormat + ` "{>Referer}" "{>User-Agent}"` // Something here as well
 | 
						CombinedLogFormat = CommonLogFormat + ` "{>opcode}"`
 | 
				
			||||||
	// DefaultLogFormat is the default log format.
 | 
						// DefaultLogFormat is the default log format.
 | 
				
			||||||
	DefaultLogFormat = CommonLogFormat
 | 
						DefaultLogFormat = CommonLogFormat
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,17 +1,27 @@
 | 
				
			|||||||
package log
 | 
					package log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/miekg/coredns/middleware"
 | 
				
			||||||
 | 
						"github.com/miekg/dns"
 | 
				
			||||||
 | 
						"golang.org/x/net/context"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type erroringMiddleware struct{}
 | 
					type erroringMiddleware struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (erroringMiddleware) ServeDNS(w dns.ResponseWriter, r *dns.Msg) (int, error) {
 | 
					func (erroringMiddleware) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
 | 
				
			||||||
	return http.StatusNotFound, nil
 | 
						return dns.RcodeServerFailure, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestLoggedStatus(t *testing.T) {
 | 
					func TestLoggedStatus(t *testing.T) {
 | 
				
			||||||
	var f bytes.Buffer
 | 
						var f bytes.Buffer
 | 
				
			||||||
	var next erroringMiddleware
 | 
						var next erroringMiddleware
 | 
				
			||||||
	rule := Rule{
 | 
						rule := Rule{
 | 
				
			||||||
		PathScope: "/",
 | 
							NameScope: ".",
 | 
				
			||||||
		Format:    DefaultLogFormat,
 | 
							Format:    DefaultLogFormat,
 | 
				
			||||||
		Log:       log.New(&f, "", 0),
 | 
							Log:       log.New(&f, "", 0),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -21,21 +31,19 @@ func TestLoggedStatus(t *testing.T) {
 | 
				
			|||||||
		Next:  next,
 | 
							Next:  next,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	r, err := http.NewRequest("GET", "/", nil)
 | 
						ctx := context.TODO()
 | 
				
			||||||
	if err != nil {
 | 
						r := new(dns.Msg)
 | 
				
			||||||
		t.Fatal(err)
 | 
						r.SetQuestion("example.org.", dns.TypeA)
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rec := httptest.NewRecorder()
 | 
						rec := middleware.NewResponseRecorder(&middleware.TestResponseWriter{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	status, err := logger.ServeHTTP(rec, r)
 | 
						rcode, _ := logger.ServeDNS(ctx, rec, r)
 | 
				
			||||||
	if status != 0 {
 | 
						if rcode != 0 {
 | 
				
			||||||
		t.Error("Expected status to be 0 - was", status)
 | 
							t.Error("Expected rcode to be 0 - was", rcode)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	logged := f.String()
 | 
						logged := f.String()
 | 
				
			||||||
	if !strings.Contains(logged, "404 13") {
 | 
						if !strings.Contains(logged, "A example.org. udp") {
 | 
				
			||||||
		t.Error("Expected 404 to be logged. Logged string -", logged)
 | 
							t.Error("Expected it to be logged. Logged string -", logged)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										15
									
								
								middleware/name.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								middleware/name.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					package middleware
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Name represents a domain name.
 | 
				
			||||||
 | 
					type Name string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Matches checks to see if other matches n.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Name matching will probably not always be a direct
 | 
				
			||||||
 | 
					// comparison; this method assures that names can be
 | 
				
			||||||
 | 
					// easily and consistently matched.
 | 
				
			||||||
 | 
					func (n Name) Matches(other string) bool {
 | 
				
			||||||
 | 
						return strings.HasSuffix(string(n), other)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,18 +0,0 @@
 | 
				
			|||||||
package middleware
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import "strings"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// TODO(miek): matches for names.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Path represents a URI path, maybe with pattern characters.
 | 
					 | 
				
			||||||
type Path string
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Matches checks to see if other matches p.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Path matching will probably not always be a direct
 | 
					 | 
				
			||||||
// comparison; this method assures that paths can be
 | 
					 | 
				
			||||||
// easily and consistently matched.
 | 
					 | 
				
			||||||
func (p Path) Matches(other string) bool {
 | 
					 | 
				
			||||||
	return strings.HasPrefix(string(p), other)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -4,12 +4,10 @@ import (
 | 
				
			|||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"io/ioutil"
 | 
						"io/ioutil"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"path"
 | 
					 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/miekg/coredns/core/parse"
 | 
						"github.com/miekg/coredns/core/parse"
 | 
				
			||||||
	"github.com/miekg/coredns/middleware"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
@@ -226,10 +224,13 @@ func (u *staticUpstream) Select() *UpstreamHost {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (u *staticUpstream) IsAllowedPath(requestPath string) bool {
 | 
					func (u *staticUpstream) IsAllowedPath(requestPath string) bool {
 | 
				
			||||||
	for _, ignoredSubPath := range u.IgnoredSubPaths {
 | 
						/*
 | 
				
			||||||
		if middleware.Path(path.Clean(requestPath)).Matches(path.Join(u.From(), ignoredSubPath)) {
 | 
							TODO(miek): fix to use Name
 | 
				
			||||||
			return false
 | 
							for _, ignoredSubPath := range u.IgnoredSubPaths {
 | 
				
			||||||
 | 
								if middleware.Path(path.Clean(requestPath)).Matches(path.Join(u.From(), ignoredSubPath)) {
 | 
				
			||||||
 | 
									return false
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						*/
 | 
				
			||||||
	return true
 | 
						return true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
package middleware
 | 
					package middleware
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"net"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/miekg/dns"
 | 
						"github.com/miekg/dns"
 | 
				
			||||||
@@ -68,3 +69,24 @@ func (r *ResponseRecorder) Hijack() {
 | 
				
			|||||||
	r.ResponseWriter.Hijack()
 | 
						r.ResponseWriter.Hijack()
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type TestResponseWriter struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (t *TestResponseWriter) LocalAddr() net.Addr {
 | 
				
			||||||
 | 
						ip := net.ParseIP("127.0.0.1")
 | 
				
			||||||
 | 
						port := 53
 | 
				
			||||||
 | 
						return &net.UDPAddr{IP: ip, Port: port, Zone: ""}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (t *TestResponseWriter) RemoteAddr() net.Addr {
 | 
				
			||||||
 | 
						ip := net.ParseIP("10.240.0.1")
 | 
				
			||||||
 | 
						port := 40212
 | 
				
			||||||
 | 
						return &net.UDPAddr{IP: ip, Port: port, Zone: ""}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (t *TestResponseWriter) WriteMsg(m *dns.Msg) error     { return nil }
 | 
				
			||||||
 | 
					func (t *TestResponseWriter) Write(buf []byte) (int, error) { return len(buf), nil }
 | 
				
			||||||
 | 
					func (t *TestResponseWriter) Close() error                  { return nil }
 | 
				
			||||||
 | 
					func (t *TestResponseWriter) TsigStatus() error             { return nil }
 | 
				
			||||||
 | 
					func (t *TestResponseWriter) TsigTimersOnly(bool)           { return }
 | 
				
			||||||
 | 
					func (t *TestResponseWriter) Hijack()                       { return }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -53,6 +53,11 @@ func NewReplacer(r *dns.Msg, rr *ResponseRecorder, emptyValue string) Replacer {
 | 
				
			|||||||
		rep.replacements["{latency}"] = time.Since(rr.start).String()
 | 
							rep.replacements["{latency}"] = time.Since(rr.start).String()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Header placeholders (case-insensitive)
 | 
				
			||||||
 | 
						// TODO(miek): syntax for flags
 | 
				
			||||||
 | 
						rep.replacements[headerReplacer+"id}"] = strconv.Itoa(int(r.Id))
 | 
				
			||||||
 | 
						rep.replacements[headerReplacer+"opcode}"] = strconv.Itoa(int(r.Opcode))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return rep
 | 
						return rep
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user