Initial 2024-01-26

This commit is contained in:
root
2024-01-26 07:11:35 +12:00
commit d03c481b33
33 changed files with 4224 additions and 0 deletions

122
cmpSnipper/cmpSnipper.go Normal file
View File

@@ -0,0 +1,122 @@
package cmpSnipper
import (
"errors"
"plugin"
)
type cmpPluginStruct struct {
Name string
Plug *plugin.Plugin
}
type App struct {
Conf interface{}
ErrIsDir error // = errors.New("Is directory")
CliList []cmpWbsCliStruct
cmpSnipperHttpServ cmpSnipperHttpServ
Rand4d int
PlugList []cmpPluginStruct
SshList []cmpSshCliStruct
}
func (app *App) PlugInit(name string, file string) {
qqq := map[string]interface{}{
"Aaa": "Bbb",
}
var plug cmpPluginStruct
var p *plugin.Plugin
p, err := plugin.Open(file)
if err != nil {
app.Log(err)
return
}
plug.Name = name
plug.Plug = p
plugInitReq, err := plug.Plug.Lookup("CmpPlug1Init")
if err != nil {
app.Log(err)
return
}
plugInitFnc := plugInitReq.(func(int, func(any, ...interface{}), map[string]interface{}) interface{})
plugInitRes := plugInitFnc(33, app.Log, qqq)
app.Log("%+v", plugInitRes)
app.PlugList = append(app.PlugList, plug)
}
func (app *App) PlugCall(pnam string, fnam string) {
for _, plug := range app.PlugList {
if plug.Name != pnam {
continue
}
plugFuncReq, err := plug.Plug.Lookup(fnam)
if err != nil {
app.Log(err)
return
}
plugFuncFnc := plugFuncReq.(func() error)
plugFuncRes := plugFuncFnc()
app.Log("%+v", plugFuncRes)
}
}
func (app *App) Prep() (error) {
app.ErrIsDir = errors.New("Is directory")
app.LogSetup()
var err = app.ConfLoadFile("secret/zest.json");
if err != nil {
return err
}
return nil
}
func (app *App) Proc() error {
var err error // = make(chan error, 1)
var term = make(chan bool, 1)
go app.WaitSignal(term)
err = app.HttpServStart()
if err != nil {
return err
}
<-term
app.HttpServStop()
app.Log("Terminating")
return nil
}
// end

View File

@@ -0,0 +1,103 @@
package cmpSnipper
import (
"fmt"
"errors"
"strconv"
"encoding/json"
)
func (app *App) IfcGet(ifc interface{}, arr ...string) (interface{}, error) {
var cnt = len(arr);
var idx string
for j := 0; j < cnt; j++ {
idx = arr[j]
switch v := ifc.(type) {
case string:
app.Log("Convert string to ifc")
ifc = ifc.(interface{})
case map[string]interface{}:
// app.Log("Valid ifc " + idx)
ifc = v[idx];
default:
app.Log("Invalid type variable %s %T", idx, ifc)
return nil, errors.New("Invalid type variable");
}
}
if ifc == nil {
return nil, errors.New("Undefine variable " + idx);
}
// app.Log("Found ifc %s %T", idx, ifc)
return ifc, nil;
}
func (app *App) ConfGetIfc(arr ...string) (interface{}, error) {
return app.IfcGet(app.Conf, arr...);
}
func (app *App) ConfGetStr(arr ...string) (string, error) {
ifc, err := app.ConfGetIfc(arr...);
if err != nil {
return "", err;
}
switch ifc.(type) {
case string:
return ifc.(string), nil;
case float64:
f := ifc.(float64)
u := uint64(f)
return strconv.FormatUint(u, 10), nil;
default:
return "", errors.New("Invalid type value !s");
}
return "", errors.New("Invalid type value");
}
func (app *App) ConfGetArr(arr ...string) ([]interface{}, error) {
ifc, err := app.ConfGetIfc(arr...);
if err != nil {
return nil, err;
}
switch v := ifc.(type) {
case []interface{}:
return v, nil
default:
fmt.Printf("Invalid type value %+q\n", ifc)
return nil, errors.New("Invalid type value !s");
}
return nil, errors.New("Invalid type value");
}
func (app *App) ConfLoadFile(file string) error {
data, err := app.FileReadLimit(file, 1048576);
if err != nil {
app.Log(err)
return err
}
// fmt.Println(string(data));
err = json.Unmarshal(data, &app.Conf)
if err != nil {
app.Log(err)
return err
}
return nil;
}

View File

@@ -0,0 +1,84 @@
package cmpSnipper
import (
"net"
"net/http"
)
type tcpKeepAliveListener struct {
*net.TCPListener
}
type cmpSnipperHttpServ struct {
HttpListener net.Listener
}
func (app *App) HttpServStart() error {
var err error;
// var subjHttpPortString string = "7070";
// var subjHttpPortUint16 uint16 = subjConf.Http.Port;
host, err := app.ConfGetStr("http", "host")
// fmt.Printf("Success load : %+v\n", host)
if err != nil {
app.Log(err)
return err
}
port, err := app.ConfGetStr("http", "port")
// fmt.Printf("Success load : %+v\n", port)
if err != nil {
app.Log(err)
return err
}
// if subjHttpPortUint16 == 0 || subjHttpPortString != strconv.FormatUint(uint64(subjHttpPortUint16), 10) {
// fmt.Printf("Invalid http.port %s != %d\n", subjHttpPortString, subjHttpPortUint16)
// app.Log(".Fatal");
// }
httpFileServer := http.FileServer(http.Dir("static"))
http.Handle("/go-prefix/static/", http.StripPrefix("/go-prefix/static/", httpFileServer))
http.HandleFunc("/" , app.HttpReq);
http.HandleFunc("/go-prefix/ws" , app.HttpWebSockHand)
var addr = host + ":" + port
server := &http.Server{Addr: addr}
app.Log("Listenning: '%s'", port);
app.cmpSnipperHttpServ.HttpListener, err = net.Listen("tcp", addr)
// defer app.HttpServClose()
if err != nil {
app.Log(err)
return err
}
go func() {
err = server.Serve(tcpKeepAliveListener{app.cmpSnipperHttpServ.HttpListener.(*net.TCPListener)})
if err == nil {
app.Log(err)
return // err
}
}()
return nil
}
func (app *App) HttpServStop() {
app.cmpSnipperHttpServ.HttpListener.Close()
app.Log("Server Closed")
}

View File

@@ -0,0 +1,245 @@
package cmpSnipper
import (
"os"
"strings"
"encoding/json"
"net/http"
)
func (app *App) HttpRespText(w http.ResponseWriter, data []byte) {
w.Write(data)
return
}
func (app *App) HttpRespJson(w http.ResponseWriter, data any) {
w.Header().Set("Content-Type", "application/json")
jsonResp, err := json.MarshalIndent(data, "", "\t")
if err != nil {
app.Log("Error happened in JSON marshal. Err: %s", err)
return
}
app.HttpRespText(w, jsonResp)
}
func HttpRespCodeText(w http.ResponseWriter, req *http.Request, code int, cont string, mesg any) {
w.WriteHeader(code)
w.Header().Set("Content-Type", cont)
}
func (app *App) HttpRespForbidden(w http.ResponseWriter, req *http.Request, mesg string) {
w.WriteHeader(http.StatusForbidden)
resp := make(map[string]any)
resp["code"] = 403
resp["status"] = "Forbidden"
resp["message"] = mesg
app.HttpRespJson(w, resp)
}
func (app *App) HttpReqDir1(w http.ResponseWriter, req *http.Request, targ string, path string) {
resp := map[string]interface{}{
"path" : path,
"directory": targ,
"content" : nil,
}
entries, err := os.ReadDir(targ)
if err != nil {
app.Log(err)
app.HttpRespForbidden(w, req, "Server error")
}
var slice []interface{};
for _, e := range entries {
slice = append(slice, map[string]interface{}{
"name": e.Name(),
})
// fmt.Println(e.Name());
}
resp["content"] = slice
app.HttpRespJson(w, resp)
return
}
func (app *App) HttpReqDir(w http.ResponseWriter, req *http.Request, targ string, path string) {
finx := path + "/index.html"
data, err := app.FileReadLimit(finx, 1048576);
if os.IsNotExist(err) {
app.HttpReqDir1(w, req, targ, path)
return
}
if err == app.ErrIsDir {
app.HttpReqDir1(w, req, targ, path)
return
}
if err != nil {
app.Log("Err: %s", err)
app.HttpRespForbidden(w, req, "Server error")
return
}
w.Header().Set("Content-Type", "text/html")
app.HttpRespText(w, data)
return
}
func (app *App) HttpReq(w http.ResponseWriter, req *http.Request) {
// https://go.dev/src/net/http/request.go
// fmt.Printf("Request: %+v\n", req)
var auri = (strings.Split(req.RequestURI, "/"))
auri[0] = "/"
var aidx = 0
app.Log("Auri: %+v", auri)
var locTarg map[string]interface{}
var locEnd bool
locList, err := app.ConfGetArr("http", "location")
if err != nil {
app.HttpRespForbidden(w, req, "Invalid http.location")
return
}
for uid, uri := range auri {
locEnd = false
for _, locIfc := range locList {
var locMap map[string]interface{};
switch v := locIfc.(type) {
case map[string]interface{}:
locMap = v;
}
if locMap == nil {
app.Log("Not Found")
continue
}
locUri := locMap["uri"]
if 1 == 0 {
// fmt.Printf("Found: %+v\n", locUri)
continue
}
if locUri != uri {
// fmt.Printf(" %s != %s\n", locUri, uri)
continue
}
// fmt.Printf("Found: %s\n", uri)
locTarg = locMap
locEnd = true
aidx = uid
switch v := locMap["list"].(type) {
case []interface{}:
locList = v;
// fmt.Printf("Found list\n");
}
}
if !locEnd {
break
}
}
/*
fmt.Printf("Targ %+v\n", locTarg);
fmt.Printf("Targ %+v\n", locEnd );
fmt.Printf("Targ %s \n", locTarg["uri"] );
fmt.Printf("Targ %+v\n", auri[(aidx+1):]);
*/
switch locTarg["type"] {
case "json":
targ := locTarg["targ"].(string)
app.HttpRespJson(w, locTarg[targ])
return
case "func":
targ := locTarg["targ"].(string)
parm := locTarg["parm"]
resp, err := app.CallFuncByName(targ, parm)
if err != nil {
app.Log("Err: %s", err)
break
}
app.HttpRespJson(w, resp)
return
case "directory":
targ := locTarg["targ"].(string)
path := targ + "/" + strings.Join(auri[(aidx+1):], "/")
app.Log("Location: %s", path)
data, err := app.FileReadLimit(path, 1048576);
if os.IsNotExist(err) {
break
}
if err == app.ErrIsDir {
app.HttpReqDir(w, req, targ, path)
return
}
if err != nil {
app.Log("Err: %s", err)
app.HttpRespForbidden(w, req, "Server error")
return
}
w.Header().Set("Content-Type", "text/html")
app.HttpRespText(w, data)
return
case "redirect":
http.Redirect(w, req, locTarg["targ"].(string), int(locTarg["code"].(float64)))
return
// case "ws":
}
app.HttpRespForbidden(w, req, "Invalid type")
}

View File

@@ -0,0 +1,168 @@
package cmpSnipper
import (
"time"
"net/http"
"github.com/gorilla/websocket"
)
type cmpWbsCliStruct struct {
W http.ResponseWriter
Connect *websocket.Conn
HostPort string
}
var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
HandshakeTimeout: 60 * time.Second,
}
func (app *App) HttpWebSockHand(w http.ResponseWriter, req *http.Request) {
conn, err := upgrader.Upgrade(w, req, nil)
defer conn.Close()
if err != nil {
app.Log(err)
return
}
app.Log("HttpWebSockHand:for")
HostPort := req.Header.Get("X-Real-Ip")
if HostPort == "" {
HostPort = req.Header.Get("X-Forwarded-For")
}
if HostPort == "" {
HostPort = req.RemoteAddr
}
app.Log("New client: %s", HostPort)
var cmpWbsCli cmpWbsCliStruct = cmpWbsCliStruct{
w,
conn,
HostPort,
}
app.CliList = append(app.CliList, cmpWbsCli)
app.Log(app.CliList)
for i, cli := range app.CliList {
app.Log("Client %s, %s", i, cli.HostPort)
}
for {
var inp = map[string]interface{}{}
var out = map[string]interface{}{
"snip": "",
"result": nil,
}
err := conn.ReadJSON(&inp)
if err != nil {
app.Log("Read JSON: %s", err)
app.Log(err)
var list []cmpWbsCliStruct
for _, ii := range app.CliList {
if ii.HostPort == HostPort {
continue
}
list = append(list, ii)
}
app.CliList = list
return
}
app.Log("Received message: %+v", inp)
out["snip"] = inp["snip"]
// app.Log("Copy snip OK")
var snip string;
snip = inp["snip"].(string)
// app.Log("Look snip")
if app.SnipExists(snip) {
out["result"], err = app.SnipCall(cmpWbsCli, snip, inp)
if err != nil {
out["error"] = "Server error"
}
} else {
out["error"] = "Unknown snip"
app.Log("Unknow snip:", inp["snip"])
}
err = conn.WriteJSON(out)
if err != nil {
app.Log(err)
}
// for
}
return
}
func (app *App) HttpWebSockSendTo(cmpWbsCli cmpWbsCliStruct, snip string, result map[string]interface{}) {
var err error
out := map[string]interface{}{
"snip": snip,
"result": result,
}
err = cmpWbsCli.Connect.WriteJSON(out)
if err != nil {
app.Log(err)
return
}
return
}
func (app *App) HttpWebSockSendAll(snip string, result map[string]interface{}) {
var err error
app.Log("Send to all")
out := map[string]interface{}{
"snip": snip,
"result": result,
}
for _, ii := range app.CliList {
if ii.HostPort == "" {
break
}
err = ii.Connect.WriteJSON(out)
if err != nil {
app.Log(err)
continue
}
}
return
}

View File

@@ -0,0 +1,57 @@
package cmpSnipper
import (
"fmt"
"log"
"time"
"encoding/json"
)
func (app *App) LogMod(arg interface{}) string {
var str string
switch t := arg.(type) {
case nil:
str = /* "N:" + */ "null"
case string:
str = /* "S:" + */ t
case error:
str = /* "E:" + */ t.Error()
case byte:
str = /* "B:" + */ string(t)
case []byte:
str = /* "A:" + */ string(t)
case interface{}:
obyte, _ := json.MarshalIndent(arg, "", "\t")
str = /* "J:" + */ string(obyte)
default:
str = /* "U:" + */ fmt.Sprintf("Unknown type %T", t)
}
return str
}
func (app *App) Log(farg any, iargs ...interface{}) {
var str = app.LogMod(farg)
log.SetPrefix(time.Now().UTC().Format("2006-01-02 15:04:05") + ": ")
oargs := make([]interface{}, len(iargs))
for k, arg := range iargs {
oargs[k] = app.LogMod(arg)
}
log.Output(2, fmt.Sprintf(str + "\n", oargs...))
}
func (app *App) LogSetup() {
log.SetFlags( log.Lshortfile );
}

View File

@@ -0,0 +1,84 @@
package cmpSnipper
import (
"os"
"os/signal"
"syscall"
)
func (app *App) WaitSignal(term chan bool) {
var sigreq = make(chan os.Signal, 1)
for true {
signal.Notify(sigreq)
sigrcv := <-sigreq
// app.Log("Got signal: %s", sigrcv)
if sigrcv == syscall.SIGTERM {
term <- true
// continue
return
}
if sigrcv == syscall.SIGINT {
term <- true
// continue
return
}
if sigrcv == syscall.SIGQUIT {
term <- true
// continue
return
}
if sigrcv == syscall.SIGUSR1 {
app.Log("Got signal: %s", sigrcv)
continue
}
if sigrcv == syscall.SIGUSR2 {
app.Log("Got signal: %s", sigrcv)
app.Log("Rand 4d: %d", app.Rand4d)
continue
}
// 1) SIGHUP
// 2) SIGINT
// 3) SIGQUIT
// 4) SIGILL
// 5) SIGTRAP
// 6) SIGABRT
// 7) SIGBUS
// 8) SIGFPE
// 9) SIGKILL
// 10) SIGUSR1
// 11) SIGSEGV
// 12) SIGUSR2
// 13) SIGPIPE
// 14) SIGALRM
// 15) SIGTERM
// 16) SIGSTKFLT
// 17) SIGCHLD
// 18) SIGCONT
// 19) SIGSTOP
// 20) SIGTSTP
// 21) SIGTTIN
// 22) SIGTTOU
// 23) SIGURG
// 24) SIGXCPU
// 25) SIGXFSZ
// 26) SIGVTALRM
// 27) SIGPROF
// 28) SIGWINCH
// 29) SIGIO
// 30) SIGPWR
// 31) SIGSYS
app.Log("Got signal: %s", sigrcv)
}
}

View File

@@ -0,0 +1,78 @@
package cmpSnipper
import (
"reflect"
"errors"
)
func (app *App) SnipExists(funcName string) bool {
snipName := app.UpperFirst(funcName) + "Snip"
refCls := reflect.ValueOf(app)
refMth := refCls.MethodByName(snipName)
if !refMth.IsValid() {
return false
}
return true
}
func (app *App) SnipCall(cmpWbsCli cmpWbsCliStruct, fnName string, ifcII interface{}) (interface{}, error) {
snName := app.UpperFirst(fnName) + "Snip"
refCls := reflect.ValueOf(app)
refMth := refCls.MethodByName(snName)
if !refMth.IsValid() {
app.Log("Call method \"%s\" not found", snName)
return nil, errors.New("Call method not founnd")
}
app.Log("Call method \"%s\"", snName)
ifcIM := map[string]interface{}{
"InputArgument" : ifcII,
"HostPort" : cmpWbsCli.HostPort,
}
refIL := []reflect.Value{
reflect.ValueOf(ifcIM),
}
refOL := refMth.Call(refIL)
infOI := refOL[0].Interface()
app.Log("Interface output item %+v", infOI)
return infOI, nil
}
func (app *App) SnipGetCli(parm any) (cmpWbsCliStruct, error) {
var err error
var cmpWbsCli cmpWbsCliStruct
HostPortIfc, err := app.IfcGet(parm.(map[string]interface{}), "HostPort")
if err != nil {
app.Log("Invalid iterface")
return cmpWbsCli, err
}
HostPort, ok := HostPortIfc.(string)
if !ok {
app.Log("Invalid string")
return cmpWbsCli, errors.New("Can't covert to string")
}
for _, ii := range app.CliList {
if HostPort != ii.HostPort {
continue
}
return ii, nil
}
return cmpWbsCli, errors.New("Client " + HostPort + " not found")
}

View File

@@ -0,0 +1,12 @@
package cmpSnipper
func (app *App) CliListSnip(parm any) (any, error) {
// app.Log("")
ret := map[string]interface{}{
"list" : app.CliList,
}
return ret, nil
}

View File

@@ -0,0 +1,32 @@
package cmpSnipper
import (
"encoding/json"
)
func (app *App) LeftMenuSnip(parm any) (any, error) {
// app.Log("Read data")
mainMenuFile, err := app.ConfGetStr("mainMenuFile")
if err != nil {
return nil, err
}
data, err := app.FileReadLimit(mainMenuFile, 1048576)
if err != nil {
return nil, err
}
var res = map[string]interface{}{}
err = json.Unmarshal(data, &res)
if err != nil {
return nil, err
}
return res, nil
}

View File

@@ -0,0 +1,70 @@
package cmpSnipper
import (
"os/exec"
"context"
"time"
"strings"
"syscall"
)
func (app *App) PingSnip(parm any) (any, error) {
// log.Println("PingSnip")
path, err := exec.LookPath("ping")
app.Log("Prog:", path)
if err != nil {
return map[string]interface{}{
"retval" : 127,
"error" : "No prog",
}, nil
}
ctx, cancel := context.WithTimeout(context.Background(), 10 * time.Second)
defer cancel()
cmd := exec.CommandContext(ctx, "ping", "-c", "4", "8.8.8.8")
cmd.Stdin = strings.NewReader("")
var stdout strings.Builder
cmd.Stdout = &stdout
var stderr strings.Builder
cmd.Stderr = &stderr
var exitCode int;
err = cmd.Run()
if err != nil {
// try to get the exit code
if exitError, ok := err.(*exec.ExitError); ok {
ws := exitError.Sys().(syscall.WaitStatus)
exitCode = ws.ExitStatus()
} else {
// This will happen (in OSX) if `name` is not available in $PATH,
// in this situation, exit code could not be get, and stderr will be
// empty string very likely, so we use the default fail code, and format err
// to string and set to stderr
app.Log("Could not get exit code for failed program")
exitCode = 255
}
} else {
// success, exitCode should be 0 if go is ok
ws := cmd.ProcessState.Sys().(syscall.WaitStatus)
exitCode = ws.ExitStatus()
}
return map[string]interface{}{
"retval" : exitCode,
"error" : err,
"stdout" : stdout.String(),
"stderr" : stderr.String(),
}, nil
}

View File

@@ -0,0 +1,16 @@
package cmpSnipper
import (
"math/rand"
)
func (app *App) Rand4dSnip(parm any) (any, error) {
// app.Log("Rand4dSnip")
app.Rand4d = rand.Intn(10000) + 1000
return map[string]interface{}{
"rand4d" : app.Rand4d,
}, nil
}

View File

@@ -0,0 +1,87 @@
package cmpSnipper
import (
"os"
"errors"
"strings"
"reflect"
)
func (app *App) FileReadLimit(file string, mSize int64) ([]byte, error) {
info, err := os.Stat(file)
if err != nil {
return nil, err
}
if info.IsDir() {
return nil, app.ErrIsDir
}
fSize := info.Size()
if fSize > mSize {
return nil, errors.New("File is big")
}
fd, err := os.Open(file)
if err != nil {
return nil, err
}
defer fd.Close()
var rata = make([]byte, fSize);
rSize, err := fd.Read(rata);
if fSize != int64(rSize) {
return nil, errors.New("Can't read full file size")
}
return rata, nil
}
func (app *App) UpperFirst(si string) string {
bi := []byte(si)
ss := strings.Title(string(bi[0]))
bo := bi
bo[0] = ss[0]
return string(bo)
}
func (app *App) CallFuncByName(funcName string, ifcIL ...interface{}) ([]interface{}, error) {
refCls := reflect.ValueOf(app)
refMth := refCls.MethodByName(funcName)
if !refMth.IsValid() {
app.Log("Call method \"%s\" not found", funcName)
return nil, errors.New("Call method not founnd")
}
app.Log("Call method \"%s\"", funcName)
refIL := make([]reflect.Value, len(ifcIL))
for i, ifcII := range ifcIL {
refIL[i] = reflect.ValueOf(ifcII)
}
// fmt.Println("reflect input list", refIL);
refOL := refMth.Call(refIL)
infOL := make([]interface{}, len(refOL))
for i, refOI := range refOL {
infOL[i] = refOI.Interface()
}
app.Log("Interface output list %+v", infOL)
return infOL, nil
}

View File

@@ -0,0 +1,196 @@
package cmpSnipper
import (
// "crypto/md5"
"net/http"
// "os"
"io"
// "fmt"
"bufio"
// "io/ioutil"
"bytes"
"strings"
// "golang.org/x/net/html"
// "net/url"
"encoding/json"
"compress/gzip"
"compress/flate"
"github.com/andybalholm/brotli"
)
func (app *App) HttpGet(url string) (map[string]interface{}) {
ret := map[string]interface{}{
"Error" : nil ,
"RequestUrl" : url ,
"StatusCode" : 0 ,
"ContentRaw" : nil ,
"ContentJson" : nil ,
"Header" : nil ,
"Content-Encoding" : "" ,
"Content-Type" : "" ,
"Content-Length" : "" ,
}
app.Log(url)
cli := &http.Client{}
ifcRawHead, err := app.ConfGetIfc("httpTest", "head")
if err != nil {
app.Log(err)
ret["Error"] = err
return ret
}
mapIfcHead := ifcRawHead.(map[string]interface{})
mapStrHead := make(map[string][]string)
for key, val := range mapIfcHead {
mapStrHead[key] = []string{ val.(string) }
}
req, err := http.NewRequest("GET", url, nil)
req.Header = mapStrHead
res, err := cli.Do(req)
if err != nil {
app.Log(err)
ret["Error"] = err
return ret
}
defer res.Body.Close()
if err != nil {
app.Log(err)
ret["Error"] = err
return ret
}
ret["StatusCode" ] = res.StatusCode
ret["Content-Length"] = res.ContentLength
ret["Header" ] = res.Header
// app.Log("Response status: %s", res.Status)
// app.Log("Header: %+v", res.Header)
// app.Log("TransferEncoding: %+v", res.TransferEncoding)
// app.Log("ContentLength: %+v", res.ContentLength)
var tmpl []string
tmpl = res.Header["Content-Encoding"]
if len(tmpl) > 0 {
ret["Content-Encoding"] = tmpl[0]
}
tmpl = res.Header["Content-Type"]
if len(tmpl) > 0 {
tmpl = strings.Split(tmpl[0], ";")
if len(tmpl) > 0 {
ret["Content-Type"] = tmpl[0]
}
}
// Content-Disposition: attachment; name="fieldName"; filename="myfile.txt"
out := new(bytes.Buffer)
var encReader io.Reader
switch ret["Content-Encoding"] {
case "":
encReader = bufio.NewReader(res.Body)
case "br":
encReader = brotli.NewReader(res.Body)
case "gzip":
encReader, err = gzip.NewReader(res.Body)
case "deflate":
encReader = flate.NewReader(res.Body)
default:
app.Log("Unknown Content-Encoding %s", ret["Content-Encoding"])
encReader = bufio.NewReader(res.Body)
}
if err != nil {
app.Log(err)
ret["Error"] = err
return ret
}
size, err := out.ReadFrom(encReader)
if err != nil {
app.Log(err)
ret["Error"] = err
return ret
}
app.Log("Read %s", size)
var contRaw []byte = out.Bytes()
ret["ContentRaw"] = contRaw
if ret["Content-Type"] == "application/json" {
var contJson interface{}
err = json.Unmarshal(contRaw, &contJson)
if err != nil {
app.Log(err)
ret["Error"] = err
return ret
}
ret["ContentJson"] = contJson
}
return ret
}
func (app *App) CmpHttpTestSnip(parm any) (any, error) {
var err error
cli, err := app.SnipGetCli(parm)
if err != nil {
return map[string]interface{}{
"status": "error",
"error" : "Not client found",
}, err
}
url, err := app.ConfGetStr("httpTest", "url")
if err != nil {
return map[string]interface{}{
"status": "error",
"error" : "Not test URL",
}, err
}
go func() {
var a map[string]interface{}
a = app.HttpGet(url)
app.Log(a)
app.HttpWebSockSendTo(cli, "cmpHttpTest", map[string]interface{}{
"status" : "response",
"response": a,
})
}()
return map[string]interface{}{
"status" : "request",
"request": url,
}, nil
}

View File

@@ -0,0 +1,288 @@
package cmpSnipper
import (
"io"
"bufio"
"strings"
"net"
"golang.org/x/crypto/ssh"
)
type cmpSshCliStruct struct {
Host string
Connect *ssh.Client
Session *ssh.Session
Output *bufio.Reader
}
func (app *App) SshAddHostKey(host string, remote net.Addr, pubKey ssh.PublicKey) error {
app.Log(pubKey)
return nil
}
func (app *App) SshConnReal(cmpSshCli *cmpSshCliStruct, host string, keyfile string) error {
var err error
cmpSshCli.Host = host
key, err := app.FileReadLimit(keyfile, 1048576)
if err != nil {
app.Log(err)
return err
}
signer, err := ssh.ParsePrivateKey(key)
if err != nil {
app.Log(err)
return err
}
config := &ssh.ClientConfig{
User: "root",
Auth: []ssh.AuthMethod{
// HostKeyCallback: InsecureIgnoreHostKey(),
// ssh.Password("yourpassword"),
ssh.PublicKeys(signer),
},
// HostKeyCallback: ssh.FixedHostKey(hostKey),
HostKeyCallback: ssh.HostKeyCallback(func(host string, remote net.Addr, key ssh.PublicKey) error {
app.SshAddHostKey(host, remote, key)
return nil
}),
}
cmpSshCli.Connect, err = ssh.Dial("tcp", cmpSshCli.Host, config)
if err != nil {
app.Log(err)
return err
}
return nil
}
func (app *App) SshSession(cmpSshCli *cmpSshCliStruct) error {
var err error
cmpSshCli.Session, err = cmpSshCli.Connect.NewSession()
if err != nil {
app.Log(err)
return err
}
// defer cmpSshCli.Session.Close()
modes := ssh.TerminalModes{
ssh.ECHO: 0,
}
err = cmpSshCli.Session.RequestPty("xterm", 50, 80, modes)
if err != nil {
app.Log(err)
return err
}
// sshIn, err := session.StdinPipe()
// if err != nil {
// app.Log(err)
// return err
// }
sshOut, err := cmpSshCli.Session.StdoutPipe()
if err != nil {
app.Log(err)
return err
}
sshErr, err := cmpSshCli.Session.StderrPipe()
if err != nil {
app.Log(err)
return err
}
output := io.MultiReader(sshOut, sshErr)
cmpSshCli.Output = bufio.NewReader(output)
return nil
}
func (app *App) SshConn(host string, keyfile string) (int, error) {
var err error
// app.Log(url)
var cmpSshCli cmpSshCliStruct
err = app.SshConnReal(&cmpSshCli, host, keyfile)
if err != nil {
return -1, err
}
err = app.SshSession(&cmpSshCli)
if err != nil {
return -1, err
}
app.SshList = append(app.SshList, cmpSshCli)
app.Log("Append new")
return len(app.SshList)-1, nil
}
func (app *App) SshExec(cmpWbsCli cmpWbsCliStruct, idx int, cma []string) (error) {
var err error
cmd := strings.Join(cma, " ")
cmpSshCli := app.SshList[idx]
// app.Log("idx: '%s', '%s'", idx, cmpSshCli.Host)
err = cmpSshCli.Session.Start(cmd)
if err != nil {
app.Log(err)
return err
}
res := map[string]interface{}{
"string": nil,
}
var bli []byte
var sli string
for {
bli, _, err = cmpSshCli.Output.ReadLine()
if err != nil {
app.Log("Complete")
break
}
sli = string(bli)
app.Log(sli)
res["string"] = sli
app.HttpWebSockSendTo(cmpWbsCli, "cmpSshTest", res)
}
cmpSshCli.Session.Wait()
app.Log("Free resource SshList[" + string(idx) + "]")
cmpSshCli.Session.Close()
cmpSshCli.Connect.Close()
app.Log("Remove SshList[" + string(idx) + "]")
var list []cmpSshCliStruct
for i, li := range app.SshList {
if i == idx {
continue
}
list = append(list, li)
}
app.SshList = list
app.Log("End")
// done <- true
return nil
}
func (app *App) CmpSshTestSnip(parm any) (any, error) {
var err error
// var ifcIM map[string]interface{} = parm
cli, err := app.SnipGetCli(parm)
// app.Log(cli)
if err != nil {
return map[string]interface{}{
"string": "Not client found",
}, err
}
host, err := app.ConfGetStr("sshTestHost", "HostPort")
if err != nil {
return map[string]interface{}{
"string": "Not set sshTestHost.HostPort",
}, err
}
keyfile, err := app.ConfGetStr("sshTestHost", "PrivateKeyFile")
if err != nil {
return map[string]interface{}{
"string": "Not set sshTestHost.PrivateKeyFile",
}, err
}
cmi, err := app.ConfGetIfc("sshTestHost", "Command")
if err != nil {
return map[string]interface{}{
"string": "Not set sshTestHost.Command",
}, err
}
cml := cmi.([]interface{})
cma := make([]string, len(cml))
for i, v := range cml {
cma[i] = v.(string)
}
/*
if cma[0] == "none" {
return map[string]interface{}{
"string": "Can't get command",
}, err
}
*/
idx, err := app.SshConn(host, keyfile)
if err != nil {
return map[string]interface{}{
"string": "Connection to '" + host + "' failed",
}, err
}
go func() {
app.SshExec(cli, idx, cma)
}()
app.Log("Wait")
return map[string]interface{}{
"string": "Launch: " + strings.Join(cma, " "),
}, nil
}