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
|
||||||
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.
|
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
|
## command line arguments
|
||||||
```
|
```
|
||||||
-h --help Print help information
|
-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.
|
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
|
## logging
|
||||||
|
|
||||||
in your logging folder you will find `access.log` and `errors.log`
|
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 (
|
use (
|
||||||
.
|
.
|
||||||
./miniws
|
./miniws
|
||||||
./miniws/sockets
|
./miniws/ipc
|
||||||
./miniws/sockets/logplus
|
|
||||||
)
|
)
|
4
main.go
4
main.go
@@ -2,8 +2,8 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"ipc"
|
||||||
"os"
|
"os"
|
||||||
"sockets"
|
|
||||||
|
|
||||||
"miniws"
|
"miniws"
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ func main() {
|
|||||||
|
|
||||||
// signal mode
|
// signal mode
|
||||||
if *signal != "" {
|
if *signal != "" {
|
||||||
client := sockets.Client{}
|
client := ipc.Client{}
|
||||||
client.OneShotWrite("unix", miniws.SOCKET_PATH, []byte(*signal))
|
client.OneShotWrite("unix", miniws.SOCKET_PATH, []byte(*signal))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@@ -2,5 +2,5 @@ go 1.24.5
|
|||||||
|
|
||||||
use (
|
use (
|
||||||
.
|
.
|
||||||
./sockets
|
./ipc
|
||||||
)
|
)
|
@@ -1,4 +1,4 @@
|
|||||||
package sockets
|
package ipc
|
||||||
|
|
||||||
type buffer []byte
|
type buffer []byte
|
||||||
|
|
@@ -1,9 +1,8 @@
|
|||||||
package sockets
|
package ipc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"log"
|
"log"
|
||||||
"logplus"
|
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
@@ -12,7 +11,7 @@ type Client struct{}
|
|||||||
|
|
||||||
func (c *Client) Start(network, address string) {
|
func (c *Client) Start(network, address string) {
|
||||||
conn, err := net.Dial(network, address)
|
conn, err := net.Dial(network, address)
|
||||||
logplus.LogIfErrorFatal(err)
|
LogIfErrorFatal(err)
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
buffer := make(buffer, 1<<12)
|
buffer := make(buffer, 1<<12)
|
||||||
@@ -20,25 +19,25 @@ func (c *Client) Start(network, address string) {
|
|||||||
for {
|
for {
|
||||||
buffer.Zero()
|
buffer.Zero()
|
||||||
scanner.Scan()
|
scanner.Scan()
|
||||||
logplus.LogIfErrorFatal(scanner.Err())
|
LogIfErrorFatal(scanner.Err())
|
||||||
buffer = []byte(scanner.Text())
|
buffer = []byte(scanner.Text())
|
||||||
_, err := conn.Write(buffer)
|
_, err := conn.Write(buffer)
|
||||||
logplus.LogIfErrorFatal(err)
|
LogIfErrorFatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) OneShotWrite(network, address string, content []byte) {
|
func (c *Client) OneShotWrite(network, address string, content []byte) {
|
||||||
conn, err := net.Dial(network, address)
|
conn, err := net.Dial(network, address)
|
||||||
logplus.LogIfErrorFatal(err)
|
LogIfErrorFatal(err)
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
//will recieve a byte
|
//will recieve a byte
|
||||||
buffer := make(buffer, 1)
|
buffer := make(buffer, 1)
|
||||||
|
|
||||||
_, err = conn.Write(content)
|
_, err = conn.Write(content)
|
||||||
logplus.LogIfErrorFatal(err)
|
LogIfErrorFatal(err)
|
||||||
_, err = conn.Read(buffer)
|
_, err = conn.Read(buffer)
|
||||||
logplus.LogIfErrorFatal(err)
|
LogIfErrorFatal(err)
|
||||||
if buffer[0] == byte(0) {
|
if buffer[0] == byte(0) {
|
||||||
log.Println("Signal", string(content), "doesn't exist!")
|
log.Println("Signal", string(content), "doesn't exist!")
|
||||||
return
|
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"
|
import "log"
|
||||||
|
|
@@ -1,8 +1,7 @@
|
|||||||
package sockets
|
package ipc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"logplus"
|
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
@@ -14,7 +13,7 @@ type Server struct{}
|
|||||||
|
|
||||||
func (s *Server) Start(recvBind func(string, []string) bool, network, address string) int {
|
func (s *Server) Start(recvBind func(string, []string) bool, network, address string) int {
|
||||||
socket, err := net.Listen(network, address)
|
socket, err := net.Listen(network, address)
|
||||||
logplus.LogIfErrorFatal(err)
|
LogIfErrorFatal(err)
|
||||||
|
|
||||||
//Cleanup the socket file
|
//Cleanup the socket file
|
||||||
c := make(chan os.Signal, 1)
|
c := make(chan os.Signal, 1)
|
||||||
@@ -29,7 +28,7 @@ func (s *Server) Start(recvBind func(string, []string) bool, network, address st
|
|||||||
|
|
||||||
//Accept connection
|
//Accept connection
|
||||||
conn, err := socket.Accept()
|
conn, err := socket.Accept()
|
||||||
logplus.LogIfErrorFatal(err)
|
LogIfErrorFatal(err)
|
||||||
|
|
||||||
//Handle the connection
|
//Handle the connection
|
||||||
//in a separate goroutine
|
//in a separate goroutine
|
||||||
@@ -46,20 +45,17 @@ func (s *Server) Start(recvBind func(string, []string) bool, network, address st
|
|||||||
conn.Close()
|
conn.Close()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
logplus.LogIfErrorFatal(err)
|
LogIfErrorFatal(err)
|
||||||
fullstring := string(buffer)
|
fullstring := string(buffer)
|
||||||
arguments := strings.Split(fullstring, " ")
|
arguments := strings.Split(fullstring, " ")
|
||||||
ret := recvBind(arguments[0], arguments[1:])
|
ret := recvBind(arguments[0], arguments[1:])
|
||||||
conn.Write([]byte{bool2byte(ret)})
|
if ret {
|
||||||
|
conn.Write([]byte{1})
|
||||||
|
} else {
|
||||||
|
conn.Write([]byte{0})
|
||||||
|
}
|
||||||
buffer.Zero()
|
buffer.Zero()
|
||||||
}
|
}
|
||||||
}(conn)
|
}(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 (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
|
"ipc"
|
||||||
"log"
|
"log"
|
||||||
"mime"
|
"mime"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"slices"
|
"slices"
|
||||||
"sockets"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -18,6 +18,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
FILTER_MODE_INVALID FilterMode = -1
|
||||||
FILTER_MODE_WHITELIST FilterMode = 0
|
FILTER_MODE_WHITELIST FilterMode = 0
|
||||||
FILTER_MODE_BLACKLIST FilterMode = 1
|
FILTER_MODE_BLACKLIST FilterMode = 1
|
||||||
|
|
||||||
@@ -67,24 +68,37 @@ func (ws *WebServer) Run() {
|
|||||||
log.Fatalln("Fatal: missing permissions to read www folder")
|
log.Fatalln("Fatal: missing permissions to read www folder")
|
||||||
}
|
}
|
||||||
|
|
||||||
ws.ipFilterMode, ws.ipFilter = ws.parseFilterPanics(FILENAME_IPFILTER)
|
ipFilterMode, ipFilter, err := ws.parseFilter(FILENAME_IPFILTER)
|
||||||
ws.userAgentFilterMode, ws.userAgentFilter = ws.parseFilterPanics(FILENAME_USERAGENTFILTER)
|
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>)
|
// create and start a unix socket server (to accept signal from another process using -s <cmd>)
|
||||||
socketserver := sockets.Server{}
|
ipcServer := ipc.Server{}
|
||||||
go socketserver.Start(ws.recvBind, "unix", SOCKET_PATH)
|
go ipcServer.Start(ws.onRecieveSignal, "unix", SOCKET_PATH)
|
||||||
|
|
||||||
http.HandleFunc("/", ws.get)
|
http.HandleFunc("/", ws.get)
|
||||||
log.Println("Server started on port " + strconv.Itoa(ws.port))
|
log.Println("Server starting on port " + strconv.Itoa(ws.port) + "...")
|
||||||
http.ListenAndServe(":"+strconv.Itoa(ws.port), nil)
|
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"))
|
command = string(bytes.Trim([]byte(command), "\x00"))
|
||||||
switch command {
|
switch command {
|
||||||
case "reload":
|
case "reload":
|
||||||
ws.parseFilterPanics(FILENAME_IPFILTER)
|
ws.parseFilter(FILENAME_IPFILTER)
|
||||||
ws.parseFilterPanics(FILENAME_USERAGENTFILTER)
|
ws.parseFilter(FILENAME_USERAGENTFILTER)
|
||||||
return true
|
return true
|
||||||
default:
|
default:
|
||||||
log.Println("Error: unknown command", command, arguments)
|
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)
|
log.Println("loaded filter: ", fileName)
|
||||||
|
|
||||||
@@ -109,17 +123,19 @@ func (ws *WebServer) parseFilterPanics(fileName string) (FilterMode, []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
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
|
if fileinfo.Size() == 0 { // empty config
|
||||||
return filterMode, filter
|
return filterMode, filter, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
filterContent, err := os.ReadFile(fullPath)
|
filterContent, err := os.ReadFile(fullPath)
|
||||||
|
|
||||||
if ws.logger.logIfError(err, 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")
|
lines := strings.Split(string(filterContent), "\n")
|
||||||
@@ -142,10 +158,11 @@ func (ws *WebServer) parseFilterPanics(fileName string) (FilterMode, []string) {
|
|||||||
case "deny":
|
case "deny":
|
||||||
filterMode = FILTER_MODE_BLACKLIST
|
filterMode = FILTER_MODE_BLACKLIST
|
||||||
default:
|
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