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  //------------------------------------------------------------------------------