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:
parent
f8e90e0e04
commit
906f225899
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,4 +1,4 @@
|
||||
public/
|
||||
frontend/public/
|
||||
output.log
|
||||
**/node_modules/
|
||||
.DS_Store
|
||||
|
25
Makefile
25
Makefile
@ -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
10
doc/http_routes.md
Normal 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
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user