mirror of
https://github.com/yhl452493373/frps-panel.git
synced 2026-04-04 06:16:59 +08:00
add an api proxy url to access frp server info
This commit is contained in:
@@ -14,6 +14,22 @@ section {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.layui-header{
|
||||||
|
line-height: 60px;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layui-title{
|
||||||
|
position: absolute;
|
||||||
|
left: 200px;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
height: 100%;
|
||||||
|
color: #fff;
|
||||||
|
padding: 0 15px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
#searchForm input {
|
#searchForm input {
|
||||||
height: 30px;
|
height: 30px;
|
||||||
line-height: 28px;
|
line-height: 28px;
|
||||||
|
|||||||
@@ -5,37 +5,20 @@ var loadServerInfo = (function ($) {
|
|||||||
* get server info
|
* get server info
|
||||||
* @param lang {{}} language json
|
* @param lang {{}} language json
|
||||||
*/
|
*/
|
||||||
function loadServerInfo(lang) {
|
function loadServerInfo(lang, title) {
|
||||||
|
console.log(title)
|
||||||
|
$("#title").text(title);
|
||||||
$('#content').empty();
|
$('#content').empty();
|
||||||
var loading = layui.layer.load();
|
var loading = layui.layer.load();
|
||||||
|
|
||||||
$.ajax({
|
$.getJSON('/proxy/api/serverinfo').done(function (result) {
|
||||||
url: 'http://127.0.0.1:7500/api/serverinfo',
|
if (result.success) {
|
||||||
dataType: 'jsonp',
|
renderServerInfo(JSON.parse(result.data));
|
||||||
success: function (result) {
|
} else {
|
||||||
result = {
|
layui.layer.msg(result.message);
|
||||||
"version": "0.51.3",
|
|
||||||
"bind_port": 7000,
|
|
||||||
"vhost_http_port": 80,
|
|
||||||
"vhost_https_port": 443,
|
|
||||||
"tcpmux_httpconnect_port": 0,
|
|
||||||
"kcp_bind_port": 7000,
|
|
||||||
"quic_bind_port": 0,
|
|
||||||
"subdomain_host": "frp.yanghuanglin.com",
|
|
||||||
"max_pool_count": 100,
|
|
||||||
"max_ports_per_client": 0,
|
|
||||||
"heart_beat_timeout": 90,
|
|
||||||
"total_traffic_in": 1669491,
|
|
||||||
"total_traffic_out": 54422369,
|
|
||||||
"cur_conns": 0,
|
|
||||||
"client_counts": 1,
|
|
||||||
"proxy_type_count": {"http": 9, "https": 8, "tcp": 7}
|
|
||||||
};
|
|
||||||
renderServerInfo(result);
|
|
||||||
},
|
|
||||||
complete: function () {
|
|
||||||
layui.layer.close(loading);
|
|
||||||
}
|
}
|
||||||
|
}).always(function () {
|
||||||
|
layui.layer.close(loading);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -140,7 +140,8 @@ var loadUserList = (function ($) {
|
|||||||
* load i18n language
|
* load i18n language
|
||||||
* @param lang {{}} language json
|
* @param lang {{}} language json
|
||||||
*/
|
*/
|
||||||
function loadUserList(lang) {
|
function loadUserList(lang, title) {
|
||||||
|
$("#title").text(title);
|
||||||
var html = layui.laytpl($('#userListTemplate').html()).render();
|
var html = layui.laytpl($('#userListTemplate').html()).render();
|
||||||
$('#content').html(html);
|
$('#content').html(html);
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
$.getJSON('/lang').done(function (lang) {
|
$.getJSON('/lang').done(function (lang) {
|
||||||
layui.element.on('nav(leftNav)', function (elem) {
|
layui.element.on('nav(leftNav)', function (elem) {
|
||||||
if (elem.attr('id') === 'serverInfo') {
|
if (elem.attr('id') === 'serverInfo') {
|
||||||
loadServerInfo(lang);
|
loadServerInfo(lang, elem.text().trim());
|
||||||
} else if (elem.attr('id') === 'userList') {
|
} else if (elem.attr('id') === 'userList') {
|
||||||
loadUserList(lang);
|
loadUserList(lang, elem.text().trim());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 322 KiB After Width: | Height: | Size: 322 KiB |
@@ -2,13 +2,13 @@
|
|||||||
<html lang="">
|
<html lang="">
|
||||||
<head>
|
<head>
|
||||||
<title>${ .UserManage }</title>
|
<title>${ .UserManage }</title>
|
||||||
<link rel="stylesheet" href="./static/layui/css/layui.css">
|
<link rel="stylesheet" href="./static/lib/layui/css/layui.css">
|
||||||
<link rel="stylesheet" href="./static/css/layui-theme-dark.css">
|
<link rel="stylesheet" href="./static/css/layui-theme-dark.css">
|
||||||
<link rel="stylesheet" href="./static/css/index.css">
|
<link rel="stylesheet" href="./static/css/index.css">
|
||||||
<link rel="stylesheet" href="./static/css/index-color.css">
|
<link rel="stylesheet" href="./static/css/index-color.css">
|
||||||
<script src="./static/layui/layui.js"></script>
|
<script src="./static/lib/layui/layui.js"></script>
|
||||||
<script src="./static/js/echarts.min.js"></script>
|
<script src="./static/lib/echarts.min.js"></script>
|
||||||
<script src="./static/js/filesize.min.js"></script>
|
<script src="./static/lib/filesize.min.js"></script>
|
||||||
<script src="./static/js/index-server-info.js"></script>
|
<script src="./static/js/index-server-info.js"></script>
|
||||||
<script src="./static/js/index-user-list.js"></script>
|
<script src="./static/js/index-user-list.js"></script>
|
||||||
<script src="./static/js/index.js"></script>
|
<script src="./static/js/index.js"></script>
|
||||||
@@ -22,13 +22,7 @@
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<style>
|
<style>
|
||||||
.layui-header {
|
|
||||||
width: 200px;
|
|
||||||
right: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.layui-layout-admin .layui-body {
|
.layui-layout-admin .layui-body {
|
||||||
top: 0;
|
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -37,6 +31,7 @@
|
|||||||
<div class="layui-layout layui-layout-admin">
|
<div class="layui-layout layui-layout-admin">
|
||||||
<div class="layui-header">
|
<div class="layui-header">
|
||||||
<div class="layui-logo layui-hide-xs layui-bg-black">${ .FrpsMultiuser }</div>
|
<div class="layui-logo layui-hide-xs layui-bg-black">${ .FrpsMultiuser }</div>
|
||||||
|
<div class="layui-title" id="title"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layui-side layui-bg-black">
|
<div class="layui-side layui-bg-black">
|
||||||
<div class="layui-side-scroll">
|
<div class="layui-side-scroll">
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -103,24 +102,14 @@ func ParseConfigFile(file string) (controller.CommonInfo, map[string]controller.
|
|||||||
log.Printf("fail to get [common] section from file %s : %v", file, err)
|
log.Printf("fail to get [common] section from file %s : %v", file, err)
|
||||||
return common, nil, nil, nil, nil, iniFile, err
|
return common, nil, nil, nil, nil, iniFile, err
|
||||||
}
|
}
|
||||||
pluginAddr := commonSection.Key("plugin_addr").Value()
|
common.PluginAddr = commonSection.Key("plugin_addr").MustString("0.0.0.0")
|
||||||
if len(pluginAddr) != 0 {
|
common.PluginPort = commonSection.Key("plugin_port").MustInt(7200)
|
||||||
common.PluginAddr = pluginAddr
|
|
||||||
} else {
|
|
||||||
common.PluginAddr = "0.0.0.0"
|
|
||||||
}
|
|
||||||
pluginPort := commonSection.Key("plugin_port").Value()
|
|
||||||
if len(pluginPort) != 0 {
|
|
||||||
port, err := strconv.Atoi(pluginPort)
|
|
||||||
if err != nil {
|
|
||||||
return common, nil, nil, nil, nil, iniFile, err
|
|
||||||
}
|
|
||||||
common.PluginPort = port
|
|
||||||
} else {
|
|
||||||
common.PluginPort = 7200
|
|
||||||
}
|
|
||||||
common.User = commonSection.Key("admin_user").Value()
|
common.User = commonSection.Key("admin_user").Value()
|
||||||
common.Pwd = commonSection.Key("admin_pwd").Value()
|
common.Pwd = commonSection.Key("admin_pwd").Value()
|
||||||
|
common.DashboardAddr = commonSection.Key("dashboard_addr").MustString("127.0.0.1")
|
||||||
|
common.DashboardPort = commonSection.Key("dashboard_port").MustInt(7500)
|
||||||
|
common.DashboardUser = commonSection.Key("dashboard_user").Value()
|
||||||
|
common.DashboardPwd = commonSection.Key("dashboard_pwd").Value()
|
||||||
|
|
||||||
portsSection, err := iniFile.GetSection("ports")
|
portsSection, err := iniFile.GetSection("ports")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -1,9 +1,16 @@
|
|||||||
; basic options
|
; basic options
|
||||||
[common]
|
[common]
|
||||||
|
; frps config info
|
||||||
plugin_addr = 127.0.0.1
|
plugin_addr = 127.0.0.1
|
||||||
plugin_port = 7200
|
plugin_port = 7200
|
||||||
admin_user = admin
|
admin_user = admin
|
||||||
admin_pwd = admin
|
admin_pwd = admin
|
||||||
|
|
||||||
|
; frp dashboard config info
|
||||||
|
dashboard_addr = 127.0.0.1
|
||||||
|
dashboard_port = 7500
|
||||||
|
dashboard_user = admin
|
||||||
|
dashboard_pwd = admin
|
||||||
|
|
||||||
; user tokens
|
; user tokens
|
||||||
[users]
|
[users]
|
||||||
|
|||||||
@@ -1,16 +1,19 @@
|
|||||||
package controller
|
package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
plugin "github.com/fatedier/frp/pkg/plugin/server"
|
plugin "github.com/fatedier/frp/pkg/plugin/server"
|
||||||
ginI18n "github.com/gin-contrib/i18n"
|
ginI18n "github.com/gin-contrib/i18n"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -21,6 +24,7 @@ const (
|
|||||||
SaveError = 3
|
SaveError = 3
|
||||||
UserFormatError = 4
|
UserFormatError = 4
|
||||||
TokenFormatError = 5
|
TokenFormatError = 5
|
||||||
|
FrpServerError = 6
|
||||||
)
|
)
|
||||||
|
|
||||||
var UserFormatReg = regexp.MustCompile("^\\w+$")
|
var UserFormatReg = regexp.MustCompile("^\\w+$")
|
||||||
@@ -38,10 +42,14 @@ type HTTPError struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type CommonInfo struct {
|
type CommonInfo struct {
|
||||||
PluginAddr string
|
PluginAddr string
|
||||||
PluginPort int
|
PluginPort int
|
||||||
User string
|
User string
|
||||||
Pwd string
|
Pwd string
|
||||||
|
DashboardAddr string
|
||||||
|
DashboardPort int
|
||||||
|
DashboardUser string
|
||||||
|
DashboardPwd string
|
||||||
}
|
}
|
||||||
|
|
||||||
type TokenInfo struct {
|
type TokenInfo struct {
|
||||||
@@ -67,6 +75,11 @@ type OperationResponse struct {
|
|||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ProxyResponse struct {
|
||||||
|
OperationResponse
|
||||||
|
Data string `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
type TokenSearch struct {
|
type TokenSearch struct {
|
||||||
TokenInfo
|
TokenInfo
|
||||||
Page int `form:"page"`
|
Page int `form:"page"`
|
||||||
@@ -632,3 +645,45 @@ func (c *HandleController) MakeEnableTokensFunc() func(context *gin.Context) {
|
|||||||
context.JSON(http.StatusOK, &response)
|
context.JSON(http.StatusOK, &response)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *HandleController) MakeProxyFunc() func(context *gin.Context) {
|
||||||
|
return func(context *gin.Context) {
|
||||||
|
res := ProxyResponse{}
|
||||||
|
host := c.CommonInfo.DashboardAddr
|
||||||
|
port := c.CommonInfo.DashboardPort
|
||||||
|
requestUrl := "http://" + host + ":" + strconv.Itoa(port) + context.Param("serverApi")
|
||||||
|
request, _ := http.NewRequest("GET", requestUrl, nil)
|
||||||
|
username := c.CommonInfo.DashboardUser
|
||||||
|
if len(strings.TrimSpace(username)) != 0 {
|
||||||
|
password := c.CommonInfo.DashboardPwd
|
||||||
|
auth := []byte(username + ":" + password)
|
||||||
|
request.Header.Add("Authorization", "Basic "+base64.StdEncoding.EncodeToString(auth))
|
||||||
|
}
|
||||||
|
response, err := http.DefaultClient.Do(request)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
res.Code = FrpServerError
|
||||||
|
res.Success = false
|
||||||
|
res.Message = err.Error()
|
||||||
|
context.JSON(http.StatusOK, &res)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
res.Code = response.StatusCode
|
||||||
|
body, err := io.ReadAll(response.Body)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
res.Success = false
|
||||||
|
res.Message = err.Error()
|
||||||
|
} else {
|
||||||
|
if res.Code == http.StatusOK {
|
||||||
|
res.Success = true
|
||||||
|
res.Data = string(body)
|
||||||
|
} else {
|
||||||
|
res.Success = false
|
||||||
|
res.Message = string(body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
context.JSON(http.StatusOK, &res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ func (c *HandleController) Register(rootDir string, engine *gin.Engine) {
|
|||||||
group.POST("/remove", c.MakeRemoveTokensFunc())
|
group.POST("/remove", c.MakeRemoveTokensFunc())
|
||||||
group.POST("/disable", c.MakeDisableTokensFunc())
|
group.POST("/disable", c.MakeDisableTokensFunc())
|
||||||
group.POST("/enable", c.MakeEnableTokensFunc())
|
group.POST("/enable", c.MakeEnableTokensFunc())
|
||||||
|
group.GET("/proxy/*serverApi", c.MakeProxyFunc())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *HandleController) HandleLogin(content *plugin.LoginContent) plugin.Response {
|
func (c *HandleController) HandleLogin(content *plugin.LoginContent) plugin.Response {
|
||||||
|
|||||||
Reference in New Issue
Block a user