func()

in plugins/wasm-go/extensions/transformer/main.go [894:1011]


func (h kvHandler) handle(host, path string, kvs map[string][]string, mapSourceData map[string]MapSourceData) error {
	// arbitary order. for example: remove → rename → replace → add → append → map → dedupe

	for _, kvtOp := range h.kvtOps {
		switch kvtOp.kvtOpType {
		case RemoveK:
			// remove
			for _, remove := range kvtOp.removeKvtGroup {
				delete(kvs, remove.key)
			}
		case RenameK:
			// rename: 若指定 oldKey 不存在则无操作;否则将 oldKey 的值追加给 newKey,并删除 oldKey:value
			for _, rename := range kvtOp.renameKvtGroup {
				oldKey, newKey := rename.oldKey, rename.newKey
				if ovs, ok := kvs[oldKey]; ok {
					kvs[newKey] = append(kvs[newKey], ovs...)
					delete(kvs, oldKey)
				}
			}
		case ReplaceK:
			// replace: 若指定 key 不存在,则无操作;否则替换 value 为 newValue
			for _, replace := range kvtOp.replaceKvtGroup {
				key, newValue := replace.key, replace.newValue
				if _, ok := kvs[key]; !ok {
					continue
				}
				if replace.reg != nil {
					newValue = replace.reg.matchAndReplace(newValue, host, path)
				}
				kvs[replace.key] = []string{newValue}
			}
		case AddK:
			// add: 若指定 key 存在则无操作;否则添加 key:value
			for _, add := range kvtOp.addKvtGroup {
				key, value := add.key, add.value
				if _, ok := kvs[key]; ok {
					continue
				}
				if add.reg != nil {
					value = add.reg.matchAndReplace(value, host, path)
				}
				kvs[key] = []string{value}
			}

		case AppendK:
			// append: 若指定 key 存在,则追加同名 kv;否则相当于添加操作
			for _, append_ := range kvtOp.appendKvtGroup {
				key, appendValue := append_.key, append_.appendValue
				if append_.reg != nil {
					appendValue = append_.reg.matchAndReplace(appendValue, host, path)
				}
				kvs[key] = append(kvs[key], appendValue)
			}
		case MapK:
			// map: 若指定 fromKey 不存在则无操作;否则将 fromKey 的值映射给 toKey 的值
			for _, map_ := range kvtOp.mapKvtGroup {
				fromKey, toKey := map_.fromKey, map_.toKey
				if kvtOp.mapSource == "headers" {
					fromKey = strings.ToLower(fromKey)
				}
				source, exist := mapSourceData[kvtOp.mapSource]
				if !exist {
					proxywasm.LogWarnf("map key failed, source:%s not exists", kvtOp.mapSource)
					continue
				}
				proxywasm.LogDebugf("search key:%s in source:%s", fromKey, kvtOp.mapSource)
				if fromValue, ok := source.search(fromKey); ok {
					switch source.mapSourceType {
					case "headers", "querys", "bodyKv":
						kvs[toKey] = fromValue.([]string)
						proxywasm.LogDebugf("map key:%s to key:%s success, value is: %v", fromKey, toKey, fromValue)

					case "bodyJson":
						if valueJson, ok := fromValue.(gjson.Result); ok {
							valueStr := valueJson.String()
							if valueStr != "" {
								kvs[toKey] = []string{valueStr}
								proxywasm.LogDebugf("map key:%s to key:%s success, values is:%s", fromKey, toKey, valueStr)
							}
						}
					}
				}
			}

		case DedupeK:
			// dedupe: 根据 strategy 去重:RETAIN_UNIQUE 保留所有唯一值,RETAIN_LAST 保留最后一个值,RETAIN_FIRST 保留第一个值 (default)
			for _, dedupe := range kvtOp.dedupeKvtGroup {
				key, strategy := dedupe.key, dedupe.strategy
				switch strings.ToUpper(strategy) {
				case "RETAIN_UNIQUE":
					uniSet, uniques := make(map[string]struct{}), make([]string, 0)
					for _, v := range kvs[key] {
						if _, ok := uniSet[v]; !ok {
							uniSet[v] = struct{}{}
							uniques = append(uniques, v)
						}
					}
					kvs[key] = uniques

				case "RETAIN_LAST":
					if vs, ok := kvs[key]; ok && len(vs) >= 1 {
						kvs[key] = vs[len(vs)-1:]
					}

				case "RETAIN_FIRST":
					fallthrough
				default:
					if vs, ok := kvs[key]; ok && len(vs) >= 1 {
						kvs[key] = vs[:1]
					}
				}
			}

		}
	}

	return nil
}