mirror of
https://github.com/khairul169/garage-webui.git
synced 2025-04-28 14:59:31 +07:00
115 lines
2.1 KiB
Go
115 lines
2.1 KiB
Go
package router
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"os/exec"
|
|
|
|
"github.com/coder/websocket"
|
|
)
|
|
|
|
type Terminal struct {
|
|
ws *websocket.Conn
|
|
remoteAddr string
|
|
cmd *exec.Cmd
|
|
}
|
|
|
|
func (c *Terminal) NewSession(w http.ResponseWriter, r *http.Request) {
|
|
cwd, err := os.Getwd()
|
|
if err != nil {
|
|
fmt.Printf("Failed to get current working directory: %v\n", err)
|
|
}
|
|
|
|
cmd := &exec.Cmd{
|
|
// Path: "/bin/bash",
|
|
Path: "/usr/bin/fish",
|
|
Dir: cwd,
|
|
}
|
|
c.cmd = cmd
|
|
|
|
stdin, err := cmd.StdinPipe()
|
|
if err != nil {
|
|
fmt.Printf("Failed to create stdin pipe: %v\n", err)
|
|
return
|
|
}
|
|
|
|
stdout, err := cmd.StdoutPipe()
|
|
if err != nil {
|
|
fmt.Printf("Failed to create stdout pipe: %v\n", err)
|
|
return
|
|
}
|
|
cmd.Stderr = cmd.Stdout
|
|
cmd.Stdout = os.Stdout
|
|
|
|
if err := cmd.Start(); err != nil {
|
|
fmt.Printf("Failed to start command: %v\n", err)
|
|
return
|
|
}
|
|
|
|
go func() {
|
|
// if err := cmd.Wait(); err != nil {
|
|
// fmt.Printf("Shell exited with error: %v\n", err)
|
|
// }
|
|
// c.ws.CloseNow()
|
|
}()
|
|
|
|
go func() {
|
|
buf := make([]byte, 1024)
|
|
for {
|
|
n, err := stdout.Read(buf)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
fmt.Printf("Data from stdout: %s\n", string(buf[:n]))
|
|
|
|
err = c.ws.Write(context.Background(), websocket.MessageText, buf[:n])
|
|
if err != nil {
|
|
fmt.Printf("Failed to write data to websocket: %v\n", err)
|
|
return
|
|
}
|
|
|
|
}
|
|
}()
|
|
|
|
for {
|
|
_, data, err := c.ws.Read(context.Background())
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
fmt.Printf("Data from websocket: %s\n", string(data))
|
|
|
|
if _, err := stdin.Write(data); err != nil {
|
|
fmt.Printf("Failed to write data to stdin: %v\n", err)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
func (c *Terminal) Close() {
|
|
if c.cmd != nil {
|
|
c.cmd.Process.Kill()
|
|
}
|
|
|
|
fmt.Println("Terminal session closed:", c.remoteAddr)
|
|
c.ws.Close(websocket.StatusInternalError, "the connection is closed")
|
|
}
|
|
|
|
func TerminalHandler(w http.ResponseWriter, r *http.Request) {
|
|
fmt.Printf("New terminal session: %s\n", r.RemoteAddr)
|
|
|
|
c, err := websocket.Accept(w, r, nil)
|
|
if err != nil {
|
|
fmt.Printf("Failed to accept websocket: %v\n", err)
|
|
return
|
|
}
|
|
|
|
term := &Terminal{ws: c, remoteAddr: r.RemoteAddr}
|
|
defer term.Close()
|
|
|
|
term.NewSession(w, r)
|
|
}
|