A lightweight HTTP server framework built from scratch in Go using raw TCP connections. No external dependencies, just pure Go standard library.
- 🚀 Built from scratch using TCP sockets
- 🛣️ Fast HTTP routing with support for path parameters
- 📦 Simple and intuitive API
- 🔄 JSON response helper
- ⚡ Concurrent request handling with goroutines
- 🎯 Pattern matching for dynamic routes
go get github.com/codewithdpk/naradHere's a simple example to get you started:
package main
import (
"github.com/codewithdpk/narad/internal/server"
)
func main() {
// Create a new router
r := server.New()
// Define a simple route
r.Handle("GET", "/", func(ctx *server.Context) {
ctx.JSON(200, []byte(`{"message": "Hello, World!"}`))
})
// Start the server on port 8080
r.Serve(":8080")
}Run the example:
go run examples/basic_server.goTest it with curl:
curl http://localhost:8080/r := server.New()
// GET request
r.Handle("GET", "/api/users", func(ctx *server.Context) {
ctx.JSON(200, []byte(`{"users": []}`))
})
// POST request
r.Handle("POST", "/api/users", func(ctx *server.Context) {
ctx.JSON(201, []byte(`{"message": "User created"}`))
})Use :param syntax to capture dynamic path segments:
// Capture user ID from URL
r.Handle("GET", "/api/users/:id", func(ctx *server.Context) {
userID := ctx.Params["id"]
response := `{"id": "` + userID + `", "name": "User ` + userID + `"}`
ctx.JSON(200, []byte(response))
})
// Multiple parameters
r.Handle("GET", "/api/posts/:postId/comments/:commentId", func(ctx *server.Context) {
postID := ctx.Params["postId"]
commentID := ctx.Params["commentId"]
// Handle the request...
})Test with:
curl http://localhost:8080/api/users/123The Context object provides access to request information:
type Context struct {
Conn net.Conn // TCP connection
Method string // HTTP method (GET, POST, etc.)
Path string // Request path
Version string // HTTP version
Headers map[string]string // Request headers
Body string // Request body
Params map[string]string // Path parameters
}// JSON response
ctx.JSON(200, []byte(`{"status": "ok"}`))
// Custom response with any content type
ctx.WriteResponse(200, "text/html", []byte("<h1>Hello</h1>"))# GET request
curl http://localhost:8080/api/users
# GET with path parameter
curl http://localhost:8080/api/users/42
# POST request
curl -X POST http://localhost:8080/api/users \
-H "Content-Type: application/json" \
-d '{"name": "John Doe"}'
# Nested routes
curl http://localhost:8080/api/products/10/reviews# GET request
http GET http://localhost:8080/api/users
# POST request
http POST http://localhost:8080/api/users name="John Doe"narad/
├── cmd/
│ └── server/
│ └── main.go # Original server implementation
├── examples/
│ └── basic_server.go # Example server to get started
├── internal/
│ └── server/
│ ├── connection.go # Connection handling and Context
│ ├── req.go # Request parsing
│ ├── response.go # Response structures
│ └── router.go # Routing logic
└── README.md
This HTTP server is built from the ground up without using Go's net/http package:
- TCP Listener: Creates a raw TCP socket listener
- Request Parsing: Manually parses HTTP request format
- Routing: Custom router with trie-based path matching
- Concurrent Handling: Each connection handled in a separate goroutine
- Response Building: Constructs HTTP responses following the HTTP/1.1 spec
New() *Router
- Creates and returns a new router instance
Handle(method string, path string, handler Handler)
- Registers a handler for the given HTTP method and path
- Parameters:
method: HTTP method (GET, POST, PUT, DELETE, etc.)path: URL path pattern (supports:paramfor dynamic segments)handler: Function to handle the request
Serve(addr string)
- Starts the HTTP server on the specified address
- Parameter:
addr: Address to listen on (e.g., ":8080", "localhost:3000")
JSON(status int, data []byte)
- Sends a JSON response
- Parameters:
status: HTTP status codedata: JSON data as byte slice
WriteResponse(status int, contentType string, body []byte)
- Sends a custom HTTP response
- Parameters:
status: HTTP status codecontentType: Content-Type header valuebody: Response body as byte slice
Contributions are welcome! Please feel free to submit a Pull Request.
This project is open source and available under the MIT License.
Built with ❤️ by codewithdpk