github.com/Jeffail/benthos/v3@v3.65.0/lib/processor/encode.go (about) 1 package processor 2 3 import ( 4 "bytes" 5 "encoding/ascii85" 6 "encoding/base64" 7 "encoding/hex" 8 "fmt" 9 "time" 10 11 "github.com/Jeffail/benthos/v3/internal/docs" 12 "github.com/Jeffail/benthos/v3/internal/tracing" 13 "github.com/Jeffail/benthos/v3/lib/log" 14 "github.com/Jeffail/benthos/v3/lib/metrics" 15 "github.com/Jeffail/benthos/v3/lib/response" 16 "github.com/Jeffail/benthos/v3/lib/types" 17 "github.com/tilinna/z85" 18 ) 19 20 //------------------------------------------------------------------------------ 21 22 func init() { 23 Constructors[TypeEncode] = TypeSpec{ 24 constructor: NewEncode, 25 Status: docs.StatusDeprecated, 26 Footnotes: ` 27 ## Alternatives 28 29 All functionality of this processor has been superseded by the 30 [bloblang](/docs/components/processors/bloblang) processor.`, 31 FieldSpecs: docs.FieldSpecs{ 32 docs.FieldCommon("scheme", "The decoding scheme to use.").HasOptions("hex", "base64", "ascii85", "z85"), 33 PartsFieldSpec, 34 }, 35 } 36 } 37 38 //------------------------------------------------------------------------------ 39 40 // EncodeConfig contains configuration fields for the Encode processor. 41 type EncodeConfig struct { 42 Scheme string `json:"scheme" yaml:"scheme"` 43 Parts []int `json:"parts" yaml:"parts"` 44 } 45 46 // NewEncodeConfig returns a EncodeConfig with default values. 47 func NewEncodeConfig() EncodeConfig { 48 return EncodeConfig{ 49 Scheme: "base64", 50 Parts: []int{}, 51 } 52 } 53 54 //------------------------------------------------------------------------------ 55 56 type encodeFunc func(bytes []byte) ([]byte, error) 57 58 func base64Encode(b []byte) ([]byte, error) { 59 var buf bytes.Buffer 60 61 e := base64.NewEncoder(base64.StdEncoding, &buf) 62 e.Write(b) 63 e.Close() 64 65 return buf.Bytes(), nil 66 } 67 68 func hexEncode(b []byte) ([]byte, error) { 69 var buf bytes.Buffer 70 71 e := hex.NewEncoder(&buf) 72 if _, err := e.Write(b); err != nil { 73 return nil, err 74 } 75 return buf.Bytes(), nil 76 } 77 78 func ascii85Encode(b []byte) ([]byte, error) { 79 var buf bytes.Buffer 80 81 e := ascii85.NewEncoder(&buf) 82 if _, err := e.Write(b); err != nil { 83 return nil, err 84 } 85 return buf.Bytes(), nil 86 } 87 88 func z85Encode(b []byte) ([]byte, error) { 89 enc := make([]byte, z85.EncodedLen(len(b))) 90 if _, err := z85.Encode(enc, b); err != nil { 91 return nil, err 92 } 93 return enc, nil 94 } 95 96 func strToEncoder(str string) (encodeFunc, error) { 97 switch str { 98 case "base64": 99 return base64Encode, nil 100 case "hex": 101 return hexEncode, nil 102 case "ascii85": 103 return ascii85Encode, nil 104 case "z85": 105 return z85Encode, nil 106 } 107 return nil, fmt.Errorf("encode scheme not recognised: %v", str) 108 } 109 110 //------------------------------------------------------------------------------ 111 112 // Encode is a processor that can selectively encode parts of a message 113 // following a chosen scheme. 114 type Encode struct { 115 conf EncodeConfig 116 fn encodeFunc 117 118 log log.Modular 119 stats metrics.Type 120 121 mCount metrics.StatCounter 122 mErr metrics.StatCounter 123 mSent metrics.StatCounter 124 mBatchSent metrics.StatCounter 125 } 126 127 // NewEncode returns a Encode processor. 128 func NewEncode( 129 conf Config, mgr types.Manager, log log.Modular, stats metrics.Type, 130 ) (Type, error) { 131 cor, err := strToEncoder(conf.Encode.Scheme) 132 if err != nil { 133 return nil, err 134 } 135 return &Encode{ 136 conf: conf.Encode, 137 fn: cor, 138 log: log, 139 stats: stats, 140 141 mCount: stats.GetCounter("count"), 142 mErr: stats.GetCounter("error"), 143 mSent: stats.GetCounter("sent"), 144 mBatchSent: stats.GetCounter("batch.sent"), 145 }, nil 146 } 147 148 //------------------------------------------------------------------------------ 149 150 // ProcessMessage applies the processor to a message, either creating >0 151 // resulting messages or a response to be sent back to the message source. 152 func (c *Encode) ProcessMessage(msg types.Message) ([]types.Message, types.Response) { 153 c.mCount.Incr(1) 154 newMsg := msg.Copy() 155 156 proc := func(i int, span *tracing.Span, part types.Part) error { 157 newPart, err := c.fn(part.Get()) 158 if err == nil { 159 newMsg.Get(i).Set(newPart) 160 } else { 161 c.log.Debugf("Failed to encode message part: %v\n", err) 162 c.mErr.Incr(1) 163 } 164 return err 165 } 166 167 if newMsg.Len() == 0 { 168 return nil, response.NewAck() 169 } 170 171 IteratePartsWithSpanV2(TypeEncode, c.conf.Parts, newMsg, proc) 172 173 c.mBatchSent.Incr(1) 174 c.mSent.Incr(int64(newMsg.Len())) 175 msgs := [1]types.Message{newMsg} 176 return msgs[:], nil 177 } 178 179 // CloseAsync shuts down the processor and stops processing requests. 180 func (c *Encode) CloseAsync() { 181 } 182 183 // WaitForClose blocks until the processor has closed down. 184 func (c *Encode) WaitForClose(timeout time.Duration) error { 185 return nil 186 } 187 188 //------------------------------------------------------------------------------