diff --git a/plugins/wasm-go/extensions/request-size-limit/README.md b/plugins/wasm-go/extensions/request-size-limit/README.md new file mode 100644 index 0000000000..dcdd75ca2c --- /dev/null +++ b/plugins/wasm-go/extensions/request-size-limit/README.md @@ -0,0 +1,21 @@ +# 功能说明 +`request-size-limit` 插件实现了限制请求 body 大小的作用,可以用于防止请求 body 过大的请求对网关及上游服务造成影响。 + +# 配置字段 + +| 名称 | 数据类型 | 填写要求 | 默认值 | 描述 | +|-------------|--------|---------------------------------------------|-----|----------------| +| requestSize | string | 需填写允许的请求体最大大小,单位为 B、KB、MB 或 GB。例如 1KB,2MB 等 | 1MB | 配置允许通过的请求体最大大小 | + +# 配置示例 + +## 限制请求 body 超过 5B 的请求 + +```yaml +requestSize: 5B +``` +配置完毕之后,下列请求将被禁止访问: + +```bash +curl -d "123456" http://example.com +``` diff --git a/plugins/wasm-go/extensions/request-size-limit/VERSION b/plugins/wasm-go/extensions/request-size-limit/VERSION new file mode 100644 index 0000000000..afaf360d37 --- /dev/null +++ b/plugins/wasm-go/extensions/request-size-limit/VERSION @@ -0,0 +1 @@ +1.0.0 \ No newline at end of file diff --git a/plugins/wasm-go/extensions/request-size-limit/go.mod b/plugins/wasm-go/extensions/request-size-limit/go.mod new file mode 100644 index 0000000000..5d99f71f9b --- /dev/null +++ b/plugins/wasm-go/extensions/request-size-limit/go.mod @@ -0,0 +1,19 @@ +module github.com/alibaba/higress/plugins/wasm-go/extensions/request-size-limit + +go 1.19 + +replace github.com/alibaba/higress/plugins/wasm-go => ../.. + +require ( + github.com/alibaba/higress/plugins/wasm-go v0.0.0 + github.com/tetratelabs/proxy-wasm-go-sdk v0.19.1-0.20220822060051-f9d179a57f8c + github.com/tidwall/gjson v1.14.3 +) + +require ( + github.com/google/uuid v1.3.0 // indirect + github.com/magefile/mage v1.14.0 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.0 // indirect + github.com/wasilibs/nottinygc v0.3.0 // indirect +) diff --git a/plugins/wasm-go/extensions/request-size-limit/go.sum b/plugins/wasm-go/extensions/request-size-limit/go.sum new file mode 100644 index 0000000000..843d9df25e --- /dev/null +++ b/plugins/wasm-go/extensions/request-size-limit/go.sum @@ -0,0 +1,18 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/magefile/mage v1.14.0 h1:6QDX3g6z1YvJ4olPhT1wksUcSa/V0a1B+pJb73fBjyo= +github.com/magefile/mage v1.14.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/tetratelabs/proxy-wasm-go-sdk v0.19.1-0.20220822060051-f9d179a57f8c h1:OCUFXVGixHLfNjg6/QYEhv+jHJ5mRGhpEUVFv9eWPJE= +github.com/tetratelabs/proxy-wasm-go-sdk v0.19.1-0.20220822060051-f9d179a57f8c/go.mod h1:5t/pWFNJ9eMyu/K/Z+OeGhDJ9sN9eCo8fc2pyM/Qjg4= +github.com/tidwall/gjson v1.14.3 h1:9jvXn7olKEHU1S9vwoMGliaT8jq1vJ7IH/n9zD9Dnlw= +github.com/tidwall/gjson v1.14.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/wasilibs/nottinygc v0.3.0 h1:0L1jsJ1MsyN5tdinmFbLfuEA0TnHRcqaBM9pDTJVJmU= +github.com/wasilibs/nottinygc v0.3.0/go.mod h1:oDcIotskuYNMpqMF23l7Z8uzD4TC0WXHK8jetlB3HIo= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/plugins/wasm-go/extensions/request-size-limit/main.go b/plugins/wasm-go/extensions/request-size-limit/main.go new file mode 100644 index 0000000000..f3a4227329 --- /dev/null +++ b/plugins/wasm-go/extensions/request-size-limit/main.go @@ -0,0 +1,71 @@ +// 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" + "github.com/alibaba/higress/plugins/wasm-go/pkg/wrapper" + "github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm" + "github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm/types" + "github.com/tidwall/gjson" + "regexp" + "strconv" + "strings" +) + +func main() { + wrapper.SetCtx( + "request-size-limit", + wrapper.ParseConfigBy(parseConfig), + wrapper.ProcessRequestBodyBy(onHttpRequestBody), + ) +} + +type RequestSizeLimitConfig struct { + requestSize int64 +} + +func parseConfig(json gjson.Result, config *RequestSizeLimitConfig, log wrapper.Log) error { + sizeStr := json.Get("requestSize").String() + sizeStr = strings.TrimSpace(sizeStr) + re := regexp.MustCompile("^([+\\-]?\\d+)([a-zA-Z]{0,2})$") + submatchs := re.FindStringSubmatch(sizeStr) + if len(submatchs) == 0 { + config.requestSize = 1024 * 1024 + return nil + } + amount, _ := strconv.ParseInt(submatchs[1], 10, 64) + unitStr := submatchs[2] + if len(unitStr) == 0 { + config.requestSize = amount + } else { + unitSizeMap := map[string]int64{ + "B": 1, + "KB": 1024, + "MB": 1024 * 1024, + "GB": 1024 * 1024 * 1024, + } + unit, ok := unitSizeMap[unitStr] + if !ok { + return errors.New("Invalid unit size: " + unitStr) + } + config.requestSize = amount * unit + } + return nil +} + +func onHttpRequestBody(ctx wrapper.HttpContext, config RequestSizeLimitConfig, body []byte, log wrapper.Log) types.Action { + if int64(len(body)) > config.requestSize { + proxywasm.SendHttpResponse(413, nil, []byte("The request body is too large"), -1) + return types.ActionContinue + } + return types.ActionContinue +}