From 18792a395ce6dadfe2f508a26d303d2a6480b833 Mon Sep 17 00:00:00 2001 From: yanghuanglin Date: Thu, 11 Jan 2024 13:11:12 +0800 Subject: [PATCH] support update proxies --- assets/static/js/index-client-info.js | 11 +- assets/static/js/index-proxy-list.js | 26 +++-- assets/static/js/index.js | 1 + assets/static/js/json-process.js | 7 +- assets/static/js/toml.js | 54 ++++++---- assets/templates/index.html | 2 +- go.mod | 1 - pkg/server/controller/controller.go | 148 ++------------------------ pkg/server/controller/register.go | 2 - pkg/server/controller/utils.go | 40 ------- pkg/server/controller/variables.go | 53 +-------- 11 files changed, 69 insertions(+), 276 deletions(-) diff --git a/assets/static/js/index-client-info.js b/assets/static/js/index-client-info.js index f0a7d66..ee47d9a 100644 --- a/assets/static/js/index-client-info.js +++ b/assets/static/js/index-client-info.js @@ -17,20 +17,19 @@ var loadClientInfo = (function ($) { }).done(function (result) { if (result.success) { var proxies = []; - result.data.proxies.forEach(function (proxy){ + result.data.proxies.forEach(function (proxy) { var items = flatJSON(proxy.ProxyConfigurer); proxies.push(expandJSON(items)) }) var visitors = []; - result.data.visitors.forEach(function (visitor){ + result.data.visitors.forEach(function (visitor) { var items = flatJSON(visitor.VisitorConfigurer); visitors.push(expandJSON(items)) }) - var newD = $.extend({},result.data,true); - newD.proxies = proxies; - newD.visitors = visitors; - console.log(TOML.stringify(newD)) + window.clientConfig = $.extend(true, {}, result.data); + window.clientConfig.proxies = proxies; + window.clientConfig.visitors = visitors; renderClientInfo(result.data); } else { layui.layer.msg(result.message); diff --git a/assets/static/js/index-proxy-list.js b/assets/static/js/index-proxy-list.js index bc5a988..339437b 100644 --- a/assets/static/js/index-proxy-list.js +++ b/assets/static/js/index-proxy-list.js @@ -219,8 +219,8 @@ var loadProxyInfo = (function ($) { }, success: function (layero, index, that) { //get and set old name for update form - var oldNameKey = layero.find('#oldName').attr('name'); - basicData[oldNameKey] = basicData.name; + var originalNameKey = layero.find('#originalNameKey').attr('name'); + basicData[originalNameKey] = basicData.name; layui.form.val('addProxyForm', flatJSON(basicData)); proxyPopupSuccess(); } @@ -259,22 +259,26 @@ var loadProxyInfo = (function ($) { */ function addOrUpdate(data, index, update) { var loading = layui.layer.load(); - var url = ''; + var originalNameKey = $('#originalNameKey').attr('name'); + var proxies = clientConfig.proxies; if (update) { - url = '/update?type=' + currentProxyType; + for (var i = 0; i < proxies.length; i++) { + if (data[originalNameKey] === proxies[i].name) { + delete data[originalNameKey]; + proxies[i] = expandJSON(data); + } + } } else { - url = '/add?type=' + currentProxyType; + proxies.push(expandJSON(data)); } - var tomlStr = TOML.stringify(expandJSON(data)); - - //todo get all proxy and replace or add a new proxy in it + var tomlStr = TOML.stringify(clientConfig); $.ajax({ - url: url, + url: '/update', type: 'post', - contentType: 'application/json', - data: JSON.stringify(expandJSON(data)), + contentType: 'text/plain', + data: tomlStr, success: function (result) { if (result.success) { layui.layer.close(index); diff --git a/assets/static/js/index.js b/assets/static/js/index.js index 2c3fd96..5d68fef 100644 --- a/assets/static/js/index.js +++ b/assets/static/js/index.js @@ -1,3 +1,4 @@ +window.clientConfig = {}; (function ($) { $(function () { function init() { diff --git a/assets/static/js/json-process.js b/assets/static/js/json-process.js index 854d083..0fa4176 100644 --- a/assets/static/js/json-process.js +++ b/assets/static/js/json-process.js @@ -1,4 +1,4 @@ -(function (){ +(function () { //param names in Basic tab var basicParams = [ { @@ -24,10 +24,10 @@ defaultValue: '-' }, { name: 'transport.useEncryption', - defaultValue: 'true', + defaultValue: 'false', }, { name: 'transport.useCompression', - defaultValue: 'true', + defaultValue: 'false', } ]; var mapParams = [{ @@ -177,6 +177,7 @@ return flat(obj); } + window.basicParams = basicParams; window.expandJSONKeys = expandJSONKeys; window.expandJSON = expandJSON; window.flatJSON = flatJSON; diff --git a/assets/static/js/toml.js b/assets/static/js/toml.js index f8d9f62..a42f291 100644 --- a/assets/static/js/toml.js +++ b/assets/static/js/toml.js @@ -336,7 +336,13 @@ module.exports = Parser module.exports = stringify module.exports.value = stringifyInline -function stringify(obj, separator) { +/** + * + * @param obj json object + * @param options {{separator: string, indentSize: number}} options + * @returns {string|null} + */ +function stringify(obj, options) { if (obj === null) throw typeError('null') if (obj === void (0)) throw typeError('undefined') if (typeof obj !== 'object') throw typeError(typeof obj) @@ -345,7 +351,19 @@ function stringify(obj, separator) { if (obj == null) return null const type = tomlType(obj) if (type !== 'table') throw typeError(type) - return stringifyObject('', '', obj, separator) + var defaultOptions = { + separator: '', + indentSize: 0, + } + if (options == null) + options = defaultOptions + else + options = { + separator: options.separator || defaultOptions.separator, + indentSize: options.indentSize || defaultOptions.indentSize, + } + + return stringifyObject('', '', obj, options) } function typeError (type) { @@ -371,7 +389,7 @@ function toJSON (obj) { return nobj } -function stringifyObject (prefix, indent, obj, separator) { +function stringifyObject (prefix, indent, obj, options) { obj = toJSON(obj) let inlineKeys let complexKeys @@ -382,13 +400,13 @@ function stringifyObject (prefix, indent, obj, separator) { inlineKeys.forEach(key => { var type = tomlType(obj[key]) if (type !== 'undefined' && type !== 'null') { - result.push(inlineIndent + stringifyKey(key) + ' = ' + stringifyAnyInline(obj[key], true, separator)) + result.push(inlineIndent + stringifyKey(key) + ' = ' + stringifyAnyInline(obj[key], true, options)) } }) if (result.length > 0) result.push('') - const complexIndent = prefix && inlineKeys.length > 0 ? indent + ' ' : '' + const complexIndent = prefix && inlineKeys.length > 0 ? (indent + ''.padStart(options.indentSize, ' ')) : '' complexKeys.forEach(key => { - result.push(stringifyComplex(prefix, complexIndent, key, obj[key], separator)) + result.push(stringifyComplex(prefix, complexIndent, key, obj[key], options)) }) return result.join('\n') } @@ -479,7 +497,7 @@ function stringifyMultilineString (str) { return '"""\n' + escaped + '"""' } -function stringifyAnyInline (value, multilineOk, separator) { +function stringifyAnyInline (value, multilineOk, options) { let type = tomlType(value) if (type === 'string') { if (multilineOk && /\n/.test(value)) { @@ -488,10 +506,10 @@ function stringifyAnyInline (value, multilineOk, separator) { type = 'string-literal' } } - return stringifyInline(value, type, separator) + return stringifyInline(value, type, options) } -function stringifyInline (value, type, separator) { +function stringifyInline (value, type, options) { /* istanbul ignore if */ if (!type) type = tomlType(value) switch (type) { @@ -502,9 +520,9 @@ function stringifyInline (value, type, separator) { case 'string-literal': return stringifyLiteralString(value) case 'integer': - return stringifyInteger(value, separator) + return stringifyInteger(value, options.separator) case 'float': - return stringifyFloat(value, separator) + return stringifyFloat(value, options.separator) case 'boolean': return stringifyBoolean(value) case 'datetime': @@ -569,19 +587,19 @@ function stringifyInlineTable (value) { return '{ ' + result.join(', ') + (result.length > 0 ? ' ' : '') + '}' } -function stringifyComplex (prefix, indent, key, value, separator) { +function stringifyComplex (prefix, indent, key, value, options) { const valueType = tomlType(value) /* istanbul ignore else */ if (valueType === 'array') { - return stringifyArrayOfTables(prefix, indent, key, value, separator) + return stringifyArrayOfTables(prefix, indent, key, value, options) } else if (valueType === 'table') { - return stringifyComplexTable(prefix, indent, key, value, separator) + return stringifyComplexTable(prefix, indent, key, value, options) } else { throw typeError(valueType) } } -function stringifyArrayOfTables (prefix, indent, key, values, separator) { +function stringifyArrayOfTables (prefix, indent, key, values, options) { values = toJSON(values) const firstValueType = tomlType(values[0]) /* istanbul ignore if */ @@ -591,18 +609,18 @@ function stringifyArrayOfTables (prefix, indent, key, values, separator) { values.forEach(table => { if (result.length > 0) result += '\n' result += indent + '[[' + fullKey + ']]\n' - result += stringifyObject(fullKey + '.', indent, table, separator) + result += stringifyObject(fullKey + '.', indent, table, options) }) return result } -function stringifyComplexTable (prefix, indent, key, value, separator) { +function stringifyComplexTable (prefix, indent, key, value, options) { const fullKey = prefix + stringifyKey(key) let result = '' if (getInlineKeys(value).length > 0) { result += indent + '[' + fullKey + ']\n' } - return result + stringifyObject(fullKey + '.', indent, value, separator) + return result + stringifyObject(fullKey + '.', indent, value, options) } },{}],10:[function(require,module,exports){ diff --git a/assets/templates/index.html b/assets/templates/index.html index bf36ce7..5714c42 100644 --- a/assets/templates/index.html +++ b/assets/templates/index.html @@ -155,7 +155,7 @@
- +
diff --git a/go.mod b/go.mod index e5aadb5..b82d355 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,6 @@ require ( github.com/gin-contrib/sessions v0.0.5 github.com/gin-gonic/gin v1.9.1 github.com/spf13/cobra v1.7.0 - github.com/vaughan0/go-ini v0.0.0-20130923145212-a98ad7ee00ec golang.org/x/text v0.11.0 ) diff --git a/pkg/server/controller/controller.go b/pkg/server/controller/controller.go index 2fbfa7f..7842c74 100644 --- a/pkg/server/controller/controller.go +++ b/pkg/server/controller/controller.go @@ -3,11 +3,8 @@ package controller import ( "bytes" "fmt" - v1 "github.com/fatedier/frp/pkg/config/v1" ginI18n "github.com/gin-contrib/i18n" "github.com/gin-gonic/gin" - "github.com/pelletier/go-toml/v2" - "github.com/vaughan0/go-ini" "log" "net/http" ) @@ -59,7 +56,7 @@ func (c *HandleController) MakeIndexFunc() func(context *gin.Context) { return func(context *gin.Context) { context.HTML(http.StatusOK, "index.html", gin.H{ "version": c.Version, - "OldNameKey": OldNameKey, + "OriginalNameKey": OriginalNameKey, "showExit": trimString(c.CommonInfo.AdminUser) != "" && trimString(c.CommonInfo.AdminPwd) != "", "FrpcPanel": ginI18n.MustGetMessage(context, "Frpc Panel"), "ClientInfo": ginI18n.MustGetMessage(context, "Client Info"), @@ -143,66 +140,8 @@ func (c *HandleController) MakeLangFunc() func(context *gin.Context) { } } -func (c *HandleController) MakeAddProxyFunc() func(context *gin.Context) { - return func(context *gin.Context) { - proxy := ini.Section{} - - response := OperationResponse{ - Success: true, - Code: Success, - Message: "proxy add success", - } - - err := context.BindJSON(&proxy) - if err != nil { - response.Success = false - response.Code = ParamError - response.Message = fmt.Sprintf("proxy add failed, param error : %v", err) - log.Printf(response.Message) - context.JSON(http.StatusOK, &response) - return - } - - name := proxy[NameKey] - - if trimString(name) == "" { - response.Success = false - response.Code = ParamError - response.Message = fmt.Sprintf("proxy add failed, proxy name invalid") - log.Printf(response.Message) - context.JSON(http.StatusOK, &response) - return - } - - if _, exist := clientProxies[name]; exist { - response.Success = false - response.Code = ProxyExist - response.Message = fmt.Sprintf("proxy add failed, proxy exist") - log.Printf(response.Message) - context.JSON(http.StatusOK, &response) - return - } - - clientProxies[name] = proxy - - res := c.UpdateFrpcConfig() - if !res.Success { - response.Success = false - response.Code = res.Code - response.Message = fmt.Sprintf("proxy add failed, error : %v", res.Message) - log.Printf(response.Message) - context.JSON(http.StatusOK, &response) - return - } - - context.JSON(0, &response) - } -} - func (c *HandleController) MakeUpdateProxyFunc() func(context *gin.Context) { return func(context *gin.Context) { - proxyType := context.Query("type") - proxy := v1.NewProxyConfigurerByType(v1.ProxyType(proxyType)) response := OperationResponse{ Success: true, @@ -210,27 +149,15 @@ func (c *HandleController) MakeUpdateProxyFunc() func(context *gin.Context) { Message: "proxy update success", } - var b = make([]byte, context.Request.ContentLength) - context.Request.Body.Read(b) - var s = string(b) - log.Print(s) - toml.Unmarshal(b, &proxy) + data, _ := context.GetRawData() - err := context.BindJSON(&proxy) - if err != nil { - response.Success = false - response.Code = ParamError - response.Message = fmt.Sprintf("update failed, param error : %v", err) - log.Printf(response.Message) - context.JSON(http.StatusOK, &response) - return - } + c.UpdateFrpcConfig(data) context.JSON(200, &response) //proxy.GetBaseConfig() // - //oldName := proxy[OldNameKey] + //oldName := proxy[OriginalNameKey] //name := proxy[NameKey] // //if trimString(oldName) == "" || trimString(name) == "" { @@ -279,69 +206,6 @@ func (c *HandleController) MakeUpdateProxyFunc() func(context *gin.Context) { } } -func (c *HandleController) MakeRemoveProxyFunc() func(context *gin.Context) { - return func(context *gin.Context) { - var proxies []ini.Section - - response := OperationResponse{ - Success: true, - Code: Success, - Message: "proxy remove success", - } - - err := context.BindJSON(&proxies) - if err != nil { - response.Success = false - response.Code = ParamError - response.Message = fmt.Sprintf("proxy remove failed, param error : %v", err) - log.Printf(response.Message) - context.JSON(http.StatusOK, &response) - return - } - - tempProxyNames := make([]string, len(proxies)) - for index, proxy := range proxies { - name := proxy[NameKey] - - if trimString(name) == "" { - response.Success = false - response.Code = ParamError - response.Message = fmt.Sprintf("proxy remove failed, proxy %v name invalid", name) - log.Printf(response.Message) - context.JSON(http.StatusOK, &response) - return - } - - if _, exist := clientProxies[name]; !exist { - response.Success = false - response.Code = ProxyExist - response.Message = fmt.Sprintf("proxy remove failed, proxy %v not exist", name) - log.Printf(response.Message) - context.JSON(http.StatusOK, &response) - return - } - - tempProxyNames[index] = name - } - - for _, name := range tempProxyNames { - delete(clientProxies, name) - } - - res := c.UpdateFrpcConfig() - if !res.Success { - response.Success = false - response.Code = res.Code - response.Message = fmt.Sprintf("proxy remvoe failed, error : %v", res.Message) - log.Printf(response.Message) - context.JSON(http.StatusOK, &response) - return - } - - context.JSON(http.StatusOK, &response) - } -} - func (c *HandleController) MakeProxyFunc() func(context *gin.Context) { return func(context *gin.Context) { res := ProxyResponse{} @@ -378,11 +242,11 @@ func (c *HandleController) MakeProxyFunc() func(context *gin.Context) { } } -func (c *HandleController) UpdateFrpcConfig() ProxyResponse { +func (c *HandleController) UpdateFrpcConfig(tomlStr []byte) ProxyResponse { res := ProxyResponse{} requestUrl := c.buildRequestUrl("/api/config") - request, _ := http.NewRequest("PUT", requestUrl, bytes.NewReader(serializeSections())) + request, _ := http.NewRequest("PUT", requestUrl, bytes.NewReader(tomlStr)) response, err := c.getClientResponse(request, c.buildClient()) if err != nil { diff --git a/pkg/server/controller/register.go b/pkg/server/controller/register.go index 677e73f..d3494cf 100644 --- a/pkg/server/controller/register.go +++ b/pkg/server/controller/register.go @@ -39,8 +39,6 @@ func (c *HandleController) Register(rootDir string, engine *gin.Engine) { group = engine.Group("/") } group.GET("/", c.MakeIndexFunc()) - group.POST("/add", c.MakeAddProxyFunc()) group.POST("/update", c.MakeUpdateProxyFunc()) - group.POST("/remove", c.MakeRemoveProxyFunc()) group.GET("/proxy/*serverApi", c.MakeProxyFunc()) } diff --git a/pkg/server/controller/utils.go b/pkg/server/controller/utils.go index fa5930f..83417b1 100644 --- a/pkg/server/controller/utils.go +++ b/pkg/server/controller/utils.go @@ -5,11 +5,9 @@ import ( "fmt" "github.com/fatedier/frp/pkg/config" v1 "github.com/fatedier/frp/pkg/config/v1" - "github.com/vaughan0/go-ini" "io" "log" "net/http" - "sort" "strconv" "strings" ) @@ -22,44 +20,6 @@ func equalIgnoreCase(source string, target string) bool { return strings.ToUpper(source) == strings.ToUpper(target) } -func sortSectionKeys(object ini.Section) []string { - var keys []string - for key := range object { - keys = append(keys, key) - } - sort.Strings(keys) - return keys -} - -func serializeSections() []byte { - var build strings.Builder - build.WriteString("[common]\n") - - for _, key := range sortSectionKeys(clientCommon) { - build.WriteString(fmt.Sprintf("%s = %s\n", key, clientCommon[key])) - } - build.WriteString("\n") - - sections := Sections{clientProxies} - - for _, sectionInfo := range sections.sort() { - name := sectionInfo.Name - build.WriteString(fmt.Sprintf("[%s]\n", name)) - section := sectionInfo.Section - - for _, key := range sortSectionKeys(section) { - value := section[key] - if key == NameKey || key == OldNameKey || trimString(value) == "" { - continue - } - build.WriteString(fmt.Sprintf("%s = %s\n", key, value)) - } - build.WriteString("\n") - } - - return []byte(build.String()) -} - func (c *HandleController) buildRequestUrl(serverApi string) string { var protocol string diff --git a/pkg/server/controller/variables.go b/pkg/server/controller/variables.go index 0ddce5a..6c0c6a7 100644 --- a/pkg/server/controller/variables.go +++ b/pkg/server/controller/variables.go @@ -1,11 +1,5 @@ package controller -import ( - "github.com/vaughan0/go-ini" - "sort" - "strings" -) - const ( Success int = iota ParamError @@ -17,7 +11,7 @@ const ( const ( NameKey = "name" - OldNameKey = "_old_name" + OriginalNameKey = "_original_name" SessionName = "GOSESSION" AuthName = "_PANEL_AUTH" LoginUrl = "/login" @@ -26,16 +20,6 @@ const ( LogoutSuccessUrl = "/login" ) -var ( - clientCommon ini.Section - clientProxies map[string]ini.Section -) - -func init() { - clientCommon = ini.Section{} - clientProxies = make(map[string]ini.Section) -} - type HTTPError struct { Code int Err error @@ -75,38 +59,3 @@ type ProxyResponse struct { OperationResponse Data any `json:"data"` } - -type ClientProxies struct { - Proxy ini.Section `json:"proxy"` -} - -type SectionInfo struct { - Name string - Section ini.Section -} - -type Sections struct { - sections map[string]ini.Section -} - -func (s *Sections) sort() []SectionInfo { - sectionInfos := make([]SectionInfo, 0) - - for key, value := range s.sections { - sectionInfos = append(sectionInfos, SectionInfo{Name: key, Section: value}) - } - - sort.Slice(sectionInfos, func(i, j int) bool { - typeCompare := strings.Compare(sectionInfos[i].Section["type"], sectionInfos[j].Section["type"]) - if typeCompare == -1 { - return true - } else if typeCompare == 0 { - nameCompare := strings.Compare(sectionInfos[i].Name, sectionInfos[j].Name) - return nameCompare == -1 - } else { - return false - } - }) - - return sectionInfos -}