Files
higress/plugins/wasm-go/extensions/http-call/main_test.go

385 lines
12 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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 (
"encoding/json"
"testing"
"github.com/higress-group/proxy-wasm-go-sdk/proxywasm/types"
"github.com/higress-group/wasm-go/pkg/test"
"github.com/stretchr/testify/require"
)
// 测试k8s服务源配置
var k8sTestConfig = func() json.RawMessage {
data, _ := json.Marshal(map[string]interface{}{
"bodyHeader": "x-response-body",
"tokenHeader": "x-auth-token",
"requestPath": "/api/auth",
"serviceSource": "k8s",
"serviceName": "auth-service",
"servicePort": 8080,
"namespace": "default",
})
return data
}()
// 测试nacos服务源配置
var nacosTestConfig = func() json.RawMessage {
data, _ := json.Marshal(map[string]interface{}{
"bodyHeader": "x-response-body",
"tokenHeader": "x-auth-token",
"requestPath": "/api/auth",
"serviceSource": "nacos",
"serviceName": "auth-service",
"servicePort": 8080,
"namespace": "public",
})
return data
}()
// 测试ip服务源配置
var ipTestConfig = func() json.RawMessage {
data, _ := json.Marshal(map[string]interface{}{
"bodyHeader": "x-response-body",
"tokenHeader": "x-auth-token",
"requestPath": "/api/auth",
"serviceSource": "ip",
"serviceName": "auth-service",
"servicePort": 8080,
})
return data
}()
// 测试dns服务源配置
var dnsTestConfig = func() json.RawMessage {
data, _ := json.Marshal(map[string]interface{}{
"bodyHeader": "x-response-body",
"tokenHeader": "x-auth-token",
"requestPath": "/api/auth",
"serviceSource": "dns",
"serviceName": "auth-service",
"servicePort": 8080,
"domain": "auth.example.com",
})
return data
}()
// 测试缺少bodyHeader的配置
var missingBodyHeaderConfig = func() json.RawMessage {
data, _ := json.Marshal(map[string]interface{}{
"tokenHeader": "x-auth-token",
"requestPath": "/api/auth",
"serviceSource": "k8s",
"serviceName": "auth-service",
"servicePort": 8080,
"namespace": "default",
})
return data
}()
// 测试缺少tokenHeader的配置
var missingTokenHeaderConfig = func() json.RawMessage {
data, _ := json.Marshal(map[string]interface{}{
"bodyHeader": "x-response-body",
"requestPath": "/api/auth",
"serviceSource": "k8s",
"serviceName": "auth-service",
"servicePort": 8080,
"namespace": "default",
})
return data
}()
// 测试缺少requestPath的配置
var missingRequestPathConfig = func() json.RawMessage {
data, _ := json.Marshal(map[string]interface{}{
"bodyHeader": "x-response-body",
"tokenHeader": "x-auth-token",
"serviceSource": "k8s",
"serviceName": "auth-service",
"servicePort": 8080,
"namespace": "default",
})
return data
}()
// 测试无效服务源的配置
var invalidServiceSourceConfig = func() json.RawMessage {
data, _ := json.Marshal(map[string]interface{}{
"bodyHeader": "x-response-body",
"tokenHeader": "x-auth-token",
"requestPath": "/api/auth",
"serviceSource": "invalid",
"serviceName": "auth-service",
"servicePort": 8080,
"namespace": "default",
})
return data
}()
func TestParseConfig(t *testing.T) {
test.RunGoTest(t, func(t *testing.T) {
// 测试k8s服务源配置
t.Run("k8s service source", func(t *testing.T) {
host, status := test.NewTestHost(k8sTestConfig)
defer host.Reset()
require.Equal(t, types.OnPluginStartStatusOK, status)
config, err := host.GetMatchConfig()
require.NoError(t, err)
require.NotNil(t, config)
httpCallConfig := config.(*HttpCallConfig)
require.Equal(t, "x-response-body", httpCallConfig.bodyHeader)
require.Equal(t, "x-auth-token", httpCallConfig.tokenHeader)
require.Equal(t, "/api/auth", httpCallConfig.requestPath)
require.NotNil(t, httpCallConfig.client)
})
// 测试nacos服务源配置
t.Run("nacos service source", func(t *testing.T) {
host, status := test.NewTestHost(nacosTestConfig)
defer host.Reset()
require.Equal(t, types.OnPluginStartStatusOK, status)
config, err := host.GetMatchConfig()
require.NoError(t, err)
require.NotNil(t, config)
httpCallConfig := config.(*HttpCallConfig)
require.Equal(t, "x-response-body", httpCallConfig.bodyHeader)
require.Equal(t, "x-auth-token", httpCallConfig.tokenHeader)
require.Equal(t, "/api/auth", httpCallConfig.requestPath)
require.NotNil(t, httpCallConfig.client)
})
// 测试ip服务源配置
t.Run("ip service source", func(t *testing.T) {
host, status := test.NewTestHost(ipTestConfig)
defer host.Reset()
require.Equal(t, types.OnPluginStartStatusOK, status)
config, err := host.GetMatchConfig()
require.NoError(t, err)
require.NotNil(t, config)
httpCallConfig := config.(*HttpCallConfig)
require.Equal(t, "x-response-body", httpCallConfig.bodyHeader)
require.Equal(t, "x-auth-token", httpCallConfig.tokenHeader)
require.Equal(t, "/api/auth", httpCallConfig.requestPath)
require.NotNil(t, httpCallConfig.client)
})
// 测试dns服务源配置
t.Run("dns service source", func(t *testing.T) {
host, status := test.NewTestHost(dnsTestConfig)
defer host.Reset()
require.Equal(t, types.OnPluginStartStatusOK, status)
config, err := host.GetMatchConfig()
require.NoError(t, err)
require.NotNil(t, config)
httpCallConfig := config.(*HttpCallConfig)
require.Equal(t, "x-response-body", httpCallConfig.bodyHeader)
require.Equal(t, "x-auth-token", httpCallConfig.tokenHeader)
require.Equal(t, "/api/auth", httpCallConfig.requestPath)
require.NotNil(t, httpCallConfig.client)
})
// 测试缺少bodyHeader的配置
t.Run("missing bodyHeader", func(t *testing.T) {
host, status := test.NewTestHost(missingBodyHeaderConfig)
defer host.Reset()
require.Equal(t, types.OnPluginStartStatusFailed, status)
config, err := host.GetMatchConfig()
require.NoError(t, err) // 框架不会返回错误而是返回nil配置
require.Nil(t, config) // 配置解析失败时返回nil
})
// 测试缺少tokenHeader的配置
t.Run("missing tokenHeader", func(t *testing.T) {
host, status := test.NewTestHost(missingTokenHeaderConfig)
defer host.Reset()
require.Equal(t, types.OnPluginStartStatusFailed, status)
config, err := host.GetMatchConfig()
require.NoError(t, err) // 框架不会返回错误而是返回nil配置
require.Nil(t, config) // 配置解析失败时返回nil
})
// 测试缺少requestPath的配置
t.Run("missing requestPath", func(t *testing.T) {
host, status := test.NewTestHost(missingRequestPathConfig)
defer host.Reset()
require.Equal(t, types.OnPluginStartStatusFailed, status)
config, err := host.GetMatchConfig()
require.NoError(t, err) // 框架不会返回错误而是返回nil配置
require.Nil(t, config) // 配置解析失败时返回nil
})
// 测试无效服务源的配置
t.Run("invalid service source", func(t *testing.T) {
host, status := test.NewTestHost(invalidServiceSourceConfig)
defer host.Reset()
require.Equal(t, types.OnPluginStartStatusFailed, status)
config, err := host.GetMatchConfig()
require.NoError(t, err) // 框架不会返回错误而是返回nil配置
require.Nil(t, config) // 配置解析失败时返回nil
})
})
}
func TestK8sOnHttpRequestHeaders(t *testing.T) {
test.RunTest(t, func(t *testing.T) {
// 使用k8s配置进行测试
host, status := test.NewTestHost(k8sTestConfig)
defer host.Reset()
require.Equal(t, types.OnPluginStartStatusOK, status)
// 模拟HTTP请求头
action := host.CallOnHttpRequestHeaders([][2]string{
{":authority", "test.com"},
{":path", "/api/test"},
{":method", "GET"},
})
// 验证返回的action
require.Equal(t, types.HeaderStopAllIterationAndWatermark, action)
// 模拟外部服务的HTTP调用响应
// 模拟成功响应
host.CallOnHttpCall([][2]string{
{":status", "200"},
{"x-auth-token", "test-token-123"},
{"content-type", "application/json"},
}, []byte(`{"message": "success", "data": "test-data"}`))
// 验证请求头是否正确设置
requestHeaders := host.GetRequestHeaders()
// 查找bodyHeader
bodyHeaderFound := false
tokenHeaderFound := false
for _, header := range requestHeaders {
if header[0] == "x-response-body" {
bodyHeaderFound = true
// 验证响应体内容(换行符被替换为#
expectedBody := `{"message": "success", "data": "test-data"}`
require.Equal(t, expectedBody, header[1])
}
if header[0] == "x-auth-token" {
tokenHeaderFound = true
require.Equal(t, "test-token-123", header[1])
}
}
require.True(t, bodyHeaderFound, "bodyHeader should be set")
require.True(t, tokenHeaderFound, "tokenHeader should be set")
require.Equal(t, types.ActionContinue, host.GetHttpStreamAction())
host.CompleteHttp()
})
}
func TestK8sOnHttpRequestHeadersWithError(t *testing.T) {
test.RunTest(t, func(t *testing.T) {
// 使用k8s配置进行测试
host, status := test.NewTestHost(k8sTestConfig)
defer host.Reset()
require.Equal(t, types.OnPluginStartStatusOK, status)
// 模拟HTTP请求头
action := host.CallOnHttpRequestHeaders([][2]string{
{":authority", "test.com"},
{":path", "/api/test"},
{":method", "GET"},
})
// 验证返回的action
require.Equal(t, types.HeaderStopAllIterationAndWatermark, action)
// 模拟外部服务返回错误状态码
host.CallOnHttpCall([][2]string{
{":status", "500"},
{"content-type", "application/json"},
}, []byte(`{"error": "internal server error"}`))
// 验证请求头不应该被设置因为状态码不是200
requestHeaders := host.GetRequestHeaders()
bodyHeaderFound := false
tokenHeaderFound := false
for _, header := range requestHeaders {
if header[0] == "x-response-body" {
bodyHeaderFound = true
}
if header[0] == "x-auth-token" {
tokenHeaderFound = true
}
}
require.False(t, bodyHeaderFound, "bodyHeader should not be set when status code is not 200")
require.False(t, tokenHeaderFound, "tokenHeader should not be set when status code is not 200")
require.Equal(t, types.ActionContinue, host.GetHttpStreamAction())
host.CompleteHttp()
})
}
func TestK8sOnHttpRequestHeadersWithNewlines(t *testing.T) {
test.RunTest(t, func(t *testing.T) {
// 使用k8s配置进行测试
host, status := test.NewTestHost(k8sTestConfig)
defer host.Reset()
require.Equal(t, types.OnPluginStartStatusOK, status)
// 模拟HTTP请求头
action := host.CallOnHttpRequestHeaders([][2]string{
{":authority", "test.com"},
{":path", "/api/test"},
{":method", "GET"},
})
// 验证返回的action
require.Equal(t, types.HeaderStopAllIterationAndWatermark, action)
// 模拟外部服务响应包含换行符
responseBody := `{"message": "success",
"data": "test-data",
"description": "multi-line response"}`
host.CallOnHttpCall([][2]string{
{":status", "200"},
{"x-auth-token", "test-token-456"},
{"content-type", "application/json"},
}, []byte(responseBody))
// 验证请求头是否正确设置,换行符应该被替换为#
requestHeaders := host.GetRequestHeaders()
bodyHeaderFound := false
expectedBody := `{"message": "success",#"data": "test-data",#"description": "multi-line response"}`
for _, header := range requestHeaders {
if header[0] == "x-response-body" {
bodyHeaderFound = true
require.Equal(t, expectedBody, header[1])
}
}
require.True(t, bodyHeaderFound, "bodyHeader should be set with newlines replaced by #")
require.Equal(t, types.ActionContinue, host.GetHttpStreamAction())
host.CompleteHttp()
})
}