diff --git a/Context.go b/Context.go
index 7afb303..46b3b8c 100644
--- a/Context.go
+++ b/Context.go
@@ -9,7 +9,6 @@ type Context interface {
Bytes([]byte) error
Error(...any) error
Next() error
- Redirect(int, string) error
Request() Request
Response() Response
Status(int) Context
@@ -52,14 +51,6 @@ func (ctx *context) Next() error {
return ctx.server.handlers[ctx.handlerCount](ctx)
}
-// Redirect redirects the client to a different location
-// with the specified status code.
-func (ctx *context) Redirect(status int, location string) error {
- ctx.response.SetStatus(status)
- ctx.response.SetHeader("Location", location)
- return nil
-}
-
// Request returns the HTTP request.
func (ctx *context) Request() Request {
return &ctx.request
diff --git a/Context_test.go b/Context_test.go
index b3a6005..05bc24f 100644
--- a/Context_test.go
+++ b/Context_test.go
@@ -4,8 +4,8 @@ import (
"errors"
"testing"
- "git.urbach.dev/go/assert"
- "git.urbach.dev/go/web"
+ "git.akyoto.dev/go/assert"
+ "git.akyoto.dev/go/web"
)
func TestBytes(t *testing.T) {
@@ -55,15 +55,3 @@ func TestErrorMultiple(t *testing.T) {
assert.Equal(t, response.Status(), 401)
assert.Equal(t, string(response.Body()), "")
}
-
-func TestRedirect(t *testing.T) {
- s := web.NewServer()
-
- s.Get("/", func(ctx web.Context) error {
- return ctx.Redirect(301, "/target")
- })
-
- response := s.Request("GET", "/", nil, nil)
- assert.Equal(t, response.Status(), 301)
- assert.Equal(t, response.Header("Location"), "/target")
-}
diff --git a/README.md b/README.md
index 149eb93..9b912f2 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# web
-A minimal HTTP/1.1 web server that sits behind a reverse proxy like `caddy` or `nginx` for HTTP 1/2/3 support.
+A fast HTTP/1.1 web server that can sit behind a reverse proxy like `caddy` or `nginx` for HTTP 1/2/3 support.
## Features
@@ -11,7 +11,7 @@ A minimal HTTP/1.1 web server that sits behind a reverse proxy like `caddy` or `
## Installation
```shell
-go get git.urbach.dev/go/web
+go get git.akyoto.dev/go/web
```
## Usage
@@ -26,23 +26,12 @@ s.Get("/", func(ctx web.Context) error {
// Parameter route
s.Get("/blog/:post", func(ctx web.Context) error {
- return ctx.String(ctx.Request().Param("post"))
+ return ctx.String(ctx.Get("post"))
})
// Wildcard route
s.Get("/images/*file", func(ctx web.Context) error {
- return ctx.String(ctx.Request().Param("file"))
-})
-
-// Middleware
-s.Use(func(ctx web.Context) error {
- start := time.Now()
-
- defer func() {
- fmt.Println(ctx.Request().Path(), time.Since(start))
- }()
-
- return ctx.Next()
+ return ctx.String(ctx.Get("file"))
})
s.Run(":8080")
@@ -55,7 +44,6 @@ PASS: TestBytes
PASS: TestString
PASS: TestError
PASS: TestErrorMultiple
-PASS: TestRedirect
PASS: TestRequest
PASS: TestRequestHeader
PASS: TestRequestParam
@@ -69,9 +57,7 @@ PASS: TestRun
PASS: TestBadRequest
PASS: TestBadRequestHeader
PASS: TestBadRequestMethod
-PASS: TestBadRequestPath
PASS: TestBadRequestProtocol
-PASS: TestConnectionClose
PASS: TestEarlyClose
PASS: TestUnavailablePort
coverage: 100.0% of statements
@@ -83,7 +69,7 @@ coverage: 100.0% of statements
## License
-Please see the [license documentation](https://urbach.dev/license).
+Please see the [license documentation](https://akyoto.dev/license).
## Copyright
diff --git a/Request.go b/Request.go
index 6c7ef3c..9ec8ef9 100644
--- a/Request.go
+++ b/Request.go
@@ -3,7 +3,7 @@ package web
import (
"bufio"
- "git.urbach.dev/go/router"
+ "git.akyoto.dev/go/router"
)
// Request is an interface for HTTP requests.
diff --git a/Request_test.go b/Request_test.go
index 1e079a8..6a08fd0 100644
--- a/Request_test.go
+++ b/Request_test.go
@@ -4,8 +4,8 @@ import (
"fmt"
"testing"
- "git.urbach.dev/go/assert"
- "git.urbach.dev/go/web"
+ "git.akyoto.dev/go/assert"
+ "git.akyoto.dev/go/web"
)
func TestRequest(t *testing.T) {
diff --git a/Response_test.go b/Response_test.go
index 9028acf..dc62965 100644
--- a/Response_test.go
+++ b/Response_test.go
@@ -6,8 +6,8 @@ import (
"io"
"testing"
- "git.urbach.dev/go/assert"
- "git.urbach.dev/go/web"
+ "git.akyoto.dev/go/assert"
+ "git.akyoto.dev/go/web"
)
func TestWrite(t *testing.T) {
diff --git a/Server.go b/Server.go
index ba163a0..f987c51 100644
--- a/Server.go
+++ b/Server.go
@@ -13,7 +13,7 @@ import (
"sync"
"syscall"
- "git.urbach.dev/go/router"
+ "git.akyoto.dev/go/router"
)
// Server is the interface for an HTTP server.
@@ -121,7 +121,6 @@ func (s *server) handleConnection(conn net.Conn) {
ctx = s.contextPool.Get().(*context)
method string
url string
- close bool
)
ctx.reader.Reset(conn)
@@ -129,7 +128,7 @@ func (s *server) handleConnection(conn net.Conn) {
defer conn.Close()
defer s.contextPool.Put(ctx)
- for !close {
+ for {
// Read the HTTP request line
message, err := ctx.reader.ReadString('\n')
@@ -157,14 +156,7 @@ func (s *server) handleConnection(conn net.Conn) {
lastSpace = len(message) - len("\r\n")
}
- space += 1
-
- if space > lastSpace {
- io.WriteString(conn, "HTTP/1.1 400 Bad Request\r\n\r\n")
- return
- }
-
- url = message[space:lastSpace]
+ url = message[space+1 : lastSpace]
// Add headers until we meet an empty line
for {
@@ -184,10 +176,6 @@ func (s *server) handleConnection(conn net.Conn) {
continue
}
- if colon > len(message)-4 {
- continue
- }
-
key := message[:colon]
value := message[colon+2 : len(message)-2]
@@ -195,10 +183,6 @@ func (s *server) handleConnection(conn net.Conn) {
Key: key,
Value: value,
})
-
- if value == "close" && strings.EqualFold(key, "connection") {
- close = true
- }
}
// Handle the request
diff --git a/Server_test.go b/Server_test.go
index f2c142b..9793aef 100644
--- a/Server_test.go
+++ b/Server_test.go
@@ -7,8 +7,8 @@ import (
"syscall"
"testing"
- "git.urbach.dev/go/assert"
- "git.urbach.dev/go/web"
+ "git.akyoto.dev/go/assert"
+ "git.akyoto.dev/go/web"
)
func TestPanic(t *testing.T) {
@@ -77,7 +77,7 @@ func TestBadRequestHeader(t *testing.T) {
assert.Nil(t, err)
defer conn.Close()
- _, err = io.WriteString(conn, "GET / HTTP/1.1\r\nBad\r\nBad:\r\nGood: Header\r\n\r\n")
+ _, err = io.WriteString(conn, "GET / HTTP/1.1\r\nBadHeader\r\nGood: Header\r\n\r\n")
assert.Nil(t, err)
buffer := make([]byte, len("HTTP/1.1 200"))
@@ -110,27 +110,6 @@ func TestBadRequestMethod(t *testing.T) {
s.Run(":8080")
}
-func TestBadRequestPath(t *testing.T) {
- s := web.NewServer()
-
- go func() {
- defer syscall.Kill(syscall.Getpid(), syscall.SIGTERM)
-
- conn, err := net.Dial("tcp", ":8080")
- assert.Nil(t, err)
- defer conn.Close()
-
- _, err = io.WriteString(conn, "GET \n")
- assert.Nil(t, err)
-
- response, err := io.ReadAll(conn)
- assert.Nil(t, err)
- assert.Equal(t, string(response), "HTTP/1.1 400 Bad Request\r\n\r\n")
- }()
-
- s.Run(":8080")
-}
-
func TestBadRequestProtocol(t *testing.T) {
s := web.NewServer()
@@ -157,26 +136,6 @@ func TestBadRequestProtocol(t *testing.T) {
s.Run(":8080")
}
-func TestConnectionClose(t *testing.T) {
- s := web.NewServer()
-
- go func() {
- defer syscall.Kill(syscall.Getpid(), syscall.SIGTERM)
-
- conn, err := net.Dial("tcp", ":8080")
- assert.Nil(t, err)
- defer conn.Close()
-
- _, err = io.WriteString(conn, "GET / HTTP/1.1\r\nConnection: close\r\n\r\n")
- assert.Nil(t, err)
-
- _, err = io.ReadAll(conn)
- assert.Nil(t, err)
- }()
-
- s.Run(":8080")
-}
-
func TestEarlyClose(t *testing.T) {
s := web.NewServer()
diff --git a/send/send.go b/content/content.go
similarity index 97%
rename from send/send.go
rename to content/content.go
index 9c4c2ca..2eca461 100644
--- a/send/send.go
+++ b/content/content.go
@@ -1,9 +1,9 @@
-package send
+package content
import (
"encoding/json"
- "git.urbach.dev/go/web"
+ "git.akyoto.dev/go/web"
)
// CSS sends the body with the content type set to `text/css`.
diff --git a/send/send_test.go b/content/content_test.go
similarity index 79%
rename from send/send_test.go
rename to content/content_test.go
index fec22c3..5d4d2ca 100644
--- a/send/send_test.go
+++ b/content/content_test.go
@@ -1,42 +1,42 @@
-package send_test
+package content_test
import (
"testing"
- "git.urbach.dev/go/assert"
- "git.urbach.dev/go/web"
- "git.urbach.dev/go/web/send"
+ "git.akyoto.dev/go/assert"
+ "git.akyoto.dev/go/web"
+ "git.akyoto.dev/go/web/content"
)
func TestContentTypes(t *testing.T) {
s := web.NewServer()
s.Get("/css", func(ctx web.Context) error {
- return send.CSS(ctx, "body{}")
+ return content.CSS(ctx, "body{}")
})
s.Get("/csv", func(ctx web.Context) error {
- return send.CSV(ctx, "ID;Name\n")
+ return content.CSV(ctx, "ID;Name\n")
})
s.Get("/html", func(ctx web.Context) error {
- return send.HTML(ctx, "")
+ return content.HTML(ctx, "")
})
s.Get("/js", func(ctx web.Context) error {
- return send.JS(ctx, "console.log(42)")
+ return content.JS(ctx, "console.log(42)")
})
s.Get("/json", func(ctx web.Context) error {
- return send.JSON(ctx, struct{ Name string }{Name: "User 1"})
+ return content.JSON(ctx, struct{ Name string }{Name: "User 1"})
})
s.Get("/text", func(ctx web.Context) error {
- return send.Text(ctx, "Hello")
+ return content.Text(ctx, "Hello")
})
s.Get("/xml", func(ctx web.Context) error {
- return send.XML(ctx, "")
+ return content.XML(ctx, "")
})
tests := []struct {
diff --git a/examples/hello/main.go b/examples/hello/main.go
index b42db84..c9853da 100644
--- a/examples/hello/main.go
+++ b/examples/hello/main.go
@@ -1,7 +1,7 @@
package main
import (
- "git.urbach.dev/go/web"
+ "git.akyoto.dev/go/web"
)
func main() {
diff --git a/go.mod b/go.mod
index f2bf46e..a4d4a7c 100644
--- a/go.mod
+++ b/go.mod
@@ -1,8 +1,8 @@
-module git.urbach.dev/go/web
+module git.akyoto.dev/go/web
-go 1.24
+go 1.22
require (
- git.urbach.dev/go/assert v0.0.0-20250225153414-fc1f84f19edf
- git.urbach.dev/go/router v0.0.0-20250601162231-e35d5715d1a5
+ git.akyoto.dev/go/assert v0.1.3
+ git.akyoto.dev/go/router v0.1.4
)
diff --git a/go.sum b/go.sum
index 4c3db0c..a12e1ec 100644
--- a/go.sum
+++ b/go.sum
@@ -1,4 +1,4 @@
-git.urbach.dev/go/assert v0.0.0-20250225153414-fc1f84f19edf h1:BQWa5GKNUsA5CSUa/+UlFWYCEVe3IDDKRbVqBLK0mAE=
-git.urbach.dev/go/assert v0.0.0-20250225153414-fc1f84f19edf/go.mod h1:y9jGII9JFiF1HNIju0u87OyPCt82xKCtqnAFyEreCDo=
-git.urbach.dev/go/router v0.0.0-20250601162231-e35d5715d1a5 h1:3qlZjgWbrHw4LWM4uBzOTldbpqCLJdeSgvcYK6f3xpc=
-git.urbach.dev/go/router v0.0.0-20250601162231-e35d5715d1a5/go.mod h1:O+doTe0DZdT2XMsTY5pe6qUMqEEIAbwtX6Xp6EqHw34=
+git.akyoto.dev/go/assert v0.1.3 h1:QwCUbmG4aZYsNk/OuRBz1zWVKmGlDUHhOnnDBfn8Qw8=
+git.akyoto.dev/go/assert v0.1.3/go.mod h1:0GzMaM0eURuDwtGkJJkCsI7r2aUKr+5GmWNTFPgDocM=
+git.akyoto.dev/go/router v0.1.4 h1:ZL5HPl4aNn4QKihf3VVs0Mm9R6ZGn2StAHGRQxjEbws=
+git.akyoto.dev/go/router v0.1.4/go.mod h1:rbHbkLJlQOafuOuvBalO3O8E0JtMFPT3zzTKX3h9T08=