mirror of
https://github.com/shlldev/miniws.git
synced 2025-09-03 11:20:59 +02:00
command line arguments, merge files, comments
This commit is contained in:
24
fetch.go
24
fetch.go
@@ -1,24 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func fetchFileContents(filepath string) ([]byte, error) {
|
|
||||||
if filepath == "/" {
|
|
||||||
filepath = "."
|
|
||||||
} else {
|
|
||||||
filepath_relative, _ := strings.CutPrefix(filepath, "/")
|
|
||||||
filepath = filepath_relative
|
|
||||||
}
|
|
||||||
fileinfo, err := os.Stat(filepath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if fileinfo.IsDir() {
|
|
||||||
filepath += "/index.html"
|
|
||||||
}
|
|
||||||
return os.ReadFile(filepath)
|
|
||||||
|
|
||||||
}
|
|
5
go.mod
Normal file
5
go.mod
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
module com.github/shlldev/miniws
|
||||||
|
|
||||||
|
go 1.22.2
|
||||||
|
|
||||||
|
require github.com/akamensky/argparse v1.4.0 // indirect
|
2
go.sum
Normal file
2
go.sum
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
github.com/akamensky/argparse v1.4.0 h1:YGzvsTqCvbEZhL8zZu2AiA5nq805NZh75JNj4ajn1xc=
|
||||||
|
github.com/akamensky/argparse v1.4.0/go.mod h1:S5kwC7IuDcEr5VeXtGPRVZ5o/FdhcMlQz4IZQuw64xA=
|
11
index.html
Normal file
11
index.html
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body style="background-color: black;">
|
||||||
|
<h1 style="color: wheat;">
|
||||||
|
test
|
||||||
|
</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
62
log.go
62
log.go
@@ -1,62 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func logIfError(err error) bool {
|
|
||||||
if err != nil {
|
|
||||||
logError(err.Error())
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// func logAccess(
|
|
||||||
// remoteAddr, remoteUser, timeLocal, request, status,
|
|
||||||
// bodyBytesSent, httpReferrer, httpUseragent string,
|
|
||||||
// ) {
|
|
||||||
// out := fmt.Sprintf("%v - %v - [%v] \"%v\" %v %v \"%v\" \"%v\"\n",
|
|
||||||
// remoteAddr, remoteUser, timeLocal, request, status, bodyBytesSent,
|
|
||||||
// httpReferrer, httpUseragent,
|
|
||||||
// )
|
|
||||||
// file, err := os.OpenFile(PATH_ACCESSLOG, os.O_APPEND|os.O_WRONLY, os.ModeType)
|
|
||||||
// if err != nil {
|
|
||||||
// log.Println("couldn't open log access file at", PATH_ACCESSLOG)
|
|
||||||
// }
|
|
||||||
// defer file.Close()
|
|
||||||
// file.WriteString(out)
|
|
||||||
// }
|
|
||||||
|
|
||||||
func logAccess(
|
|
||||||
remoteAddr, identifier, authuser, timestamp, request,
|
|
||||||
status, bytesSent string,
|
|
||||||
) {
|
|
||||||
out := fmt.Sprintf("%v %v %v [%v] \"%v\" %v %v\n",
|
|
||||||
remoteAddr, identifier, authuser, timestamp, request, status, bytesSent,
|
|
||||||
)
|
|
||||||
file, err := os.OpenFile(PATH_ACCESSLOG, os.O_APPEND|os.O_WRONLY, os.ModeType)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("couldn't open log access file at", PATH_ACCESSLOG)
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
file.WriteString(out)
|
|
||||||
}
|
|
||||||
|
|
||||||
func logError(str string) {
|
|
||||||
file, err := os.OpenFile(PATH_ERRORLOG, os.O_APPEND|os.O_WRONLY, os.ModeType)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("couldn't open log error file at", PATH_ACCESSLOG)
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
file.WriteString(str + "\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
func getOrDash(str string) string {
|
|
||||||
if str == "" {
|
|
||||||
return "-"
|
|
||||||
}
|
|
||||||
return str
|
|
||||||
}
|
|
112
main.go
112
main.go
@@ -1,28 +1,52 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/akamensky/argparse"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
PATH_ACCESSLOG string = "access.log"
|
PATH_ACCESSLOG string = "access.log"
|
||||||
PATH_ERRORLOG string = "error.log"
|
PATH_ERRORLOG string = "error.log"
|
||||||
|
FLAGS_LOG_OPEN int = os.O_APPEND | os.O_WRONLY | os.O_CREATE
|
||||||
|
PERMS_LOG_OPEN os.FileMode = os.ModeType | os.ModePerm
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var _logFolder string = ""
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
|
parser := argparse.NewParser("miniws", "")
|
||||||
|
port := parser.String("p", "port", &argparse.Options{Default: "8040"})
|
||||||
|
logFolder := parser.String("l", "logs-folder", &argparse.Options{Default: "logs"})
|
||||||
|
|
||||||
|
err := parser.Parse(os.Args)
|
||||||
|
if err != nil {
|
||||||
|
// In case of error print error and print usage
|
||||||
|
// This can also be done by passing -h or --help flags
|
||||||
|
fmt.Print(parser.Usage(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
_logFolder = *logFolder
|
||||||
|
|
||||||
http.HandleFunc("/{resource...}", get)
|
http.HandleFunc("/{resource...}", get)
|
||||||
log.Println("Server started")
|
log.Println("Server started on port " + *port)
|
||||||
http.ListenAndServe(":8080", nil)
|
http.ListenAndServe(":"+*port, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func get(writer http.ResponseWriter, req *http.Request) {
|
func get(writer http.ResponseWriter, req *http.Request) {
|
||||||
fetchedData, fetchErr := fetchFileContents(req.URL.Path)
|
fetchedData, fetchErr := fetchFileContents(req.URL.Path)
|
||||||
respStatusCode := int(200)
|
|
||||||
var sentBytes int = 0
|
sentBytes := 0
|
||||||
|
respStatusCode := http.StatusOK
|
||||||
|
|
||||||
if logIfError(fetchErr) {
|
if logIfError(fetchErr) {
|
||||||
respStatusCode = http.StatusNotFound
|
respStatusCode = http.StatusNotFound
|
||||||
writer.WriteHeader(respStatusCode)
|
writer.WriteHeader(respStatusCode)
|
||||||
@@ -30,12 +54,86 @@ func get(writer http.ResponseWriter, req *http.Request) {
|
|||||||
sentBytesCount, _ := writer.Write(fetchedData)
|
sentBytesCount, _ := writer.Write(fetchedData)
|
||||||
sentBytes = sentBytesCount
|
sentBytes = sentBytesCount
|
||||||
}
|
}
|
||||||
logAccess(strings.Split(req.RemoteAddr, ":")[0], "-", getOrDash(req.URL.User.Username()), time.Now().Format("02/Jan/2006:03:04:05 -0700"),
|
|
||||||
req.Method+" "+req.URL.Path+" "+getHttpString(req.ProtoMajor, req.ProtoMinor), strconv.Itoa(respStatusCode),
|
logAccess(
|
||||||
strconv.Itoa(sentBytes),
|
strings.Split(req.RemoteAddr, ":")[0], //remote address
|
||||||
|
"-", //identifier (can't get)
|
||||||
|
getOrDash(req.URL.User.Username()), //username
|
||||||
|
time.Now().Format("02/Jan/2006:15:04:05 -0700"), //timestamp
|
||||||
|
req.Method+" "+req.URL.Path+" "+getHttpString(req.ProtoMajor, req.ProtoMinor), //HTTP version
|
||||||
|
strconv.Itoa(respStatusCode), //response code
|
||||||
|
strconv.Itoa(sentBytes), //# of sent bytes
|
||||||
|
req.Referer(), //Referer
|
||||||
|
req.UserAgent(), //User Agent
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fetchFileContents(filepath string) ([]byte, error) {
|
||||||
|
if filepath == "/" {
|
||||||
|
filepath = "."
|
||||||
|
} else {
|
||||||
|
filepath_relative, _ := strings.CutPrefix(filepath, "/")
|
||||||
|
filepath = filepath_relative
|
||||||
|
}
|
||||||
|
fileinfo, err := os.Stat(filepath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if fileinfo.IsDir() {
|
||||||
|
filepath += "/index.html"
|
||||||
|
}
|
||||||
|
return os.ReadFile(filepath)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns error != nil
|
||||||
|
func logIfError(err error) bool {
|
||||||
|
if err != nil {
|
||||||
|
logError(err.Error())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func logAccess(
|
||||||
|
remoteAddr, identifier, authuser, timestamp, request,
|
||||||
|
status, bytesSent, referer, user_agent string,
|
||||||
|
) {
|
||||||
|
out := fmt.Sprintf("%v %v %v [%v] \"%v\" %v %v \"%v\" \"%v\"\n",
|
||||||
|
remoteAddr, identifier, authuser, timestamp, request, status, bytesSent, referer, user_agent,
|
||||||
|
)
|
||||||
|
os.Mkdir(_logFolder, os.ModeDir|os.ModePerm)
|
||||||
|
file, err := os.OpenFile(assureSlash(_logFolder)+PATH_ACCESSLOG, FLAGS_LOG_OPEN, PERMS_LOG_OPEN)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println("couldn't open log access file at", assureSlash(_logFolder)+PATH_ACCESSLOG)
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
file.WriteString(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
func logError(str string) {
|
||||||
|
file, err := os.OpenFile(assureSlash(_logFolder)+PATH_ERRORLOG, FLAGS_LOG_OPEN, PERMS_LOG_OPEN)
|
||||||
|
os.Mkdir(_logFolder, os.ModeDir|os.ModePerm)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println("couldn't open log error file at", assureSlash(_logFolder)+PATH_ERRORLOG)
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
file.WriteString(str + "\n")
|
||||||
|
}
|
||||||
|
|
||||||
func getHttpString(major, minor int) string {
|
func getHttpString(major, minor int) string {
|
||||||
return "HTTP/" + strconv.Itoa(major) + "." + strconv.Itoa(minor)
|
return "HTTP/" + strconv.Itoa(major) + "." + strconv.Itoa(minor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getOrDash(str string) string {
|
||||||
|
if str == "" {
|
||||||
|
return "-"
|
||||||
|
}
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
func assureSlash(str string) string {
|
||||||
|
return strings.TrimSuffix(str, "/") + "/"
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user