github.com/sohaha/zlsgo@v1.7.13-0.20240501141223-10dd1a906f76/znet/cache/cache.go (about)

     1  package cache
     2  
     3  import (
     4  	"sort"
     5  	"time"
     6  
     7  	"github.com/sohaha/zlsgo/zcache"
     8  	"github.com/sohaha/zlsgo/znet"
     9  	"github.com/sohaha/zlsgo/zstring"
    10  )
    11  
    12  type (
    13  	// Config configuration
    14  	Config struct {
    15  		Custom func(c *znet.Context) (key string, expiration time.Duration)
    16  		zcache.Options
    17  	}
    18  	cacheContext struct {
    19  		Type    string
    20  		Content []byte
    21  		Code    int32
    22  	}
    23  )
    24  
    25  func New(opt ...func(conf *Config)) znet.HandlerFunc {
    26  	conf := Config{
    27  		Custom: func(c *znet.Context) (key string, expiration time.Duration) {
    28  			return QueryKey(c), 0
    29  		},
    30  	}
    31  
    32  	cache := zcache.NewFast(func(o *zcache.Options) {
    33  		conf.Options = *o
    34  		conf.Options.Expiration = time.Minute * 10
    35  		for _, f := range opt {
    36  			f(&conf)
    37  		}
    38  		*o = conf.Options
    39  	})
    40  
    41  	return func(c *znet.Context) {
    42  		key, expiration := conf.Custom(c)
    43  		if key == "" {
    44  			c.Next()
    45  			return
    46  		}
    47  
    48  		v, ok := cache.ProvideGet(key, func() (interface{}, bool) {
    49  			c.Next()
    50  
    51  			p := c.PrevContent()
    52  			if p.Code.Load() != 0 {
    53  				return &cacheContext{
    54  					Code:    p.Code.Load(),
    55  					Type:    p.Type,
    56  					Content: p.Content,
    57  				}, true
    58  			}
    59  			return nil, false
    60  		}, expiration)
    61  
    62  		if !ok {
    63  			return
    64  		}
    65  
    66  		if data, ok := v.(*cacheContext); ok {
    67  			p := c.PrevContent()
    68  			p.Code.Store(data.Code)
    69  			p.Content = data.Content
    70  			p.Type = data.Type
    71  			c.Abort()
    72  		}
    73  	}
    74  }
    75  
    76  func QueryKey(c *znet.Context) (key string) {
    77  	m := c.GetAllQueryMaps()
    78  	mLen := len(m)
    79  	if mLen == 0 {
    80  		return c.Request.URL.Path
    81  	}
    82  
    83  	keys := make([]string, 0, mLen)
    84  	for k := range m {
    85  		keys = append(keys, k)
    86  	}
    87  	sort.Strings(keys)
    88  
    89  	b := zstring.Buffer((len(m) * 4) + 2)
    90  	b.WriteString(c.Request.URL.Path)
    91  	b.WriteString("?")
    92  	for _, k := range keys {
    93  		b.WriteString(k)
    94  		b.WriteString("=")
    95  		b.WriteString(m[k])
    96  		b.WriteString("&")
    97  	}
    98  	return b.String()
    99  }