Inital commit
This commit is contained in:
43
main.go
Normal file
43
main.go
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"log/slog"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
rh "tilok.dev/go-http-server/response_helper"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
//TODO: Make interface configurable
|
||||||
|
interf := "127.0.0.1:8080"
|
||||||
|
listener, err := net.Listen("tcp", interf)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("Could not create listener", "err", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
defer listener.Close()
|
||||||
|
|
||||||
|
for {
|
||||||
|
conn, err := listener.Accept()
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("Could not accept connection", "err", err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
go handleConnection(conn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleConnection(conn net.Conn) {
|
||||||
|
defer conn.Close()
|
||||||
|
reader := bufio.NewReader(conn)
|
||||||
|
headers := readHeaders(reader)
|
||||||
|
if headers == nil {
|
||||||
|
rh.RespondWithStatusCode(400, conn)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
slog.Info("Received request", "method", headers.Method, "uri", headers.Uri, "proto", headers.Proto, "client", conn.RemoteAddr().String())
|
||||||
|
headers.debugPrintHeaders()
|
||||||
|
}
|
||||||
71
readheaders.go
Normal file
71
readheaders.go
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Headers struct {
|
||||||
|
Method string
|
||||||
|
Uri string
|
||||||
|
Proto string
|
||||||
|
|
||||||
|
KV map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
func readHeaders(reader *bufio.Reader) *Headers {
|
||||||
|
headers := Headers{}
|
||||||
|
kvHeaders := make(map[string]string)
|
||||||
|
versionLine, err := reader.ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("Could not read version line", "err", err.Error())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
method, uri, proto := parseRequestLine(versionLine)
|
||||||
|
if method == "" || uri == "" || proto == "" {
|
||||||
|
slog.Error("Invalid request line", "line", versionLine)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
headers.Method = method
|
||||||
|
headers.Uri = uri
|
||||||
|
headers.Proto = proto
|
||||||
|
|
||||||
|
headerStr, err := reader.ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("Could not read headers", "err", err.Error())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for strings.TrimSpace(headerStr) != "" {
|
||||||
|
header := strings.SplitN(headerStr, ":", 2)
|
||||||
|
if len(header) == 2 {
|
||||||
|
kvHeaders[strings.TrimSpace(header[0])] = strings.TrimSpace(header[1])
|
||||||
|
}
|
||||||
|
headerStr, err = reader.ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("Could not read headers", "err", err.Error())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
headers.KV = kvHeaders
|
||||||
|
return &headers
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Headers) debugPrintHeaders() {
|
||||||
|
for key, value := range m.KV {
|
||||||
|
fmt.Printf("%s: %s\n", key, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseRequestLine(versionLine string) (string, string, string) {
|
||||||
|
cleanLine := strings.TrimSpace(versionLine)
|
||||||
|
parts := strings.Split(cleanLine, " ")
|
||||||
|
if len(parts) != 3 {
|
||||||
|
return "", "", ""
|
||||||
|
}
|
||||||
|
return parts[0], parts[1], parts[2]
|
||||||
|
}
|
||||||
14
response_helper/response_helper.go
Normal file
14
response_helper/response_helper.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package response_helper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RespondWithStatusCode(statusCode int, conn net.Conn) {
|
||||||
|
conn.Write([]byte(fmt.Sprintf("HTTP/1.1 %d %s\r\n", statusCode, http.StatusText(statusCode))))
|
||||||
|
conn.Write([]byte("Content-Type: text/plain\r\n"))
|
||||||
|
conn.Write([]byte("Content-Length: 0\r\n"))
|
||||||
|
conn.Write([]byte("\r\n"))
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user