-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
149 lines (125 loc) · 3.58 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package main
import (
"bufio"
"fmt"
"net"
"strings"
)
// HandlerFunc represents a function that can handle incoming connections.
type HandlerFunc func(net.Conn)
// Route represents a TCP route and its associated handler function.
type Route struct {
Pattern string
Handler HandlerFunc
}
// TCPHandler is responsible for routing incoming connections based on their patterns.
type TCPHandler struct {
routes []Route
}
// NewTCPHandler creates a new TCPHandler.
func NewTCPHandler() *TCPHandler {
return &TCPHandler{}
}
// HandleFunc registers a handler for a specific pattern.
func (h *TCPHandler) HandleFunc(pattern string, handler HandlerFunc) {
h.routes = append(h.routes, Route{Pattern: pattern, Handler: handler})
}
// ServeTCP accepts incoming connections and routes them to the appropriate handler.
func (h *TCPHandler) ServeTCP(listener net.Listener) error {
defer listener.Close()
for {
conn, err := listener.Accept()
if err != nil {
return err
}
go h.handleConnection(conn)
}
}
// handleConnection routes an incoming connection to the appropriate handler based on its pattern.
func (h *TCPHandler) handleConnection(conn net.Conn) {
defer func(conn net.Conn) {
err := conn.Close()
if err != nil {
}
}(conn)
// Create a reader to read from the connection
reader := bufio.NewReader(conn)
// Read the request line
requestLine, err := reader.ReadString('\n')
if err != nil {
fmt.Println("Error reading request line:", err.Error())
return
}
// Parse the request line
parts := strings.Fields(requestLine)
if len(parts) != 3 {
fmt.Println("Malformed request line:", requestLine)
return
}
method, path, _ := parts[0], parts[1], parts[2]
// Read the headers
headers := make(map[string]string)
for {
line, err := reader.ReadString('\n')
if err != nil || line == "\r\n" {
break
}
parts := strings.SplitN(line, ":", 2)
if len(parts) == 2 {
headers[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1])
}
}
// Read the body if content length is specified
var body string
contentLengthStr, ok := headers["Content-Length"]
if ok {
contentLength := 0
fmt.Sscanf(contentLengthStr, "%d", &contentLength)
bodyBytes := make([]byte, contentLength)
_, err := reader.Read(bodyBytes)
if err != nil {
fmt.Println("Error reading body:", err.Error())
return
}
body = string(bodyBytes)
}
// Print the received request
//fmt.Println("Received request:")
//fmt.Println("Method:", method)
//fmt.Println("Path:", path)
//fmt.Println("Headers:", headers)
//fmt.Println("Body:", body)
fmt.Sprintf("Received request:\nMethod: %s\nPath: %s\nHeaders: %v\nBody: %s", method, path, headers, body)
// Find a matching route and handle the request
for _, route := range h.routes {
if route.Pattern == path {
route.Handler(conn)
return
}
}
conn.Write([]byte("HTTP/1.1 400 OK\r\nContent-Type: text/html\r\n\r\n<h1>Route Not Found</h1>"))
}
func main() {
// Create a new TCPHandler instance
handler := NewTCPHandler()
// Register handler functions for specific routes
handler.HandleFunc("/", func(conn net.Conn) {
// Send an HTTP response
response := "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<h1>Hello Dev</h1>"
conn.Write([]byte(response))
})
// Start listening on port 8080
listener, err := net.Listen("tcp", ":8080")
if err != nil {
fmt.Println("Error listening:", err.Error())
return
}
defer listener.Close()
fmt.Println("Server is listening on port 8080")
// Serve incoming connections using the TCPHandler
err = handler.ServeTCP(listener)
if err != nil {
fmt.Println("Error serving:", err.Error())
return
}
}