func onHttpRequestHeaders()

in plugins/wasm-go/extensions/transformer/main.go [287:394]


func onHttpRequestHeaders(ctx wrapper.HttpContext, config TransformerConfig, log wrapper.Log) types.Action {
	// because it may be a response transformer, so the setting of host and path have to advance
	host, path := ctx.Host(), ctx.Path()
	ctx.SetContext("host", host)
	ctx.SetContext("path", path)

	if config.reqTrans == nil {
		ctx.DontReadRequestBody()
		return types.ActionContinue
	}

	log.Debug("on http request headers ...")

	headers, err := proxywasm.GetHttpRequestHeaders()
	if err != nil {
		log.Warn("failed to get request headers")
		ctx.DontReadRequestBody()
		return types.ActionContinue
	}
	hs := convertHeaders(headers)
	if hs[":authority"] == nil {
		log.Warn(errGetRequestHost.Error())
		ctx.DontReadRequestBody()
		return types.ActionContinue
	}
	if hs[":path"] == nil {
		log.Warn(errGetRequestPath.Error())
		ctx.DontReadRequestBody()
		return types.ActionContinue
	}
	contentType := ""
	if hs["content-type"] != nil {
		contentType = hs["content-type"][0]
	}
	ctx.SetContext("content-type", contentType)

	isValidRequestContent := isValidRequestContentType(contentType)
	isBodyChange := config.reqTrans.IsBodyChange()
	needBodyMapSource := config.reqTrans.NeedBodyMapSource()

	log.Debugf("contentType:%s, isValidRequestContent:%v, isBodyChange:%v, needBodyMapSource:%v",
		contentType, isValidRequestContent, isBodyChange, needBodyMapSource)

	if isBodyChange && isValidRequestContent {
		delete(hs, "content-length")
	}

	qs, err := parseQueryByPath(path)
	if err != nil {
		log.Warnf("failed to parse query params by path: %v", err)
		ctx.DontReadRequestBody()
		return types.ActionContinue
	}

	ctx.SetContext("headers", hs)
	ctx.SetContext("querys", qs)

	if !isValidRequestContent || (!isBodyChange && !needBodyMapSource) {
		ctx.DontReadRequestBody()
	} else if needBodyMapSource {
		// we need do transform during body phase
		ctx.SetContext("need_head_trans", struct{}{})
		log.Debug("delay header's transform to body phase")
		return types.HeaderStopIteration
	}

	mapSourceData := make(map[string]MapSourceData)
	mapSourceData["headers"] = MapSourceData{
		mapSourceType: "headers",
		kvs:           hs,
	}
	mapSourceData["querys"] = MapSourceData{
		mapSourceType: "querys",
		kvs:           qs,
	}

	if config.reqTrans.IsHeaderChange() {
		if err = config.reqTrans.TransformHeaders(host, path, hs, mapSourceData); err != nil {
			log.Warnf("failed to transform request headers: %v", err)
			ctx.DontReadRequestBody()
			return types.ActionContinue
		}
	}

	if config.reqTrans.IsQueryChange() {
		if err = config.reqTrans.TransformQuerys(host, path, qs, mapSourceData); err != nil {
			log.Warnf("failed to transform request query params: %v", err)
			ctx.DontReadRequestBody()
			return types.ActionContinue
		}
		path, err = constructPath(path, qs)
		if err != nil {
			log.Warnf("failed to construct path: %v", err)
			ctx.DontReadRequestBody()
			return types.ActionContinue
		}
		hs[":path"] = []string{path}
	}

	headers = reconvertHeaders(hs)
	if err = proxywasm.ReplaceHttpRequestHeaders(headers); err != nil {
		log.Warnf("failed to replace request headers: %v", err)
		ctx.DontReadRequestBody()
		return types.ActionContinue
	}

	return types.ActionContinue
}