refactored hws to improve database operability
This commit is contained in:
2
hws/.gitignore
vendored
2
hws/.gitignore
vendored
@@ -17,3 +17,5 @@ coverage.html
|
|||||||
|
|
||||||
# Go workspace file
|
# Go workspace file
|
||||||
go.work
|
go.work
|
||||||
|
|
||||||
|
.claude/
|
||||||
|
|||||||
21
hws/LICENSE
Normal file
21
hws/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2026 haelnorr
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
119
hws/README.md
Normal file
119
hws/README.md
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
# hws
|
||||||
|
|
||||||
|
[](https://pkg.go.dev/git.haelnorr.com/h/golib/hws)
|
||||||
|
|
||||||
|
A lightweight, opinionated HTTP web server framework for Go built on top of the standard library's `net/http`.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- 🚀 Built on Go 1.22+ routing patterns with method and path matching
|
||||||
|
- 🎯 Structured error handling with customizable error pages
|
||||||
|
- 📝 Integrated logging with zerolog via hlog
|
||||||
|
- 🔧 Middleware support with predictable execution order
|
||||||
|
- 🗜️ GZIP compression support
|
||||||
|
- 🔒 Safe static file serving (prevents directory listing)
|
||||||
|
- ⚙️ Environment variable configuration
|
||||||
|
- ⏱️ Request timing and logging middleware
|
||||||
|
- 💚 Graceful shutdown support
|
||||||
|
- 🏥 Built-in health check endpoint
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go get git.haelnorr.com/h/golib/hws
|
||||||
|
```
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"git.haelnorr.com/h/golib/hws"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Load configuration from environment variables
|
||||||
|
config, _ := hws.ConfigFromEnv()
|
||||||
|
|
||||||
|
// Create server
|
||||||
|
server, _ := hws.NewServer(config)
|
||||||
|
|
||||||
|
// Define routes
|
||||||
|
routes := []hws.Route{
|
||||||
|
{
|
||||||
|
Path: "/",
|
||||||
|
Method: hws.MethodGET,
|
||||||
|
Handler: http.HandlerFunc(homeHandler),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Path: "/api/users/{id}",
|
||||||
|
Method: hws.MethodGET,
|
||||||
|
Handler: http.HandlerFunc(getUserHandler),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add routes and middleware
|
||||||
|
server.AddRoutes(routes...)
|
||||||
|
server.AddMiddleware()
|
||||||
|
|
||||||
|
// Start server
|
||||||
|
ctx := context.Background()
|
||||||
|
server.Start(ctx)
|
||||||
|
|
||||||
|
// Wait for server to be ready
|
||||||
|
<-server.Ready()
|
||||||
|
}
|
||||||
|
|
||||||
|
func homeHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Write([]byte("Hello, World!"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func getUserHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
id := r.PathValue("id")
|
||||||
|
w.Write([]byte("User ID: " + id))
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
Comprehensive documentation is available in the [Wiki](https://git.haelnorr.com/h/golib/wiki/hws).
|
||||||
|
|
||||||
|
### Key Topics
|
||||||
|
|
||||||
|
- [Configuration](https://git.haelnorr.com/h/golib/wiki/hws#configuration)
|
||||||
|
- [Routing](https://git.haelnorr.com/h/golib/wiki/hws#routing)
|
||||||
|
- [Middleware](https://git.haelnorr.com/h/golib/wiki/hws#middleware)
|
||||||
|
- [Error Handling](https://git.haelnorr.com/h/golib/wiki/hws#error-handling)
|
||||||
|
- [Logging](https://git.haelnorr.com/h/golib/wiki/hws#logging)
|
||||||
|
- [Static Files](https://git.haelnorr.com/h/golib/wiki/hws#static-files)
|
||||||
|
- [Graceful Shutdown](https://git.haelnorr.com/h/golib/wiki/hws#graceful-shutdown)
|
||||||
|
- [Complete Examples](https://git.haelnorr.com/h/golib/wiki/hws#complete-production-example)
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
| Variable | Description | Default |
|
||||||
|
|----------|-------------|---------|
|
||||||
|
| `HWS_HOST` | Host to listen on | `127.0.0.1` |
|
||||||
|
| `HWS_PORT` | Port to listen on | `3000` |
|
||||||
|
| `HWS_TRUSTED_HOST` | Trusted hostname/domain | Same as Host |
|
||||||
|
| `HWS_GZIP` | Enable GZIP compression | `false` |
|
||||||
|
| `HWS_READ_HEADER_TIMEOUT` | Header read timeout (seconds) | `2` |
|
||||||
|
| `HWS_WRITE_TIMEOUT` | Write timeout (seconds) | `10` |
|
||||||
|
| `HWS_IDLE_TIMEOUT` | Idle connection timeout (seconds) | `120` |
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Contributions are welcome! Please feel free to submit a Pull Request.
|
||||||
|
|
||||||
|
## Related Projects
|
||||||
|
|
||||||
|
- [hwsauth](https://git.haelnorr.com/h/golib/hwsauth) - JWT authentication middleware for hws
|
||||||
|
- [hlog](https://git.haelnorr.com/h/golib/hlog) - Structured logging with zerolog
|
||||||
|
- [jwt](https://git.haelnorr.com/h/golib/jwt) - JWT token generation and validation
|
||||||
@@ -149,7 +149,7 @@ func Test_Start_Errors(t *testing.T) {
|
|||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = server.Start(nil)
|
err = server.Start(t.Context())
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Contains(t, err.Error(), "Context cannot be nil")
|
assert.Contains(t, err.Error(), "Context cannot be nil")
|
||||||
})
|
})
|
||||||
@@ -163,7 +163,7 @@ func Test_Shutdown_Errors(t *testing.T) {
|
|||||||
startTestServer(t, server)
|
startTestServer(t, server)
|
||||||
<-server.Ready()
|
<-server.Ready()
|
||||||
|
|
||||||
err := server.Shutdown(nil)
|
err := server.Shutdown(t.Context())
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Contains(t, err.Error(), "Context cannot be nil")
|
assert.Contains(t, err.Error(), "Context cannot be nil")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user