feat: basic file handling

This commit is contained in:
2026-02-15 16:31:49 +01:00
parent fccc976b4e
commit f85afce949
4 changed files with 142 additions and 4 deletions

115
http_handle.go Normal file
View File

@@ -0,0 +1,115 @@
package main
import (
"bufio"
"errors"
"fmt"
"io"
"io/fs"
"log/slog"
"mime"
"net"
"os"
"path"
"strings"
"tilok.dev/go-http-server/config"
rh "tilok.dev/go-http-server/response_helper"
)
func HandleHTTPRequest(headers Headers, conn net.Conn) {
if strings.Contains(headers.Uri, "..") {
conn.Write([]byte("HTTP/1.1 403 Fuck you\r\n\r\n"))
conn.Close()
return
}
config := config.GetConfig()
_, err := os.Stat(config.Htdocs)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
CreateDefaultHtdocs(config.Htdocs)
} else {
slog.Error("Failed to stat directory", "error", err)
panic("Failed to stat directory")
}
}
desiredPath := path.Join(config.Htdocs, headers.Uri)
if headers.Uri == "/" {
desiredPath = path.Join(config.Htdocs, "index.html")
}
file, err := os.Open(desiredPath)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
rh.RespondWithStatusCode(404, conn)
return
}
if errors.Is(err, fs.ErrPermission) {
rh.RespondWithStatusCode(403, conn)
return
}
slog.Error("Unhandled error case", "err", err)
rh.RespondWithStatusCode(500, conn)
return
}
defer file.Close()
sendFile(file, conn)
conn.Close()
}
func sendFile(file *os.File, conn net.Conn) {
reader := bufio.NewReader(file)
defer file.Close()
fileStat, err := file.Stat()
if err != nil {
slog.Error("Failed to stat file", "error", err)
rh.RespondWithStatusCode(500, conn)
return
}
parts := strings.Split(fileStat.Name(), ".")
ext := "." + parts[len(parts)-1]
mime_type := mime.TypeByExtension(ext)
length := fileStat.Size()
if mime_type == "" {
mime_type = "application/octet-stream"
}
header := fmt.Sprintf("HTTP/1.1 200 OK\r\nContent-Type: %s\r\nContent-Length: %d\r\nServer: Tilo's Go HTTP Server\r\n\r\n", mime_type, length)
conn.Write([]byte(header))
buf := make([]byte, 4096)
for {
n, err := reader.Read(buf)
if err != nil {
if err == io.EOF {
break
}
slog.Error("Failed to read file", "error", err)
rh.RespondWithStatusCode(500, conn)
return
}
conn.Write(buf[:n])
}
}
func CreateDefaultHtdocs(dirPath string) error {
err := os.MkdirAll(dirPath, 0755)
if err != nil {
return err
}
err = os.WriteFile(path.Join(dirPath, "index.html"), []byte("<DOCTYPE html><html><head><title>Hello World</title></head><body><h1>Hello World</h1></body></html>"), 0644)
if err != nil {
return err
}
return nil
}