Files
higress/plugins/wasm-go/example/http-call/main.go
2022-11-04 17:46:43 +08:00

121 lines
3.7 KiB
Go

// Copyright (c) 2022 Alibaba Group Holding Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main
import (
"errors"
"net/http"
"strings"
"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm"
"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm/types"
"github.com/tidwall/gjson"
"github.com/mse-group/wasm-extensions-go/pkg/wrapper"
)
func main() {
wrapper.SetCtx(
"http-call",
wrapper.ParseConfigBy(parseConfig),
wrapper.ProcessRequestHeadersBy(onHttpRequestHeaders),
)
}
type HttpCallConfig struct {
client wrapper.HttpClient
requestPath string
bodyHeader string
tokenHeader string
}
func parseConfig(json gjson.Result, config *HttpCallConfig, log wrapper.LogWrapper) error {
config.bodyHeader = json.Get("bodyHeader").String()
if config.bodyHeader == "" {
return errors.New("missing bodyHeader in config")
}
config.tokenHeader = json.Get("tokenHeader").String()
if config.tokenHeader == "" {
return errors.New("missing tokenHeader in config")
}
config.requestPath = json.Get("requestPath").String()
if config.requestPath == "" {
return errors.New("missing requestPath in config")
}
serviceSource := json.Get("serviceSource").String()
serviceName := json.Get("serviceName").String()
servicePort := json.Get("servicePort").Int()
if serviceName == "" || servicePort == 0 {
return errors.New("invalid service config")
}
switch serviceSource {
case "k8s":
namespace := json.Get("namespace").String()
config.client = wrapper.NewClusterClient(wrapper.K8sCluster{
ServiceName: serviceName,
Namespace: namespace,
Port: servicePort,
})
return nil
case "nacos":
namespace := json.Get("namespace").String()
config.client = wrapper.NewClusterClient(wrapper.NacosCluster{
ServiceName: serviceName,
NamespaceID: namespace,
Port: servicePort,
})
return nil
case "ip":
config.client = wrapper.NewClusterClient(wrapper.StaticIpCluster{
ServiceName: serviceName,
Port: servicePort,
})
return nil
case "dns":
domain := json.Get("domain").String()
config.client = wrapper.NewClusterClient(wrapper.DnsCluster{
ServiceName: serviceName,
Port: servicePort,
Domain: domain,
})
return nil
default:
return errors.New("unknown service source: " + serviceSource)
}
}
func onHttpRequestHeaders(contextID uint32, config HttpCallConfig, needBody *bool, log wrapper.LogWrapper) types.Action {
config.client.Get(config.requestPath, nil,
func(statusCode int, responseHeaders http.Header, responseBody []byte) {
defer proxywasm.ResumeHttpRequest()
if statusCode != http.StatusOK {
log.Errorf("http call failed, status: %d", statusCode)
proxywasm.SendHttpResponse(http.StatusInternalServerError, nil,
[]byte("http call failed"), -1)
return
}
// avoid protocol error
body := strings.ReplaceAll(string(responseBody), "\n", "#")
// set body to the original request header
proxywasm.AddHttpRequestHeader(config.bodyHeader, body)
// set service response token header to the original request header
token := responseHeaders.Get(config.tokenHeader)
if token != "" {
proxywasm.AddHttpRequestHeader(config.tokenHeader, token)
}
})
return types.ActionPause
}