How do I change the target_url for my proxy in a Custom Go Plugin?

This works using the UI and an advanced trigger via URL Rewrite. But in my Go plugin, I want to change the target_url so that I can do header validation and process the request to one of multiple upstreams depending on the header value.

Eg. header “UserID: 1” should send the upstream to Service A
header “UserID: 2” should send the upstream to Service B


The example below will accomplish a target_url redirect based on header value, in a Go plugin.

func setUpstream(r *http.Request, upstream string) {
	apiDef := ctx.GetDefinition(r)
	apiDef.Proxy.EnableLoadBalancing = true
	apiDef.Proxy.StructuredTargetList = apidef.NewHostListFromList([]string{upstream})

func ChangeUpstreamURL(rw http.ResponseWriter, r *http.Request) {
	userHeader := r.Header.Get("UserID")

	if userHeader == "1" {
		setUpstream(r, "")
	} else if userHeader == "2" {
		setUpstream(r, "")
	} else {
		setUpstream(r, "")

Firas this is giving me Deja Vu from our sync today

Haha totally! This can definitely do what you’re looking to accomplish and we can make it more sophisticated too. Lets chat! :slightly_smiling_face:

I’m trying not to spam the forums, but I am having issue building the Go plugin in the Go custom plugin tutorial because we don’t have a license. I tried to use the docker image the tutorial uses directly, but there are incompatibilities in versions of the tutorial .go file

Any tips?

Makes perfect sense - you will need a license key to stand up the Gateway in the Custom-Go-Plugin repo. You can self serve a license key here and run that environment directly via the MakeFile.

Please note that this solution will override the StructuredTargetList at the API definition level, which can result in race conditions. For example, a ManyToMany relationship when we return a different upstream for identical requests (i.e., based on a key).

Could you explain more on this?

Our tests shows the golang url rewrite thing works as expected.

  • the host is rewritten based on the logic of the plugin
  • the apidef is preserved. its not changed by the plugin