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