From 834c6447ca15d9cff07817e803859a2a8b23a017 Mon Sep 17 00:00:00 2001 From: ginuerzh Date: Sun, 15 Jan 2023 17:44:12 +0800 Subject: [PATCH] add webapi for ingress --- api/config_ingress.go | 166 ++++++++++++++++++++++++++++++++++++++++++ api/service.go | 4 + api/swagger.yaml | 114 +++++++++++++++++++++++++++++ ingress/ingress.go | 2 +- 4 files changed, 285 insertions(+), 1 deletion(-) create mode 100644 api/config_ingress.go diff --git a/api/config_ingress.go b/api/config_ingress.go new file mode 100644 index 0000000..c619d21 --- /dev/null +++ b/api/config_ingress.go @@ -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 createIngressRequest +type createIngressRequest struct { + // in: body + Data config.IngressConfig `json:"data"` +} + +// successful operation. +// swagger:response createIngressResponse +type createIngressResponse struct { + Data Response +} + +func createIngress(ctx *gin.Context) { + // swagger:route POST /config/ingresses Ingress createIngressRequest + // + // Create a new ingress, the name of the ingress must be unique in ingress list. + // + // Security: + // basicAuth: [] + // + // Responses: + // 200: createIngressResponse + + var req createIngressRequest + ctx.ShouldBindJSON(&req.Data) + + if req.Data.Name == "" { + writeError(ctx, ErrInvalid) + return + } + + v := parsing.ParseIngress(&req.Data) + + if err := registry.IngressRegistry().Register(req.Data.Name, v); err != nil { + writeError(ctx, ErrDup) + return + } + + cfg := config.Global() + cfg.Ingresses = append(cfg.Ingresses, &req.Data) + config.SetGlobal(cfg) + + ctx.JSON(http.StatusOK, Response{ + Msg: "OK", + }) +} + +// swagger:parameters updateIngressRequest +type updateIngressRequest struct { + // in: path + // required: true + Ingress string `uri:"ingress" json:"ingress"` + // in: body + Data config.IngressConfig `json:"data"` +} + +// successful operation. +// swagger:response updateIngressResponse +type updateIngressResponse struct { + Data Response +} + +func updateIngress(ctx *gin.Context) { + // swagger:route PUT /config/ingresses/{ingress} Ingress updateIngressRequest + // + // Update ingress by name, the ingress must already exist. + // + // Security: + // basicAuth: [] + // + // Responses: + // 200: updateIngressResponse + + var req updateIngressRequest + ctx.ShouldBindUri(&req) + ctx.ShouldBindJSON(&req.Data) + + if !registry.IngressRegistry().IsRegistered(req.Ingress) { + writeError(ctx, ErrNotFound) + return + } + + req.Data.Name = req.Ingress + + v := parsing.ParseIngress(&req.Data) + + registry.IngressRegistry().Unregister(req.Ingress) + + if err := registry.IngressRegistry().Register(req.Ingress, v); err != nil { + writeError(ctx, ErrDup) + return + } + + cfg := config.Global() + for i := range cfg.Ingresses { + if cfg.Ingresses[i].Name == req.Ingress { + cfg.Ingresses[i] = &req.Data + break + } + } + config.SetGlobal(cfg) + + ctx.JSON(http.StatusOK, Response{ + Msg: "OK", + }) +} + +// swagger:parameters deleteIngressRequest +type deleteIngressRequest struct { + // in: path + // required: true + Ingress string `uri:"ingress" json:"ingress"` +} + +// successful operation. +// swagger:response deleteIngressResponse +type deleteIngressResponse struct { + Data Response +} + +func deleteIngress(ctx *gin.Context) { + // swagger:route DELETE /config/ingresses/{ingress} Ingress deleteIngressRequest + // + // Delete ingress by name. + // + // Security: + // basicAuth: [] + // + // Responses: + // 200: deleteIngressResponse + + var req deleteIngressRequest + ctx.ShouldBindUri(&req) + + if !registry.IngressRegistry().IsRegistered(req.Ingress) { + writeError(ctx, ErrNotFound) + return + } + registry.IngressRegistry().Unregister(req.Ingress) + + cfg := config.Global() + ingresses := cfg.Ingresses + cfg.Ingresses = nil + for _, s := range ingresses { + if s.Name == req.Ingress { + continue + } + cfg.Ingresses = append(cfg.Ingresses, s) + } + config.SetGlobal(cfg) + + ctx.JSON(http.StatusOK, Response{ + Msg: "OK", + }) +} diff --git a/api/service.go b/api/service.go index 07208a3..6802179 100644 --- a/api/service.go +++ b/api/service.go @@ -134,6 +134,10 @@ func registerConfig(config *gin.RouterGroup) { config.PUT("/hosts/:hosts", updateHosts) config.DELETE("/hosts/:hosts", deleteHosts) + config.POST("/ingresses", createIngress) + config.PUT("/ingresses/:ingress", updateIngress) + config.DELETE("/ingresses/:ingress", deleteIngress) + config.POST("/limiters", createLimiter) config.PUT("/limiters/:limiter", updateLimiter) config.DELETE("/limiters/:limiter", deleteLimiter) diff --git a/api/swagger.yaml b/api/swagger.yaml index b87e273..b2392f1 100644 --- a/api/swagger.yaml +++ b/api/swagger.yaml @@ -173,6 +173,11 @@ definitions: $ref: '#/definitions/HostsConfig' type: array x-go-name: Hosts + ingresses: + items: + $ref: '#/definitions/IngressConfig' + type: array + x-go-name: Ingresses limiters: items: $ref: '#/definitions/LimiterConfig' @@ -333,6 +338,9 @@ definitions: x-go-name: Chain chainGroup: $ref: '#/definitions/ChainGroupConfig' + ingress: + type: string + x-go-name: Ingress metadata: additionalProperties: {} type: object @@ -416,6 +424,36 @@ definitions: $ref: '#/definitions/Duration' type: object x-go-package: github.com/go-gost/x/config + IngressConfig: + properties: + file: + $ref: '#/definitions/FileLoader' + http: + $ref: '#/definitions/HTTPLoader' + name: + type: string + x-go-name: Name + redis: + $ref: '#/definitions/RedisLoader' + reload: + $ref: '#/definitions/Duration' + rules: + items: + $ref: '#/definitions/IngressRuleConfig' + type: array + x-go-name: Rules + type: object + x-go-package: github.com/go-gost/x/config + IngressRuleConfig: + properties: + endpoint: + type: string + x-go-name: Endpoint + hostname: + type: string + x-go-name: Hostname + type: object + x-go-package: github.com/go-gost/x/config LimiterConfig: properties: file: @@ -1243,6 +1281,64 @@ paths: summary: Update hosts by name, the hosts must already exist. tags: - Hosts + /config/ingresses: + post: + operationId: createIngressRequest + parameters: + - in: body + name: data + schema: + $ref: '#/definitions/IngressConfig' + x-go-name: Data + responses: + "200": + $ref: '#/responses/createIngressResponse' + security: + - basicAuth: + - '[]' + summary: Create a new ingress, the name of the ingress must be unique in ingress list. + tags: + - Ingress + /config/ingresses/{ingress}: + delete: + operationId: deleteIngressRequest + parameters: + - in: path + name: ingress + required: true + type: string + x-go-name: Ingress + responses: + "200": + $ref: '#/responses/deleteIngressResponse' + security: + - basicAuth: + - '[]' + summary: Delete ingress by name. + tags: + - Ingress + put: + operationId: updateIngressRequest + parameters: + - in: path + name: ingress + required: true + type: string + x-go-name: Ingress + - in: body + name: data + schema: + $ref: '#/definitions/IngressConfig' + x-go-name: Data + responses: + "200": + $ref: '#/responses/updateIngressResponse' + security: + - basicAuth: + - '[]' + summary: Update ingress by name, the ingress must already exist. + tags: + - Ingress /config/limiters: post: operationId: createLimiterRequest @@ -1520,6 +1616,12 @@ responses: Data: {} schema: $ref: '#/definitions/Response' + createIngressResponse: + description: successful operation. + headers: + Data: {} + schema: + $ref: '#/definitions/Response' createLimiterResponse: description: successful operation. headers: @@ -1586,6 +1688,12 @@ responses: Data: {} schema: $ref: '#/definitions/Response' + deleteIngressResponse: + description: successful operation. + headers: + Data: {} + schema: + $ref: '#/definitions/Response' deleteLimiterResponse: description: successful operation. headers: @@ -1664,6 +1772,12 @@ responses: Data: {} schema: $ref: '#/definitions/Response' + updateIngressResponse: + description: successful operation. + headers: + Data: {} + schema: + $ref: '#/definitions/Response' updateLimiterResponse: description: successful operation. headers: diff --git a/ingress/ingress.go b/ingress/ingress.go index 71bd788..238796a 100644 --- a/ingress/ingress.go +++ b/ingress/ingress.go @@ -127,7 +127,7 @@ func (ing *ingress) reload(ctx context.Context) error { } host := rule.Host if host[0] == '*' { - host = "." + host[1:] + host = host[1:] } rules[host] = rule }