Browse Source

assets: optimize static files archetucture

fatedier 8 years ago
parent
commit
4300169041

+ 1 - 0
Makefile

@@ -15,6 +15,7 @@ fmt:
 
 frps:
 	go build -o bin/frps ./src/frp/cmd/frps
+	cp -rf ./assets ./bin
 
 frpc:
 	go build -o bin/frpc ./src/frp/cmd/frpc

+ 0 - 6
assets/static/bootstrap.min.css → assets/css/bootstrap.min.css

@@ -1,10 +1,4 @@
 /*!
- * bootswatch v3.3.6
- * Homepage: http://bootswatch.com
- * Copyright 2012-2015 Thomas Park
- * Licensed under MIT
- * Based on Bootstrap
-*//*!
  * Bootstrap v3.3.6 (http://getbootstrap.com)
  * Copyright 2011-2015 Twitter, Inc.
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)

+ 0 - 0
assets/static/font-awesome.min.css → assets/css/font-awesome.min.css


+ 18 - 0
assets/css/iconfont.css

@@ -0,0 +1,18 @@
+
+@font-face {font-family: "iconfont";
+  src: url('/static/font/iconfont.eot'); /* IE9*/
+  src: url('/static/font/iconfont.eot#iefix') format('embedded-opentype'), /* IE6-IE8 */
+  url('/static/font/iconfont.woff') format('woff'), /* chrome, firefox */
+  url('/static/font/iconfont.ttf') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
+  url('/static/font/iconfont.svg#iconfont') format('svg'); /* iOS 4.1- */
+}
+
+.iconfont {
+  font-family:"iconfont" !important;
+  font-size:16px;
+  font-style:normal;
+  -webkit-font-smoothing: antialiased;
+  -webkit-text-stroke-width: 0.2px;
+  -moz-osx-font-smoothing: grayscale;
+}
+.icon-sort:before { content: "\e66d"; }

+ 0 - 0
assets/static/iconfont.eot → assets/font/iconfont.eot


+ 0 - 0
assets/static/iconfont.svg → assets/font/iconfont.svg


+ 0 - 0
assets/static/iconfont.ttf → assets/font/iconfont.ttf


+ 0 - 0
assets/static/iconfont.woff → assets/font/iconfont.woff


+ 41 - 48
assets/index.html

@@ -3,19 +3,14 @@
 
 <head>
   <title>frp</title>
-  <link href="static/bootstrap.min.css" rel="stylesheet">
-  <script src="static/jquery.min.js"></script>
-  <script src="static/bootstrap.min.js"></script>
-  <link href="static/iconfont.css" rel="stylesheet">
+  <link href="static/css/bootstrap.min.css" rel="stylesheet">
+  <link href="static/css/iconfont.css" rel="stylesheet">
+  <script src="static/js/jquery.min.js"></script>
+  <script src="static/js/bootstrap.min.js"></script>
 </head>
 
 <body>
-  <div class="container-fluid">
-    <!--div class="row">
-      <div class="col-sm-12 text-center">
-        <h1 class="logo">frp</h1>
-      </div>
-    </div-->
+  <div class="container-fluid" style="margin-top: 80px">
     <div class="row">
       <div class="col-md-5 col-sm-offset-1">
         <div class="panel panel-default">
@@ -57,23 +52,23 @@
       </div>
     </div>
   </div>
-  <script src="static/angular.min.js"></script>
-  <script type="text/javascript" src="static/echarts.min.js"></script>
+  <script src="static/js/angular.min.js"></script>
+  <script type="text/javascript" src="static/js/echarts.min.js"></script>
   <script>
     var alldata = new Array();
     var index = null; 
-    <<< range .proxies >>>
-      alldata["<<< .name >>>"] = {
-        name: "<<< .name >>>",
-        type: "<<< .type >>>",
-        bind_addr: "<<< .bind_addr >>>",
-        listen_port: "<<< .listen_port >>>",
-        current_conns: <<< .current_conns >>> ,
-        domains: [ <<< range.custom_domains >>> "<<< . >>>", <<< end >>> ],
-        stat: "<<< .status >>>",
-        use_encryption: "<<< .use_encryption >>>",
-        use_gzip: "<<< .use_gzip >>>",
-        privilege_mode: "<<< .privilege_mode >>>",
+    <<< range .>>>
+      alldata["<<< .Name >>>"] = {
+        name: "<<< .Name >>>",
+        type: "<<< .Type >>>",
+        bind_addr: "<<< .BindAddr >>>",
+        listen_port: "<<< .ListenPort >>>",
+        current_conns: <<< .CurrentConns >>> ,
+        domains: [ <<< range.CustomDomains >>> "<<< . >>>", <<< end >>> ],
+        stat: "<<< .Status >>>",
+        use_encryption: "<<< .UseEncryption >>>",
+        use_gzip: "<<< .UseGzip >>>",
+        privilege_mode: "<<< .PrivilegeMode >>>",
         times: [],
         ins: [],
         outs: [],
@@ -93,7 +88,6 @@
     var step = 1;
 
     function reloadview() {
-      console.log("in reloadview index:", index);
       window.maxval = 0;
       window.dw = " B";
       window.step = 1;
@@ -154,12 +148,12 @@
         },
         series: [{
           name: 'flow_in',
-          type: 'line',
+          type: 'bar',
           stack: '总量',
           data: alldata[index].ins
         }, {
           name: 'flow_out',
-          type: 'line',
+          type: 'bar',
           stack: '总量',
           data: alldata[index].outs
         }]
@@ -196,7 +190,7 @@
         },
         series: [{
           name: 'total_accept_conns',
-          type: 'line',
+          type: 'bar',
           stack: '总量',
           data: alldata[index].conns
         }]
@@ -244,34 +238,33 @@
     {
       var ttdy = new Date();
       var today = ttdy.getFullYear() * 10000 + (1 + ttdy.getMonth()) * 100 + ttdy.getDate();
-			for (var inx in newproxies.proxies) {
-        console.log("now inx is ", inx);
-        if (newproxies.proxies[inx].current_conns == undefined) {
-          newproxies.proxies[inx].current_conns = 0;
-          alldata[newproxies.proxies[inx].name].current_conns = 0;
+			for (var inx in newproxies) {
+        if (newproxies[inx].current_conns == undefined) {
+          newproxies[inx].current_conns = 0;
+          alldata[newproxies[inx].name].current_conns = 0;
         }
 
-        if (newproxies.proxies[inx].daily == undefined ) {
-          newproxies.proxies[inx].daily = [];
+        if (newproxies[inx].daily == undefined ) {
+          newproxies[inx].daily = [];
         } 
 
-        newproxies.proxies[inx].daily.sort(function (a, b) {
+        newproxies[inx].daily.sort(function (a, b) {
             return a.time > b.time;
         });
 
-        for (var iinnx in newproxies.proxies[inx].daily) {
-          alldata[newproxies.proxies[inx].name].times.push(newproxies.proxies[inx].daily[iinnx].time);
-          alldata[newproxies.proxies[inx].name].ins.push(newproxies.proxies[inx].daily[iinnx].flow_in);
-          alldata[newproxies.proxies[inx].name].outs.push(newproxies.proxies[inx].daily[iinnx].flow_out);
-          alldata[newproxies.proxies[inx].name].conns.push(newproxies.proxies[inx].daily[iinnx].total_accept_conns);
+        for (var iinnx in newproxies[inx].daily) {
+          alldata[newproxies[inx].name].times.push(newproxies[inx].daily[iinnx].time);
+          alldata[newproxies[inx].name].ins.push(newproxies[inx].daily[iinnx].flow_in);
+          alldata[newproxies[inx].name].outs.push(newproxies[inx].daily[iinnx].flow_out);
+          alldata[newproxies[inx].name].conns.push(newproxies[inx].daily[iinnx].total_accept_conns);
         }
         
-        if (newproxies.proxies[inx].daily.length == 0 || newproxies.proxies[inx].daily[0].time != today) {
-          alldata[newproxies.proxies[inx].name].times.push(today);
-          alldata[newproxies.proxies[inx].name].ins.push(0);
-          alldata[newproxies.proxies[inx].name].outs.push(0);
-          alldata[newproxies.proxies[inx].name].conns.push(0);
-          newproxies.proxies[inx].daily.push({
+        if (newproxies[inx].daily.length == 0 || newproxies[inx].daily[0].time != today) {
+          alldata[newproxies[inx].name].times.push(today);
+          alldata[newproxies[inx].name].ins.push(0);
+          alldata[newproxies[inx].name].outs.push(0);
+          alldata[newproxies[inx].name].conns.push(0);
+          newproxies[inx].daily.push({
             time: today,
             flow_in: 0,
             flow_out: 0,
@@ -286,7 +279,7 @@
     app.controller('myCtrl', function($scope) {
       $scope.col = 'name';
       $scope.desc = 0;
-      $scope.proxies = newproxies.proxies;
+      $scope.proxies = newproxies;
     });
 
     $(".tab_info").hover(

+ 0 - 1
assets/static/angular.min.js → assets/js/angular.min.js

@@ -315,4 +315,3 @@ y(e)||e.test(b)}}}}},Kc=function(){return{restrict:"A",require:"?ngModel",link:f
 C.console&&console.log("WARNING: Tried to load angular more than once."):(je(),le(ca),ca.module("ngLocale",[],["$provide",function(a){function b(a){a+="";var b=a.indexOf(".");return-1==b?0:a.length-b-1}a.value("$locale",{DATETIME_FORMATS:{AMPMS:["AM","PM"],DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),ERANAMES:["Before Christ","Anno Domini"],ERAS:["BC","AD"],FIRSTDAYOFWEEK:6,MONTH:"January February March April May June July August September October November December".split(" "),
 SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),STANDALONEMONTH:"January February March April May June July August September October November December".split(" "),WEEKENDRANGE:[5,6],fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",medium:"MMM d, y h:mm:ss a",mediumDate:"MMM d, y",mediumTime:"h:mm:ss a","short":"M/d/yy h:mm a",shortDate:"M/d/yy",shortTime:"h:mm a"},NUMBER_FORMATS:{CURRENCY_SYM:"$",DECIMAL_SEP:".",GROUP_SEP:",",
 PATTERNS:[{gSize:3,lgSize:3,maxFrac:3,minFrac:0,minInt:1,negPre:"-",negSuf:"",posPre:"",posSuf:""},{gSize:3,lgSize:3,maxFrac:2,minFrac:2,minInt:1,negPre:"-\u00a4",negSuf:"",posPre:"\u00a4",posSuf:""}]},id:"en-us",localeID:"en_US",pluralCat:function(a,c){var e=a|0,f=c;void 0===f&&(f=Math.min(b(a),3));Math.pow(10,f);return 1==e&&0==f?"one":"other"}})}]),F(C.document).ready(function(){fe(C.document,Bc)}))})(window);!window.angular.$$csp().noInlineStyle&&window.angular.element(document.head).prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}.ng-animate-shim{visibility:hidden;}.ng-anchor{position:absolute;}</style>');
-//# sourceMappingURL=angular.min.js.map

+ 0 - 0
assets/static/bootstrap.min.js → assets/js/bootstrap.min.js


+ 0 - 0
assets/static/echarts.min.js → assets/js/echarts.min.js


+ 0 - 0
assets/static/jquery.min.js → assets/js/jquery.min.js


+ 2 - 0
conf/frps.ini

@@ -7,6 +7,8 @@ vhost_http_port = 80
 vhost_https_port = 443
 # if you want to configure or reload frps by dashboard, dashboard_port must be set
 dashboard_port = 7500
+# dashboard assets directory(only for debug mode)
+assets_dir = ./assets
 # console or real logFile path like ./frps.log
 log_file = ./frps.log
 # debug, info, warn, error

+ 10 - 0
src/frp/models/server/config.go

@@ -36,6 +36,7 @@ var (
 	VhostHttpPort  int64  = 0 // if VhostHttpPort equals 0, don't listen a public port for http protocol
 	VhostHttpsPort int64  = 0 // if VhostHttpsPort equals 0, don't listen a public port for https protocol
 	DashboardPort  int64  = 0 // if DashboardPort equals 0, dashboard is not available
+	AssetsDir      string = ""
 	LogFile        string = "console"
 	LogWay         string = "console" // console or file
 	LogLevel       string = "info"
@@ -118,6 +119,11 @@ func loadCommonConf(confFile string) error {
 		DashboardPort = 0
 	}
 
+	tmpStr, ok = conf.Get("common", "assets_dir")
+	if ok {
+		AssetsDir = tmpStr
+	}
+
 	tmpStr, ok = conf.Get("common", "log_file")
 	if ok {
 		LogFile = tmpStr
@@ -252,6 +258,8 @@ func loadProxyConf(confFile string) (proxyServers map[string]*ProxyServer, err e
 				}
 			} else if proxyServer.Type == "http" {
 				// for http
+				proxyServer.ListenPort = VhostHttpPort
+
 				domainStr, ok := section["custom_domains"]
 				if ok {
 					proxyServer.CustomDomains = strings.Split(domainStr, ",")
@@ -266,6 +274,8 @@ func loadProxyConf(confFile string) (proxyServers map[string]*ProxyServer, err e
 				}
 			} else if proxyServer.Type == "https" {
 				// for https
+				proxyServer.ListenPort = VhostHttpsPort
+
 				domainStr, ok := section["custom_domains"]
 				if ok {
 					proxyServer.CustomDomains = strings.Split(domainStr, ",")

+ 29 - 42
src/frp/models/server/dashboard.go

@@ -16,55 +16,42 @@ package server
 
 import (
 	"fmt"
-	"frp/models/metric"
-	"html/template"
+	"net"
 	"net/http"
-
-	"github.com/gin-gonic/gin"
+	"time"
 )
 
-func index(w http.ResponseWriter, r *http.Request) {
-	serinfo := metric.GetAllProxyMetrics()
-	t := template.Must(template.New("index.html").Delims("<<<", ">>>").ParseFiles("index.html"))
-
-	err := t.Execute(w, serinfo)
-	if err != nil {
-		fmt.Println(err.Error())
-	}
-}
+var (
+	httpServerReadTimeout  = 10 * time.Second
+	httpServerWriteTimeout = 10 * time.Second
+)
 
 func RunDashboardServer(addr string, port int64) (err error) {
-	defer func() {
-		if r := recover(); r != nil {
-			err = fmt.Errorf("%v", r)
-		}
-	}()
-	gin.SetMode(gin.ReleaseMode)
-	router := gin.New()
-	//router.LoadHTMLGlob("assets/*")
-	router.GET("/api/reload", apiReload)
-	router.GET("/api/proxies", apiProxies)
-	go router.Run(fmt.Sprintf("%s:%d", addr, port))
-	return
-}
-
-func RunDashboardServer2(addr string, port int64) (err error) {
-	defer func() {
-		if r := recover(); r != nil {
-			err = fmt.Errorf("%v", r)
-		}
-	}()
-
-	http.HandleFunc("/", index)
-
-	fs := http.FileServer(http.Dir("static"))
-	http.Handle("/static/", http.StripPrefix("/static/", fs))
-
-	newPort := fmt.Sprintf(":%d", port)
-	err = http.ListenAndServe(newPort, nil)
+	// url router
+	mux := http.NewServeMux()
+	// api, see dashboard_api.go
+	mux.HandleFunc("/api/reload", apiReload)
+	mux.HandleFunc("/api/proxies", apiProxies)
+
+	// view see dashboard_view.go
+	mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./assets"))))
+	mux.HandleFunc("/", viewDashboard)
+
+	address := fmt.Sprintf("%s:%d", addr, port)
+	server := &http.Server{
+		Addr:         address,
+		Handler:      mux,
+		ReadTimeout:  httpServerReadTimeout,
+		WriteTimeout: httpServerWriteTimeout,
+	}
+	if address == "" {
+		address = ":http"
+	}
+	ln, err := net.Listen("tcp", address)
 	if err != nil {
 		return err
 	}
 
-	return nil
+	go server.Serve(ln)
+	return
 }

+ 10 - 7
src/frp/models/server/dashboard_api.go

@@ -17,8 +17,7 @@ package server
 import (
 	"encoding/json"
 	"fmt"
-
-	"github.com/gin-gonic/gin"
+	"net/http"
 
 	"frp/models/metric"
 	"frp/utils/log"
@@ -29,10 +28,10 @@ type GeneralResponse struct {
 	Msg  string `json:"msg"`
 }
 
-func apiReload(c *gin.Context) {
+func apiReload(w http.ResponseWriter, r *http.Request) {
+	var buf []byte
 	res := &GeneralResponse{}
 	defer func() {
-		buf, _ := json.Marshal(res)
 		log.Info("Http response [/api/reload]: %s", string(buf))
 	}()
 
@@ -43,7 +42,9 @@ func apiReload(c *gin.Context) {
 		res.Msg = fmt.Sprintf("%v", err)
 		log.Error("frps reload error: %v", err)
 	}
-	c.JSON(200, res)
+
+	buf, _ = json.Marshal(res)
+	w.Write(buf)
 }
 
 type ProxiesResponse struct {
@@ -52,7 +53,8 @@ type ProxiesResponse struct {
 	Proxies []*metric.ServerMetric `json:"proxies"`
 }
 
-func apiProxies(c *gin.Context) {
+func apiProxies(w http.ResponseWriter, r *http.Request) {
+	var buf []byte
 	res := &ProxiesResponse{}
 	defer func() {
 		log.Info("Http response [/api/proxies]: code [%d]", res.Code)
@@ -60,5 +62,6 @@ func apiProxies(c *gin.Context) {
 
 	log.Info("Http request: [/api/proxies]")
 	res.Proxies = metric.GetAllProxyMetrics()
-	c.JSON(200, res)
+	buf, _ = json.Marshal(res)
+	w.Write(buf)
 }

+ 35 - 0
src/frp/models/server/dashboard_view.go

@@ -0,0 +1,35 @@
+// Copyright 2016 fatedier, fatedier@gmail.com
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// 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 server
+
+import (
+	"html/template"
+	"net/http"
+	"path"
+
+	"frp/models/metric"
+	"frp/utils/log"
+)
+
+func viewDashboard(w http.ResponseWriter, r *http.Request) {
+	metrics := metric.GetAllProxyMetrics()
+	t := template.Must(template.New("index.html").Delims("<<<", ">>>").ParseFiles(path.Join(AssetsDir, "index.html")))
+
+	err := t.Execute(w, metrics)
+	if err != nil {
+		log.Warn("parse template file [index.html] error: %v", err)
+		http.Error(w, "parse template file error", http.StatusInternalServerError)
+	}
+}

+ 7 - 1
src/frp/models/server/server.go

@@ -63,7 +63,13 @@ func NewProxyServerFromCtlMsg(req *msg.ControlReq) (p *ProxyServer) {
 	p.PrivilegeMode = req.PrivilegeMode
 	p.PrivilegeToken = PrivilegeToken
 	p.BindAddr = BindAddr
-	p.ListenPort = req.RemotePort
+	if p.Type == "tcp" {
+		p.ListenPort = req.RemotePort
+	} else if p.Type == "http" {
+		p.ListenPort = VhostHttpPort
+	} else if p.Type == "https" {
+		p.ListenPort = VhostHttpsPort
+	}
 	p.CustomDomains = req.CustomDomains
 	p.HostHeaderRewrite = req.HostHeaderRewrite
 	return

+ 0 - 1
src/frp/utils/vhost/vhost.go

@@ -131,7 +131,6 @@ func (l *Listener) Accept() (*conn.Conn, error) {
 	// if rewriteFunc is exist and rewriteHost is set
 	// rewrite http requests with a modified host header
 	if l.mux.rewriteFunc != nil && l.rewriteHost != "" {
-		fmt.Printf("host rewrite: %s\n", l.rewriteHost)
 		sConn, err := l.mux.rewriteFunc(conn, l.rewriteHost)
 		if err != nil {
 			return nil, fmt.Errorf("http host header rewrite failed")