add limiter web api

This commit is contained in:
ginuerzh 2022-09-06 15:38:45 +08:00
parent 779af72f7c
commit 54e1801e74
13 changed files with 330 additions and 48 deletions

View File

@ -24,7 +24,7 @@ type getConfigResponse struct {
}
func getConfig(ctx *gin.Context) {
// swagger:route GET /config ConfigManagement getConfigRequest
// swagger:route GET /config Config getConfigRequest
//
// Get current config.
//
@ -71,7 +71,7 @@ type saveConfigResponse struct {
}
func saveConfig(ctx *gin.Context) {
// swagger:route POST /config ConfigManagement saveConfigRequest
// swagger:route POST /config Config saveConfigRequest
//
// Save current config to file (gost.yaml or gost.json).
//

View File

@ -22,7 +22,7 @@ type createAdmissionResponse struct {
}
func createAdmission(ctx *gin.Context) {
// swagger:route POST /config/admissions ConfigManagement createAdmissionRequest
// swagger:route POST /config/admissions Admission createAdmissionRequest
//
// Create a new admission, the name of admission must be unique in admission list.
//
@ -72,7 +72,7 @@ type updateAdmissionResponse struct {
}
func updateAdmission(ctx *gin.Context) {
// swagger:route PUT /config/admissions/{admission} ConfigManagement updateAdmissionRequest
// swagger:route PUT /config/admissions/{admission} Admission updateAdmissionRequest
//
// Update admission by name, the admission must already exist.
//
@ -130,7 +130,7 @@ type deleteAdmissionResponse struct {
}
func deleteAdmission(ctx *gin.Context) {
// swagger:route DELETE /config/admissions/{admission} ConfigManagement deleteAdmissionRequest
// swagger:route DELETE /config/admissions/{admission} Admission deleteAdmissionRequest
//
// Delete admission by name.
//

View File

@ -22,7 +22,7 @@ type createAutherResponse struct {
}
func createAuther(ctx *gin.Context) {
// swagger:route POST /config/authers ConfigManagement createAutherRequest
// swagger:route POST /config/authers Auther createAutherRequest
//
// Create a new auther, the name of the auther must be unique in auther list.
//
@ -71,7 +71,7 @@ type updateAutherResponse struct {
}
func updateAuther(ctx *gin.Context) {
// swagger:route PUT /config/authers/{auther} ConfigManagement updateAutherRequest
// swagger:route PUT /config/authers/{auther} Auther updateAutherRequest
//
// Update auther by name, the auther must already exist.
//
@ -128,7 +128,7 @@ type deleteAutherResponse struct {
}
func deleteAuther(ctx *gin.Context) {
// swagger:route DELETE /config/authers/{auther} ConfigManagement deleteAutherRequest
// swagger:route DELETE /config/authers/{auther} Auther deleteAutherRequest
//
// Delete auther by name.
//

View File

@ -22,7 +22,7 @@ type createBypassResponse struct {
}
func createBypass(ctx *gin.Context) {
// swagger:route POST /config/bypasses ConfigManagement createBypassRequest
// swagger:route POST /config/bypasses Bypass createBypassRequest
//
// Create a new bypass, the name of bypass must be unique in bypass list.
//
@ -72,7 +72,7 @@ type updateBypassResponse struct {
}
func updateBypass(ctx *gin.Context) {
// swagger:route PUT /config/bypasses/{bypass} ConfigManagement updateBypassRequest
// swagger:route PUT /config/bypasses/{bypass} Bypass updateBypassRequest
//
// Update bypass by name, the bypass must already exist.
//
@ -130,7 +130,7 @@ type deleteBypassResponse struct {
}
func deleteBypass(ctx *gin.Context) {
// swagger:route DELETE /config/bypasses/{bypass} ConfigManagement deleteBypassRequest
// swagger:route DELETE /config/bypasses/{bypass} Bypass deleteBypassRequest
//
// Delete bypass by name.
//

View File

@ -22,7 +22,7 @@ type createChainResponse struct {
}
func createChain(ctx *gin.Context) {
// swagger:route POST /config/chains ConfigManagement createChainRequest
// swagger:route POST /config/chains Chain createChainRequest
//
// Create a new chain, the name of chain must be unique in chain list.
//
@ -77,7 +77,7 @@ type updateChainResponse struct {
}
func updateChain(ctx *gin.Context) {
// swagger:route PUT /config/chains/{chain} ConfigManagement updateChainRequest
// swagger:route PUT /config/chains/{chain} Chain updateChainRequest
//
// Update chain by name, the chain must already exist.
//
@ -139,7 +139,7 @@ type deleteChainResponse struct {
}
func deleteChain(ctx *gin.Context) {
// swagger:route DELETE /config/chains/{chain} ConfigManagement deleteChainRequest
// swagger:route DELETE /config/chains/{chain} Chain deleteChainRequest
//
// Delete chain by name.
//

View File

@ -22,7 +22,7 @@ type createHostsesponse struct {
}
func createHosts(ctx *gin.Context) {
// swagger:route POST /config/hosts ConfigManagement createHostsRequest
// swagger:route POST /config/hosts Hosts createHostsRequest
//
// Create a new hosts, the name of the hosts must be unique in hosts list.
//
@ -72,7 +72,7 @@ type updateHostsResponse struct {
}
func updateHosts(ctx *gin.Context) {
// swagger:route PUT /config/hosts/{hosts} ConfigManagement updateHostsRequest
// swagger:route PUT /config/hosts/{hosts} Hosts updateHostsRequest
//
// Update hosts by name, the hosts must already exist.
//
@ -130,7 +130,7 @@ type deleteHostsResponse struct {
}
func deleteHosts(ctx *gin.Context) {
// swagger:route DELETE /config/hosts/{hosts} ConfigManagement deleteHostsRequest
// swagger:route DELETE /config/hosts/{hosts} Hosts deleteHostsRequest
//
// Delete hosts by name.
//

166
api/config_limiter.go Normal file
View File

@ -0,0 +1,166 @@
package api
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/go-gost/x/config"
"github.com/go-gost/x/config/parsing"
"github.com/go-gost/x/registry"
)
// swagger:parameters createLimiterRequest
type createLimiterRequest struct {
// in: body
Data config.LimiterConfig `json:"data"`
}
// successful operation.
// swagger:response createLimiterResponse
type createLimiterResponse struct {
Data Response
}
func createLimiter(ctx *gin.Context) {
// swagger:route POST /config/limiters Limiter createLimiterRequest
//
// Create a new limiter, the name of limiter must be unique in limiter list.
//
// Security:
// basicAuth: []
//
// Responses:
// 200: createLimiterResponse
var req createLimiterRequest
ctx.ShouldBindJSON(&req.Data)
if req.Data.Name == "" {
writeError(ctx, ErrInvalid)
return
}
v := parsing.ParseRateLimiter(&req.Data)
if err := registry.RateLimiterRegistry().Register(req.Data.Name, v); err != nil {
writeError(ctx, ErrDup)
return
}
cfg := config.Global()
cfg.Limiters = append(cfg.Limiters, &req.Data)
config.SetGlobal(cfg)
ctx.JSON(http.StatusOK, Response{
Msg: "OK",
})
}
// swagger:parameters updateLimiterRequest
type updateLimiterRequest struct {
// in: path
// required: true
Limiter string `uri:"limiter" json:"limiter"`
// in: body
Data config.LimiterConfig `json:"data"`
}
// successful operation.
// swagger:response updateLimiterResponse
type updateLimiterResponse struct {
Data Response
}
func updateLimiter(ctx *gin.Context) {
// swagger:route PUT /config/limiters/{limiter} Limiter updateLimiterRequest
//
// Update limiter by name, the limiter must already exist.
//
// Security:
// basicAuth: []
//
// Responses:
// 200: updateLimiterResponse
var req updateLimiterRequest
ctx.ShouldBindUri(&req)
ctx.ShouldBindJSON(&req.Data)
if !registry.RateLimiterRegistry().IsRegistered(req.Limiter) {
writeError(ctx, ErrNotFound)
return
}
req.Data.Name = req.Limiter
v := parsing.ParseRateLimiter(&req.Data)
registry.RateLimiterRegistry().Unregister(req.Limiter)
if err := registry.RateLimiterRegistry().Register(req.Limiter, v); err != nil {
writeError(ctx, ErrDup)
return
}
cfg := config.Global()
for i := range cfg.Limiters {
if cfg.Limiters[i].Name == req.Limiter {
cfg.Limiters[i] = &req.Data
break
}
}
config.SetGlobal(cfg)
ctx.JSON(http.StatusOK, Response{
Msg: "OK",
})
}
// swagger:parameters deleteLimiterRequest
type deleteLimiterRequest struct {
// in: path
// required: true
Limiter string `uri:"Limiter" json:"Limiter"`
}
// successful operation.
// swagger:response deleteLimiterResponse
type deleteLimiterResponse struct {
Data Response
}
func deleteLimiter(ctx *gin.Context) {
// swagger:route DELETE /config/limiters/{limiter} Limiter deleteLimiterRequest
//
// Delete limiter by name.
//
// Security:
// basicAuth: []
//
// Responses:
// 200: deleteLimiterResponse
var req deleteLimiterRequest
ctx.ShouldBindUri(&req)
if !registry.RateLimiterRegistry().IsRegistered(req.Limiter) {
writeError(ctx, ErrNotFound)
return
}
registry.RateLimiterRegistry().Unregister(req.Limiter)
cfg := config.Global()
limiteres := cfg.Limiters
cfg.Limiters = nil
for _, s := range limiteres {
if s.Name == req.Limiter {
continue
}
cfg.Limiters = append(cfg.Limiters, s)
}
config.SetGlobal(cfg)
ctx.JSON(http.StatusOK, Response{
Msg: "OK",
})
}

View File

@ -22,7 +22,7 @@ type createResolverResponse struct {
}
func createResolver(ctx *gin.Context) {
// swagger:route POST /config/resolvers ConfigManagement createResolverRequest
// swagger:route POST /config/resolvers Resolver createResolverRequest
//
// Create a new resolver, the name of the resolver must be unique in resolver list.
//
@ -76,7 +76,7 @@ type updateResolverResponse struct {
}
func updateResolver(ctx *gin.Context) {
// swagger:route PUT /config/resolvers/{resolver} ConfigManagement updateResolverRequest
// swagger:route PUT /config/resolvers/{resolver} Resolver updateResolverRequest
//
// Update resolver by name, the resolver must already exist.
//
@ -138,7 +138,7 @@ type deleteResolverResponse struct {
}
func deleteResolver(ctx *gin.Context) {
// swagger:route DELETE /config/resolvers/{resolver} ConfigManagement deleteResolverRequest
// swagger:route DELETE /config/resolvers/{resolver} Resolver deleteResolverRequest
//
// Delete resolver by name.
//

View File

@ -22,7 +22,7 @@ type createServiceResponse struct {
}
func createService(ctx *gin.Context) {
// swagger:route POST /config/services ConfigManagement createServiceRequest
// swagger:route POST /config/services Service createServiceRequest
//
// Create a new service, the name of the service must be unique in service list.
//
@ -84,7 +84,7 @@ type updateServiceResponse struct {
}
func updateService(ctx *gin.Context) {
// swagger:route PUT /config/services/{service} ConfigManagement updateServiceRequest
// swagger:route PUT /config/services/{service} Service updateServiceRequest
//
// Update service by name, the service must already exist.
//
@ -151,7 +151,7 @@ type deleteServiceResponse struct {
}
func deleteService(ctx *gin.Context) {
// swagger:route DELETE /config/services/{service} ConfigManagement deleteServiceRequest
// swagger:route DELETE /config/services/{service} Service deleteServiceRequest
//
// Delete service by name.
//

View File

@ -129,4 +129,9 @@ func registerConfig(config *gin.RouterGroup) {
config.POST("/hosts", createHosts)
config.PUT("/hosts/:hosts", updateHosts)
config.DELETE("/hosts/:hosts", deleteHosts)
config.POST("/limiters", createLimiter)
config.PUT("/limiters/:limiter", updateLimiter)
config.DELETE("/limiters/:limiter", deleteLimiter)
}

View File

@ -156,6 +156,11 @@ definitions:
$ref: '#/definitions/HostsConfig'
type: array
x-go-name: Hosts
limiters:
items:
$ref: '#/definitions/LimiterConfig'
type: array
x-go-name: Limiters
log:
$ref: '#/definitions/LogConfig'
metrics:
@ -351,6 +356,15 @@ definitions:
$ref: '#/definitions/Duration'
type: object
x-go-package: github.com/go-gost/x/config
LimiterConfig:
properties:
name:
type: string
x-go-name: Name
rate:
$ref: '#/definitions/RateLimiterConfig'
type: object
x-go-package: github.com/go-gost/x/config
ListenerConfig:
properties:
auth:
@ -469,6 +483,21 @@ definitions:
x-go-name: Addr
type: object
x-go-package: github.com/go-gost/x/config
RateLimiterConfig:
properties:
file:
$ref: '#/definitions/FileLoader'
limits:
items:
type: string
type: array
x-go-name: Limits
redis:
$ref: '#/definitions/RedisLoader'
reload:
$ref: '#/definitions/Duration'
type: object
x-go-package: github.com/go-gost/x/config
RecorderConfig:
properties:
file:
@ -597,6 +626,9 @@ definitions:
interface:
type: string
x-go-name: Interface
limiter:
type: string
x-go-name: Limiter
listener:
$ref: '#/definitions/ListenerConfig'
metadata:
@ -674,7 +706,7 @@ paths:
- '[]'
summary: Get current config.
tags:
- ConfigManagement
- Config
post:
operationId: saveConfigRequest
parameters:
@ -691,7 +723,7 @@ paths:
- '[]'
summary: Save current config to file (gost.yaml or gost.json).
tags:
- ConfigManagement
- Config
/config/admissions:
post:
operationId: createAdmissionRequest
@ -709,7 +741,7 @@ paths:
- '[]'
summary: Create a new admission, the name of admission must be unique in admission list.
tags:
- ConfigManagement
- Admission
/config/admissions/{admission}:
delete:
operationId: deleteAdmissionRequest
@ -727,7 +759,7 @@ paths:
- '[]'
summary: Delete admission by name.
tags:
- ConfigManagement
- Admission
put:
operationId: updateAdmissionRequest
parameters:
@ -749,7 +781,7 @@ paths:
- '[]'
summary: Update admission by name, the admission must already exist.
tags:
- ConfigManagement
- Admission
/config/authers:
post:
operationId: createAutherRequest
@ -767,7 +799,7 @@ paths:
- '[]'
summary: Create a new auther, the name of the auther must be unique in auther list.
tags:
- ConfigManagement
- Auther
/config/authers/{auther}:
delete:
operationId: deleteAutherRequest
@ -785,7 +817,7 @@ paths:
- '[]'
summary: Delete auther by name.
tags:
- ConfigManagement
- Auther
put:
operationId: updateAutherRequest
parameters:
@ -807,7 +839,7 @@ paths:
- '[]'
summary: Update auther by name, the auther must already exist.
tags:
- ConfigManagement
- Auther
/config/bypasses:
post:
operationId: createBypassRequest
@ -825,7 +857,7 @@ paths:
- '[]'
summary: Create a new bypass, the name of bypass must be unique in bypass list.
tags:
- ConfigManagement
- Bypass
/config/bypasses/{bypass}:
delete:
operationId: deleteBypassRequest
@ -843,7 +875,7 @@ paths:
- '[]'
summary: Delete bypass by name.
tags:
- ConfigManagement
- Bypass
put:
operationId: updateBypassRequest
parameters:
@ -865,7 +897,7 @@ paths:
- '[]'
summary: Update bypass by name, the bypass must already exist.
tags:
- ConfigManagement
- Bypass
/config/chains:
post:
operationId: createChainRequest
@ -883,7 +915,7 @@ paths:
- '[]'
summary: Create a new chain, the name of chain must be unique in chain list.
tags:
- ConfigManagement
- Chain
/config/chains/{chain}:
delete:
operationId: deleteChainRequest
@ -901,7 +933,7 @@ paths:
- '[]'
summary: Delete chain by name.
tags:
- ConfigManagement
- Chain
put:
operationId: updateChainRequest
parameters:
@ -923,7 +955,7 @@ paths:
- '[]'
summary: Update chain by name, the chain must already exist.
tags:
- ConfigManagement
- Chain
/config/hosts:
post:
operationId: createHostsRequest
@ -941,7 +973,7 @@ paths:
- '[]'
summary: Create a new hosts, the name of the hosts must be unique in hosts list.
tags:
- ConfigManagement
- Hosts
/config/hosts/{hosts}:
delete:
operationId: deleteHostsRequest
@ -959,7 +991,7 @@ paths:
- '[]'
summary: Delete hosts by name.
tags:
- ConfigManagement
- Hosts
put:
operationId: updateHostsRequest
parameters:
@ -981,7 +1013,64 @@ paths:
- '[]'
summary: Update hosts by name, the hosts must already exist.
tags:
- ConfigManagement
- Hosts
/config/limiters:
post:
operationId: createLimiterRequest
parameters:
- in: body
name: data
schema:
$ref: '#/definitions/LimiterConfig'
x-go-name: Data
responses:
"200":
$ref: '#/responses/createLimiterResponse'
security:
- basicAuth:
- '[]'
summary: Create a new limiter, the name of limiter must be unique in limiter list.
tags:
- Limiter
/config/limiters/{limiter}:
delete:
operationId: deleteLimiterRequest
parameters:
- in: path
name: Limiter
required: true
type: string
responses:
"200":
$ref: '#/responses/deleteLimiterResponse'
security:
- basicAuth:
- '[]'
summary: Delete limiter by name.
tags:
- Limiter
put:
operationId: updateLimiterRequest
parameters:
- in: path
name: limiter
required: true
type: string
x-go-name: Limiter
- in: body
name: data
schema:
$ref: '#/definitions/LimiterConfig'
x-go-name: Data
responses:
"200":
$ref: '#/responses/updateLimiterResponse'
security:
- basicAuth:
- '[]'
summary: Update limiter by name, the limiter must already exist.
tags:
- Limiter
/config/resolvers:
post:
operationId: createResolverRequest
@ -999,7 +1088,7 @@ paths:
- '[]'
summary: Create a new resolver, the name of the resolver must be unique in resolver list.
tags:
- ConfigManagement
- Resolver
/config/resolvers/{resolver}:
delete:
operationId: deleteResolverRequest
@ -1017,7 +1106,7 @@ paths:
- '[]'
summary: Delete resolver by name.
tags:
- ConfigManagement
- Resolver
put:
operationId: updateResolverRequest
parameters:
@ -1039,7 +1128,7 @@ paths:
- '[]'
summary: Update resolver by name, the resolver must already exist.
tags:
- ConfigManagement
- Resolver
/config/services:
post:
operationId: createServiceRequest
@ -1057,7 +1146,7 @@ paths:
- '[]'
summary: Create a new service, the name of the service must be unique in service list.
tags:
- ConfigManagement
- Service
/config/services/{service}:
delete:
operationId: deleteServiceRequest
@ -1075,7 +1164,7 @@ paths:
- '[]'
summary: Delete service by name.
tags:
- ConfigManagement
- Service
put:
operationId: updateServiceRequest
parameters:
@ -1097,7 +1186,7 @@ paths:
- '[]'
summary: Update service by name, the service must already exist.
tags:
- ConfigManagement
- Service
produces:
- application/json
responses:
@ -1131,6 +1220,12 @@ responses:
Data: {}
schema:
$ref: '#/definitions/Response'
createLimiterResponse:
description: successful operation.
headers:
Data: {}
schema:
$ref: '#/definitions/Response'
createResolverResponse:
description: successful operation.
headers:
@ -1173,6 +1268,12 @@ responses:
Data: {}
schema:
$ref: '#/definitions/Response'
deleteLimiterResponse:
description: successful operation.
headers:
Data: {}
schema:
$ref: '#/definitions/Response'
deleteResolverResponse:
description: successful operation.
headers:
@ -1227,6 +1328,12 @@ responses:
Data: {}
schema:
$ref: '#/definitions/Response'
updateLimiterResponse:
description: successful operation.
headers:
Data: {}
schema:
$ref: '#/definitions/Response'
updateResolverResponse:
description: successful operation.
headers:

4
go.mod
View File

@ -3,7 +3,7 @@ module github.com/go-gost/x
go 1.18
require (
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d
github.com/gin-contrib/cors v1.3.1
github.com/gin-gonic/gin v1.7.7
@ -33,7 +33,7 @@ require (
golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8
golang.org/x/net v0.0.0-20220812174116-3211cb980234
golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2
golang.org/x/time v0.0.0-20191024005414-555d28b269f0
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9
golang.zx2c4.com/wireguard v0.0.0-20220703234212-c31a7b1ab478
google.golang.org/grpc v1.49.0
google.golang.org/protobuf v1.27.1

4
go.sum
View File

@ -47,6 +47,8 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc=
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ=
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
@ -593,6 +595,8 @@ golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 h1:ftMN5LMiBFjbzleLqtoBZk7KdJwhuybIU+FckUHgoyQ=
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=