2
0
mirror of https://github.com/elisescu/tty-share synced 2024-11-03 23:15:42 +00:00

Refactor the frontend structure

Change the Makefile and webpack config to reflect the new structure of
where we keep the frontend generated files.

Use the 404 static pages when requests are made to paths not found.

Add a small doc describing the available http routes.
This commit is contained in:
Vasile Popescu 2018-05-12 18:36:08 +02:00
parent f8e90e0e04
commit 906f225899
7 changed files with 130 additions and 75 deletions

2
.gitignore vendored
View File

@ -1,4 +1,4 @@
public/
frontend/public/
output.log
**/node_modules/
.DS_Store

View File

@ -9,44 +9,33 @@ TTY_SENDER=tty_sender
TTY_SERVER_SRC=$(filter-out ./tty-server/assets_bundle.go, $(wildcard ./tty-server/*.go)) ./tty-server/assets_bundle.go
TTY_SENDER_SRC=$(wildcard ./tty-sender/*.go)
EXTRA_BUILD_DEPS=$(wildcard ./common/*go)
TTY_SERVER_ASSETS=$(addprefix ./public/templates/,$(notdir $(wildcard ./frontend/templates/*))) public/bundle.js
TTY_SERVER_ASSETS=$(wildcard frontend/public/*)
all: $(TTY_SERVER) $(TTY_SENDER)
@echo "All done"
$(TTY_SERVER): $(TTY_SERVER_SRC) $(EXTRA_BUILD_DEPS) $(TTY_SERVER_ASSETS)
$(TTY_SERVER): $(TTY_SERVER_SRC) $(EXTRA_BUILD_DEPS)
go build -o $@ $(TTY_SERVER_SRC)
$(TTY_SENDER): $(TTY_SENDER_SRC) $(EXTRA_BUILD_DEPS)
go build -o $@ $(TTY_SENDER_SRC)
# TODO: perhaps replace all these paths with variables?
frontend/bundle.js: $(wildcard ./frontend/src/*)
cd frontend && npm run build && cd -
public/bundle.js: frontend/bundle.js
mkdir -p $(dir $@)
cp $^ $@
public/templates/%: frontend/templates/%
mkdir -p $(dir $@)
cp $^ $@
tty-server/assets_bundle.go: $(TTY_SERVER_ASSETS)
go-bindata --prefix public -o $@ $^
go-bindata --prefix frontend/public/ -o $@ $^
frontend: FORCE
cd frontend && npm run build && cd -
clean:
@rm -f $(TTY_SERVER) $(TTY_SENDER)
rm -f $(TTY_SERVER) $(TTY_SENDER)
rm -fr frontend/out/
@echo "Cleaned"
runs: $(TTY_SERVER)
@./$(TTY_SERVER) --url http://localhost:9090 --web_address :9090 --sender_address :7654
./$(TTY_SERVER) --url http://localhost:9090 --web_address :9090 --sender_address :7654
runc: $(TTY_SENDER)
@./$(TTY_SENDER) --logfile output.log
./$(TTY_SENDER) --logfile output.log --useTLS=false
test:
@go test github.com/elisescu/tty-share/testing -v

10
doc/http_routes.md Normal file
View File

@ -0,0 +1,10 @@
Routes
======
These are the routes the server will listen to:
* `/` - the main page which probably will be a redirect
* `/ws/<session id>` - will serve the websockets session
* `/s/<session id>` - will serve the tty-receiver webpage, which will make some further requests for
the resources
* `/static/` - serving the static resources: 404 page, js and css files

View File

@ -4,9 +4,8 @@
"description": "",
"main": "",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack",
"watch": "webpack --watch --hot"
"watch": "TTY_SHARE_ENV=development webpack --watch",
"build": "TTY_SHARE_ENV=production webpack"
},
"author": "",
"license": "",
@ -24,7 +23,9 @@
"source-map-loader": "0.2.2",
"style-loader": "0.19.0",
"webpack": "3.7.1",
"webpack-dev-server": "2.9.1",
"xterm": "2.9.2"
},
"devDependencies": {
"copy-webpack-plugin": "4.5.1"
}
}

View File

@ -15,7 +15,7 @@
}
console.log("Initial data", window.ttyInitialData)
</script>
<script src="/static/bundle.js"></script>
<script src="/static/tty-receiver.js"></script>
</body>
</html>

View File

@ -1,11 +1,16 @@
var path = require('path');
module.exports = {
entry: './src/main.js',
output: {
path: __dirname,
filename: 'bundle.js'
const webpack = require("webpack");
const copyWebpackPlugin = require('copy-webpack-plugin')
const develBuild = process.env.TTY_SHARE_ENV === 'development';
let mainConfig = {
entry: {
'tty-receiver': './tty-receiver/main.js',
},
output: {
path: __dirname + '/public/',
filename: '[name].js',
},
devtool: 'inline-source-map',
module: {
rules: [
{
@ -47,5 +52,21 @@ module.exports = {
use: ['source-map-loader']
}
]
}
};
},
plugins: [
new copyWebpackPlugin([
'static',
'templates',
], {
debug: 'info',
}),
],
};
if (develBuild) {
mainConfig.devtool = 'inline-source-map';
} else {
mainConfig.plugins.push(new webpack.optimize.UglifyJsPlugin( { minimize: true }));
}
module.exports = mainConfig;

View File

@ -2,16 +2,24 @@ package main
import (
"errors"
"fmt"
"html/template"
"mime"
"net"
"net/http"
"os"
"path/filepath"
"sync"
"github.com/gorilla/mux"
"github.com/gorilla/websocket"
)
const (
errorInvalidSession = iota
errorNotFound = iota
errorNotAllowed = iota
)
var log = MainLogger
// SessionTemplateModel used for templating
@ -41,6 +49,35 @@ type TTYProxyServer struct {
activeSessionsRWLock sync.RWMutex
}
func (server *TTYProxyServer) serveContent(w http.ResponseWriter, r *http.Request, name string) {
// If a path to the frontend resources was passed, serve from there, otherwise, serve from the
// builtin bundle
if server.config.FrontendPath == "" {
file, err := Asset(name)
if err != nil {
w.WriteHeader(http.StatusNotFound)
return
}
ctype := mime.TypeByExtension(filepath.Ext(name))
if ctype == "" {
ctype = http.DetectContentType(file)
}
w.Header().Set("Content-Type", ctype)
w.Write(file)
} else {
_, err := os.Open(server.config.FrontendPath + string(os.PathSeparator) + name)
if err != nil {
w.WriteHeader(http.StatusNotFound)
return
}
http.ServeFile(w, r, name)
}
}
// NewTTYProxyServer creates a new instance
func NewTTYProxyServer(config TTYProxyServerConfig) (server *TTYProxyServer) {
server = &TTYProxyServer{
@ -51,29 +88,22 @@ func NewTTYProxyServer(config TTYProxyServerConfig) (server *TTYProxyServer) {
}
routesHandler := mux.NewRouter()
if config.FrontendPath != "" {
routesHandler.PathPrefix("/static/").Handler(http.StripPrefix("/static/",
http.FileServer(http.Dir(config.FrontendPath))))
} else {
// Serve the bundled assets
routesHandler.PathPrefix("/static/").Handler(http.StripPrefix("/static/",
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
data, err := Asset(r.URL.Path)
if err != nil {
w.WriteHeader(http.StatusNotFound)
return
}
w.Write(data)
log.Infof("Delivered %s from the bundle", r.URL.Path)
})))
}
routesHandler.PathPrefix("/static/").Handler(http.StripPrefix("/static/",
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
server.serveContent(w, r, r.URL.Path)
})))
routesHandler.HandleFunc("/", defaultHandler)
routesHandler.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
server.serveContent(w, r, "index.html")
})
routesHandler.HandleFunc("/s/{sessionID}", func(w http.ResponseWriter, r *http.Request) {
sessionsHandler(server, w, r)
server.handleSession(w, r)
})
routesHandler.HandleFunc("/ws/{sessionID}", func(w http.ResponseWriter, r *http.Request) {
websocketHandler(server, w, r)
server.handleWebsocket(w, r)
})
routesHandler.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
server.serveContent(w, r, "404.html")
})
server.activeSessions = make(map[string]*ttyShareSession)
@ -85,14 +115,14 @@ func getWSPath(sessionID string) string {
return "/ws/" + sessionID
}
func websocketHandler(server *TTYProxyServer, w http.ResponseWriter, r *http.Request) {
func (server *TTYProxyServer) handleWebsocket(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
sessionID := vars["sessionID"]
defer log.Debug("Finished WS connection for ", sessionID)
// Validate incoming request.
if r.Method != "GET" {
w.WriteHeader(http.StatusMethodNotAllowed)
w.WriteHeader(http.StatusForbidden)
return
}
@ -112,20 +142,14 @@ func websocketHandler(server *TTYProxyServer, w http.ResponseWriter, r *http.Req
if session == nil {
log.Error("WE connection for invalid sessionID: ", sessionID, ". Killing it.")
// TODO: Create a proper way to communicate with the remote WS end, so that the server can send
// control messages or data messages to go directly to the terminal.
conn.WriteMessage(websocket.TextMessage, []byte("$ access denied."))
w.WriteHeader(http.StatusForbidden)
return
}
session.HandleReceiver(newWSConnection(conn))
}
func defaultHandler(http.ResponseWriter, *http.Request) {
log.Debug("Default handler ")
}
func sessionsHandler(server *TTYProxyServer, w http.ResponseWriter, r *http.Request) {
func (server *TTYProxyServer) handleSession(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
sessionID := vars["sessionID"]
@ -133,31 +157,41 @@ func sessionsHandler(server *TTYProxyServer, w http.ResponseWriter, r *http.Requ
session := getSession(server, sessionID)
// No valid session with this ID
if session == nil {
w.WriteHeader(http.StatusMethodNotAllowed)
server.serveContent(w, r, "invalid-session.html")
return
}
templateDta, err := Asset("templates/index.html")
var t *template.Template
var err error
if server.config.FrontendPath == "" {
templateDta, err := Asset("tty-receiver.in.html")
if err != nil {
panic("Cannot find the tty-receiver html template")
}
t = template.New("tty-receiver.html")
_, err = t.Parse(string(templateDta))
} else {
t, err = template.ParseFiles(server.config.FrontendPath + string(os.PathSeparator) + "tty-receiver.in.html")
}
if err != nil {
fmt.Fprintf(w, err.Error())
return
panic("Cannot parse the tty-receiver html template")
}
t := template.New("index.html")
_, err = t.Parse(string(templateDta))
if err != nil {
fmt.Fprintf(w, err.Error())
return
}
templateModel := SessionTemplateModel{
SessionID: sessionID,
Salt: "salt&pepper",
WSPath: getWSPath(sessionID),
}
t.Execute(w, templateModel)
err = t.Execute(w, templateModel)
if err != nil {
panic("Cannot execute the tty-receiver html template")
}
}
func addNewSession(server *TTYProxyServer, session *ttyShareSession) {