123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- package backends
- import (
- "bytes"
- "compress/zlib"
- "github.com/flashmob/go-guerrilla/mail"
- "io"
- "sync"
- )
- // ----------------------------------------------------------------------------------
- // Processor Name: compressor
- // ----------------------------------------------------------------------------------
- // Description : Compress the e.Data (email data) and e.DeliveryHeader together
- // ----------------------------------------------------------------------------------
- // Config Options: None
- // --------------:-------------------------------------------------------------------
- // Input : e.Data, e.DeliveryHeader generated by Header() processor
- // ----------------------------------------------------------------------------------
- // Output : sets the pointer to a compressor in e.Info["zlib-compressor"]
- // : to write the compressed data, simply use fmt to print as a string,
- // : eg. fmt.Println("%s", e.Info["zlib-compressor"])
- // : or just call the String() func .Info["zlib-compressor"].String()
- // : Note that it can only be outputted once. It destroys the buffer
- // : after being printed
- // ----------------------------------------------------------------------------------
- func init() {
- processors["compressor"] = func() Decorator {
- return Compressor()
- }
- }
- // compressedData struct will be compressed using zlib when printed via fmt
- type compressor struct {
- extraHeaders []byte
- data *bytes.Buffer
- // the pool is used to recycle buffers to ease up on the garbage collector
- pool *sync.Pool
- }
- // newCompressedData returns a new CompressedData
- func newCompressor() *compressor {
- // grab it from the pool
- var p = sync.Pool{
- // if not available, then create a new one
- New: func() interface{} {
- var b bytes.Buffer
- return &b
- },
- }
- return &compressor{
- pool: &p,
- }
- }
- // Set the extraheaders and buffer of data to compress
- func (c *compressor) set(b []byte, d *bytes.Buffer) {
- c.extraHeaders = b
- c.data = d
- }
- // String implements the Stringer interface.
- // Can only be called once!
- // This is because the compression buffer will be reset and compressor will be returned to the pool
- func (c *compressor) String() string {
- if c.data == nil {
- return ""
- }
- //borrow a buffer form the pool
- b := c.pool.Get().(*bytes.Buffer)
- // put back in the pool
- defer func() {
- b.Reset()
- c.pool.Put(b)
- }()
- var r *bytes.Reader
- w, _ := zlib.NewWriterLevel(b, zlib.BestSpeed)
- r = bytes.NewReader(c.extraHeaders)
- _, _ = io.Copy(w, r)
- _, _ = io.Copy(w, c.data)
- _ = w.Close()
- return b.String()
- }
- // clear it, without clearing the pool
- func (c *compressor) clear() {
- c.extraHeaders = []byte{}
- c.data = nil
- }
- func Compressor() Decorator {
- return func(p Processor) Processor {
- return ProcessWith(func(e *mail.Envelope, task SelectTask) (Result, error) {
- if task == TaskSaveMail {
- compressor := newCompressor()
- compressor.set([]byte(e.DeliveryHeader), &e.Data)
- // put the pointer in there for other processors to use later in the line
- e.Values["zlib-compressor"] = compressor
- // continue to the next Processor in the decorator stack
- return p.Process(e, task)
- } else {
- return p.Process(e, task)
- }
- })
- }
- }
|