github.com/gofiber/fiber/v2@v2.47.0/middleware/logger/template_chain.go (about)

     1  package logger
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  
     7  	"github.com/gofiber/fiber/v2/utils"
     8  )
     9  
    10  // buildLogFuncChain analyzes the template and creates slices with the functions for execution and
    11  // slices with the fixed parts of the template and the parameters
    12  //
    13  // fixParts contains the fixed parts of the template or parameters if a function is stored in the funcChain at this position
    14  // funcChain contains for the parts which exist the functions for the dynamic parts
    15  // funcChain and fixParts always have the same length and contain nil for the parts where no data is required in the chain,
    16  // if a function exists for the part, a parameter for it can also exist in the fixParts slice
    17  func buildLogFuncChain(cfg *Config, tagFunctions map[string]LogFunc) ([][]byte, []LogFunc, error) {
    18  	// process flow is copied from the fasttemplate flow https://github.com/valyala/fasttemplate/blob/2a2d1afadadf9715bfa19683cdaeac8347e5d9f9/template.go#L23-L62
    19  	templateB := utils.UnsafeBytes(cfg.Format)
    20  	startTagB := utils.UnsafeBytes(startTag)
    21  	endTagB := utils.UnsafeBytes(endTag)
    22  	paramSeparatorB := utils.UnsafeBytes(paramSeparator)
    23  
    24  	var fixParts [][]byte
    25  	var funcChain []LogFunc
    26  
    27  	for {
    28  		currentPos := bytes.Index(templateB, startTagB)
    29  		if currentPos < 0 {
    30  			// no starting tag found in the existing template part
    31  			break
    32  		}
    33  		// add fixed part
    34  		funcChain = append(funcChain, nil)
    35  		fixParts = append(fixParts, templateB[:currentPos])
    36  
    37  		templateB = templateB[currentPos+len(startTagB):]
    38  		currentPos = bytes.Index(templateB, endTagB)
    39  		if currentPos < 0 {
    40  			// cannot find end tag - just write it to the output.
    41  			funcChain = append(funcChain, nil)
    42  			fixParts = append(fixParts, startTagB)
    43  			break
    44  		}
    45  		// ## function block ##
    46  		// first check for tags with parameters
    47  		if index := bytes.Index(templateB[:currentPos], paramSeparatorB); index != -1 {
    48  			logFunc, ok := tagFunctions[utils.UnsafeString(templateB[:index+1])]
    49  			if !ok {
    50  				return nil, nil, errors.New("No parameter found in \"" + utils.UnsafeString(templateB[:currentPos]) + "\"")
    51  			}
    52  			funcChain = append(funcChain, logFunc)
    53  			// add param to the fixParts
    54  			fixParts = append(fixParts, templateB[index+1:currentPos])
    55  		} else if logFunc, ok := tagFunctions[utils.UnsafeString(templateB[:currentPos])]; ok {
    56  			// add functions without parameter
    57  			funcChain = append(funcChain, logFunc)
    58  			fixParts = append(fixParts, nil)
    59  		}
    60  		// ## function block end ##
    61  
    62  		// reduce the template string
    63  		templateB = templateB[currentPos+len(endTagB):]
    64  	}
    65  	// set the rest
    66  	funcChain = append(funcChain, nil)
    67  	fixParts = append(fixParts, templateB)
    68  
    69  	return fixParts, funcChain, nil
    70  }