mirror of
				https://github.com/coredns/coredns.git
				synced 2025-11-03 02:33:21 -05:00 
			
		
		
		
	* Create geoip plugin Signed-off-by: Sven Nebel <nebel.sven@gmail.com> * Update plugin/geoip/README.md Co-authored-by: Miek Gieben <miek@miek.nl> Signed-off-by: Sven Nebel <nebel.sven@gmail.com> * Update plugin/geoip/README.md Co-authored-by: Miek Gieben <miek@miek.nl> Signed-off-by: Sven Nebel <nebel.sven@gmail.com> * Update plugin/geoip/README.md Co-authored-by: Miek Gieben <miek@miek.nl> Signed-off-by: Sven Nebel <nebel.sven@gmail.com> * Move DBFILE bullet below example Signed-off-by: Sven Nebel <nebel.sven@gmail.com> * Update plugin/geoip/README.md Co-authored-by: Miek Gieben <miek@miek.nl> Signed-off-by: Sven Nebel <nebel.sven@gmail.com> * Remove plugin name test case Signed-off-by: Sven Nebel <nebel.sven@gmail.com> * Remove languages option Signed-off-by: Sven Nebel <nebel.sven@gmail.com> * Update free database link Signed-off-by: Sven Nebel <nebel.sven@gmail.com> * Remove last language bits Signed-off-by: Sven Nebel <nebel.sven@gmail.com> * Use 127.0.0.1 as probing IP Signed-off-by: Sven Nebel <nebel.sven@gmail.com> * Update plugin/geoip/geoip.go Co-authored-by: Miek Gieben <miek@miek.nl> Signed-off-by: Sven Nebel <nebel.sven@gmail.com> * Update plugin/geoip/geoip.go Co-authored-by: Miek Gieben <miek@miek.nl> Signed-off-by: Sven Nebel <nebel.sven@gmail.com> * Use relative path for fixtures dir Signed-off-by: Sven Nebel <nebel.sven@gmail.com> * Set names with default string zero value Signed-off-by: Sven Nebel <nebel.sven@gmail.com> * Remove unused db types Signed-off-by: Sven Nebel <nebel.sven@gmail.com> * Remove non city databases in testdata Signed-off-by: Sven Nebel <nebel.sven@gmail.com> * Remove create databases main Signed-off-by: Sven Nebel <nebel.sven@gmail.com> * Fix metadata label format test case Signed-off-by: Sven Nebel <nebel.sven@gmail.com> * Fix import path block Signed-off-by: Sven Nebel <nebel.sven@gmail.com> * go fmt after changes Signed-off-by: Sven Nebel <nebel.sven@gmail.com> * Tidy up go.mod and go.sum Signed-off-by: Sven Nebel <nebel.sven@gmail.com> * Add plugin to CODEOWNERS Signed-off-by: Sven Nebel <nebel.sven@gmail.com> Co-authored-by: Miek Gieben <miek@miek.nl>
		
			
				
	
	
		
			129 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			129 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Package metadata provides an API that allows plugins to add metadata to the context.
 | 
						|
// Each metadata is stored under a label that has the form <plugin>/<name>. Each metadata
 | 
						|
// is returned as a Func. When Func is called the metadata is returned. If Func is expensive to
 | 
						|
// execute it is its responsibility to provide some form of caching. During the handling of a
 | 
						|
// query it is expected the metadata stays constant.
 | 
						|
//
 | 
						|
// Basic example:
 | 
						|
//
 | 
						|
// Implement the Provider interface for a plugin p:
 | 
						|
//
 | 
						|
//    func (p P) Metadata(ctx context.Context, state request.Request) context.Context {
 | 
						|
//       metadata.SetValueFunc(ctx, "test/something", func() string { return "myvalue" })
 | 
						|
//	 return ctx
 | 
						|
//    }
 | 
						|
//
 | 
						|
// Basic example with caching:
 | 
						|
//
 | 
						|
//    func (p P) Metadata(ctx context.Context, state request.Request) context.Context {
 | 
						|
//       cached := ""
 | 
						|
//       f := func() string {
 | 
						|
//		if cached != "" {
 | 
						|
//                 return cached
 | 
						|
//             }
 | 
						|
//             cached = expensiveFunc()
 | 
						|
//             return cached
 | 
						|
//       }
 | 
						|
//       metadata.SetValueFunc(ctx, "test/something", f)
 | 
						|
//	 return ctx
 | 
						|
//    }
 | 
						|
//
 | 
						|
// If you need access to this metadata from another plugin:
 | 
						|
//
 | 
						|
//    // ...
 | 
						|
//    valueFunc := metadata.ValueFunc(ctx, "test/something")
 | 
						|
//    value := valueFunc()
 | 
						|
//    // use 'value'
 | 
						|
//
 | 
						|
package metadata
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"strings"
 | 
						|
 | 
						|
	"github.com/coredns/coredns/request"
 | 
						|
)
 | 
						|
 | 
						|
// Provider interface needs to be implemented by each plugin willing to provide
 | 
						|
// metadata information for other plugins.
 | 
						|
type Provider interface {
 | 
						|
	// Metadata adds metadata to the context and returns a (potentially) new context.
 | 
						|
	// Note: this method should work quickly, because it is called for every request
 | 
						|
	// from the metadata plugin.
 | 
						|
	Metadata(ctx context.Context, state request.Request) context.Context
 | 
						|
}
 | 
						|
 | 
						|
// Func is the type of function in the metadata, when called they return the value of the label.
 | 
						|
type Func func() string
 | 
						|
 | 
						|
// IsLabel checks that the provided name is a valid label name, i.e. two or more words separated by a slash.
 | 
						|
func IsLabel(label string) bool {
 | 
						|
	p := strings.Index(label, "/")
 | 
						|
	if p <= 0 || p >= len(label)-1 {
 | 
						|
		// cannot accept namespace empty nor label empty
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	return true
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
// Labels returns all metadata keys stored in the context. These label names should be named
 | 
						|
// as: plugin/NAME, where NAME is something descriptive.
 | 
						|
func Labels(ctx context.Context) []string {
 | 
						|
	if metadata := ctx.Value(key{}); metadata != nil {
 | 
						|
		if m, ok := metadata.(md); ok {
 | 
						|
			return keys(m)
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// ValueFuncs returns the map[string]Func from the context, or nil if it does not exist.
 | 
						|
func ValueFuncs(ctx context.Context) map[string]Func {
 | 
						|
	if metadata := ctx.Value(key{}); metadata != nil {
 | 
						|
		if m, ok := metadata.(md); ok {
 | 
						|
			return m
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// ValueFunc returns the value function of label. If none can be found nil is returned. Calling the
 | 
						|
// function returns the value of the label.
 | 
						|
func ValueFunc(ctx context.Context, label string) Func {
 | 
						|
	if metadata := ctx.Value(key{}); metadata != nil {
 | 
						|
		if m, ok := metadata.(md); ok {
 | 
						|
			return m[label]
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// SetValueFunc set the metadata label to the value function. If no metadata can be found this is a noop and
 | 
						|
// false is returned. Any existing value is overwritten.
 | 
						|
func SetValueFunc(ctx context.Context, label string, f Func) bool {
 | 
						|
	if metadata := ctx.Value(key{}); metadata != nil {
 | 
						|
		if m, ok := metadata.(md); ok {
 | 
						|
			m[label] = f
 | 
						|
			return true
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return false
 | 
						|
}
 | 
						|
 | 
						|
// md is metadata information storage.
 | 
						|
type md map[string]Func
 | 
						|
 | 
						|
// key defines the type of key that is used to save metadata into the context.
 | 
						|
type key struct{}
 | 
						|
 | 
						|
func keys(m map[string]Func) []string {
 | 
						|
	s := make([]string, len(m))
 | 
						|
	i := 0
 | 
						|
	for k := range m {
 | 
						|
		s[i] = k
 | 
						|
		i++
 | 
						|
	}
 | 
						|
	return s
 | 
						|
}
 |