mirror of
https://github.com/shlldev/miniws.git
synced 2025-09-02 19:00:59 +02:00
small refactor, add available signals to README
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
# miniws
|
||||
miniws (minimal web server) is a very simple web server written in golang. its purpose is to be lightweight, easy to configure and easily expandable for personal use.
|
||||
|
||||
all the help you'll ever need is in this README, and in the help text (`miniws -h`). there is no other documentation you have to read.
|
||||
|
||||
## command line arguments
|
||||
```
|
||||
-h --help Print help information
|
||||
@@ -21,6 +23,10 @@ in your config folder you will find `ipfilter.conf` and `useragentfilter.conf`
|
||||
|
||||
both files use the same format: specify `allow|deny` in the first line to tell miniws to treat the file as a whitelist or a blacklist, then specify one ip/user-agent per line.
|
||||
|
||||
## signals
|
||||
you can pass the following signals when using -s:
|
||||
- `reload`: reloads the configuration files from disk
|
||||
|
||||
## logging
|
||||
|
||||
in your logging folder you will find `access.log` and `errors.log`
|
||||
|
3
go.work
3
go.work
@@ -3,6 +3,5 @@ go 1.24.5
|
||||
use (
|
||||
.
|
||||
./miniws
|
||||
./miniws/sockets
|
||||
./miniws/sockets/logplus
|
||||
./miniws/ipc
|
||||
)
|
4
main.go
4
main.go
@@ -2,8 +2,8 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"ipc"
|
||||
"os"
|
||||
"sockets"
|
||||
|
||||
"miniws"
|
||||
|
||||
@@ -44,7 +44,7 @@ func main() {
|
||||
|
||||
// signal mode
|
||||
if *signal != "" {
|
||||
client := sockets.Client{}
|
||||
client := ipc.Client{}
|
||||
client.OneShotWrite("unix", miniws.SOCKET_PATH, []byte(*signal))
|
||||
return
|
||||
}
|
||||
|
@@ -2,5 +2,5 @@ go 1.24.5
|
||||
|
||||
use (
|
||||
.
|
||||
./sockets
|
||||
./ipc
|
||||
)
|
@@ -1,4 +1,4 @@
|
||||
package sockets
|
||||
package ipc
|
||||
|
||||
type buffer []byte
|
||||
|
@@ -1,9 +1,8 @@
|
||||
package sockets
|
||||
package ipc
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"log"
|
||||
"logplus"
|
||||
"net"
|
||||
"os"
|
||||
)
|
||||
@@ -12,7 +11,7 @@ type Client struct{}
|
||||
|
||||
func (c *Client) Start(network, address string) {
|
||||
conn, err := net.Dial(network, address)
|
||||
logplus.LogIfErrorFatal(err)
|
||||
LogIfErrorFatal(err)
|
||||
defer conn.Close()
|
||||
|
||||
buffer := make(buffer, 1<<12)
|
||||
@@ -20,25 +19,25 @@ func (c *Client) Start(network, address string) {
|
||||
for {
|
||||
buffer.Zero()
|
||||
scanner.Scan()
|
||||
logplus.LogIfErrorFatal(scanner.Err())
|
||||
LogIfErrorFatal(scanner.Err())
|
||||
buffer = []byte(scanner.Text())
|
||||
_, err := conn.Write(buffer)
|
||||
logplus.LogIfErrorFatal(err)
|
||||
LogIfErrorFatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) OneShotWrite(network, address string, content []byte) {
|
||||
conn, err := net.Dial(network, address)
|
||||
logplus.LogIfErrorFatal(err)
|
||||
LogIfErrorFatal(err)
|
||||
defer conn.Close()
|
||||
|
||||
//will recieve a byte
|
||||
buffer := make(buffer, 1)
|
||||
|
||||
_, err = conn.Write(content)
|
||||
logplus.LogIfErrorFatal(err)
|
||||
LogIfErrorFatal(err)
|
||||
_, err = conn.Read(buffer)
|
||||
logplus.LogIfErrorFatal(err)
|
||||
LogIfErrorFatal(err)
|
||||
if buffer[0] == byte(0) {
|
||||
log.Println("Signal", string(content), "doesn't exist!")
|
||||
return
|
3
miniws/ipc/go.mod
Normal file
3
miniws/ipc/go.mod
Normal file
@@ -0,0 +1,3 @@
|
||||
module ipc
|
||||
|
||||
go 1.24.5
|
@@ -1,4 +1,4 @@
|
||||
package logplus
|
||||
package ipc
|
||||
|
||||
import "log"
|
||||
|
@@ -1,8 +1,7 @@
|
||||
package sockets
|
||||
package ipc
|
||||
|
||||
import (
|
||||
"io"
|
||||
"logplus"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
@@ -14,7 +13,7 @@ type Server struct{}
|
||||
|
||||
func (s *Server) Start(recvBind func(string, []string) bool, network, address string) int {
|
||||
socket, err := net.Listen(network, address)
|
||||
logplus.LogIfErrorFatal(err)
|
||||
LogIfErrorFatal(err)
|
||||
|
||||
//Cleanup the socket file
|
||||
c := make(chan os.Signal, 1)
|
||||
@@ -29,7 +28,7 @@ func (s *Server) Start(recvBind func(string, []string) bool, network, address st
|
||||
|
||||
//Accept connection
|
||||
conn, err := socket.Accept()
|
||||
logplus.LogIfErrorFatal(err)
|
||||
LogIfErrorFatal(err)
|
||||
|
||||
//Handle the connection
|
||||
//in a separate goroutine
|
||||
@@ -46,20 +45,17 @@ func (s *Server) Start(recvBind func(string, []string) bool, network, address st
|
||||
conn.Close()
|
||||
break
|
||||
}
|
||||
logplus.LogIfErrorFatal(err)
|
||||
LogIfErrorFatal(err)
|
||||
fullstring := string(buffer)
|
||||
arguments := strings.Split(fullstring, " ")
|
||||
ret := recvBind(arguments[0], arguments[1:])
|
||||
conn.Write([]byte{bool2byte(ret)})
|
||||
if ret {
|
||||
conn.Write([]byte{1})
|
||||
} else {
|
||||
conn.Write([]byte{0})
|
||||
}
|
||||
buffer.Zero()
|
||||
}
|
||||
}(conn)
|
||||
}
|
||||
}
|
||||
|
||||
func bool2byte(b bool) byte {
|
||||
if b {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
module sockets
|
||||
|
||||
go 1.24.5
|
@@ -1,6 +0,0 @@
|
||||
go 1.24.5
|
||||
|
||||
use (
|
||||
.
|
||||
./logplus
|
||||
)
|
@@ -1,3 +0,0 @@
|
||||
module logplus
|
||||
|
||||
go 1.22.2
|
@@ -3,13 +3,13 @@ package miniws
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"ipc"
|
||||
"log"
|
||||
"mime"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"sockets"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
FILTER_MODE_INVALID FilterMode = -1
|
||||
FILTER_MODE_WHITELIST FilterMode = 0
|
||||
FILTER_MODE_BLACKLIST FilterMode = 1
|
||||
|
||||
@@ -67,24 +68,37 @@ func (ws *WebServer) Run() {
|
||||
log.Fatalln("Fatal: missing permissions to read www folder")
|
||||
}
|
||||
|
||||
ws.ipFilterMode, ws.ipFilter = ws.parseFilterPanics(FILENAME_IPFILTER)
|
||||
ws.userAgentFilterMode, ws.userAgentFilter = ws.parseFilterPanics(FILENAME_USERAGENTFILTER)
|
||||
ipFilterMode, ipFilter, err := ws.parseFilter(FILENAME_IPFILTER)
|
||||
if err != nil {
|
||||
log.Fatalln("Fatal: IP filter invalid:", err)
|
||||
}
|
||||
ws.ipFilterMode = ipFilterMode
|
||||
ws.ipFilter = ipFilter
|
||||
userAgentFilterMode, userAgentFilter, err := ws.parseFilter(FILENAME_USERAGENTFILTER)
|
||||
if err != nil {
|
||||
log.Fatalln("Fatal: UserAgent filter invalid:", err)
|
||||
}
|
||||
ws.userAgentFilter = userAgentFilter
|
||||
ws.userAgentFilterMode = userAgentFilterMode
|
||||
|
||||
// create and start a unix socket server (to accept signal from another process using -s <cmd>)
|
||||
socketserver := sockets.Server{}
|
||||
go socketserver.Start(ws.recvBind, "unix", SOCKET_PATH)
|
||||
ipcServer := ipc.Server{}
|
||||
go ipcServer.Start(ws.onRecieveSignal, "unix", SOCKET_PATH)
|
||||
|
||||
http.HandleFunc("/", ws.get)
|
||||
log.Println("Server started on port " + strconv.Itoa(ws.port))
|
||||
http.ListenAndServe(":"+strconv.Itoa(ws.port), nil)
|
||||
log.Println("Server starting on port " + strconv.Itoa(ws.port) + "...")
|
||||
httpErr := http.ListenAndServe(":"+strconv.Itoa(ws.port), nil)
|
||||
if httpErr != nil {
|
||||
log.Fatalln(httpErr)
|
||||
}
|
||||
}
|
||||
|
||||
func (ws *WebServer) recvBind(command string, arguments []string) bool {
|
||||
func (ws *WebServer) onRecieveSignal(command string, arguments []string) bool {
|
||||
command = string(bytes.Trim([]byte(command), "\x00"))
|
||||
switch command {
|
||||
case "reload":
|
||||
ws.parseFilterPanics(FILENAME_IPFILTER)
|
||||
ws.parseFilterPanics(FILENAME_USERAGENTFILTER)
|
||||
ws.parseFilter(FILENAME_IPFILTER)
|
||||
ws.parseFilter(FILENAME_USERAGENTFILTER)
|
||||
return true
|
||||
default:
|
||||
log.Println("Error: unknown command", command, arguments)
|
||||
@@ -92,7 +106,7 @@ func (ws *WebServer) recvBind(command string, arguments []string) bool {
|
||||
}
|
||||
}
|
||||
|
||||
func (ws *WebServer) parseFilterPanics(fileName string) (FilterMode, []string) {
|
||||
func (ws *WebServer) parseFilter(fileName string) (FilterMode, []string, error) {
|
||||
|
||||
log.Println("loaded filter: ", fileName)
|
||||
|
||||
@@ -109,17 +123,19 @@ func (ws *WebServer) parseFilterPanics(fileName string) (FilterMode, []string) {
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
panic("Error opening " + fileName + ": " + err.Error())
|
||||
return FILTER_MODE_INVALID, nil,
|
||||
errors.New("Error opening " + fileName + ": " + err.Error())
|
||||
}
|
||||
|
||||
if fileinfo.Size() == 0 { // empty config
|
||||
return filterMode, filter
|
||||
return filterMode, filter, nil
|
||||
}
|
||||
|
||||
filterContent, err := os.ReadFile(fullPath)
|
||||
|
||||
if ws.logger.logIfError(err, fullPath) {
|
||||
panic("Error reading " + fileName + ": " + err.Error())
|
||||
return FILTER_MODE_INVALID, nil,
|
||||
errors.New("Error reading " + fileName + ": " + err.Error())
|
||||
}
|
||||
|
||||
lines := strings.Split(string(filterContent), "\n")
|
||||
@@ -142,10 +158,11 @@ func (ws *WebServer) parseFilterPanics(fileName string) (FilterMode, []string) {
|
||||
case "deny":
|
||||
filterMode = FILTER_MODE_BLACKLIST
|
||||
default:
|
||||
panic("invalid filter mode for " + fileName + ": use allow|deny")
|
||||
return FILTER_MODE_INVALID, nil,
|
||||
errors.New("invalid filter mode for " + fileName + ": use allow|deny")
|
||||
}
|
||||
|
||||
return filterMode, filter
|
||||
return filterMode, filter, nil
|
||||
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user