Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
5d942ea
Fix Fiber v3 adapter for Unix socket testing
Dishank-Sen Sep 23, 2025
0bd1560
test(adaptor): use temp dir for Unix socket and skip on non-Unix
Dishank-Sen Sep 23, 2025
599bd4c
formatted test file and handle error check
Dishank-Sen Sep 24, 2025
b5ada3c
Merge branch 'main' into unix-socket-adaptor-fix
Dishank-Sen Sep 24, 2025
51c132c
resolves issues in adapter test
Dishank-Sen Sep 24, 2025
45af477
Merge branch 'unix-socket-adaptor-fix' of https://github.com/Dishank-…
Dishank-Sen Sep 24, 2025
09c1dc8
*net.TCPaddr to net.addr
Dishank-Sen Sep 24, 2025
73bad86
fixes in adaptor test
Dishank-Sen Sep 25, 2025
ec57fd1
fixes in adaptor test
Dishank-Sen Sep 25, 2025
8a8cd9b
fixes in adaptor test
Dishank-Sen Sep 25, 2025
e8bf607
checked error return in adataptor test
Dishank-Sen Sep 26, 2025
ad9451b
Merge branch 'main' into unix-socket-adaptor-fix
Dishank-Sen Sep 26, 2025
bd4728e
resolved variable shadowing in adaptor test
Dishank-Sen Sep 26, 2025
86694e5
Merge branch 'unix-socket-adaptor-fix' of https://github.com/Dishank-…
Dishank-Sen Sep 26, 2025
a465c87
resolved variable shadowing in adaptor test
Dishank-Sen Sep 26, 2025
2222fe9
resolved variable shadowing in adaptor test
Dishank-Sen Sep 26, 2025
43e5f82
Merge branch 'main' into unix-socket-adaptor-fix
Dishank-Sen Sep 27, 2025
71ea1cf
Merge branch 'main' into unix-socket-adaptor-fix
Dishank-Sen Sep 27, 2025
896afbd
added resolveRemoteAddr function for resolving addr properly
Dishank-Sen Sep 28, 2025
ce7b893
changes in resolveRemoteAddr function
Dishank-Sen Sep 28, 2025
5a4a4fe
Merge branch 'main' into unix-socket-adaptor-fix
Dishank-Sen Sep 28, 2025
447e526
resolved lint error
Dishank-Sen Sep 28, 2025
70e3e44
Merge branch 'main' into unix-socket-adaptor-fix
Dishank-Sen Sep 28, 2025
4d25336
added test for bad remote address
Dishank-Sen Sep 28, 2025
8fbb9aa
resolve lint issue in adaptor test
Dishank-Sen Sep 28, 2025
f235a7b
resolve lint issue in adaptor test
Dishank-Sen Sep 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 31 additions & 7 deletions middleware/adaptor/adaptor.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package adaptor

import (
"errors"
"fmt"
"io"
"net"
"net/http"
Expand Down Expand Up @@ -138,6 +140,32 @@ func FiberApp(app *fiber.App) http.HandlerFunc {
return handlerFunc(app)
}

func isUnixNetwork(network string) bool {
return network == "unix" || network == "unixgram" || network == "unixpacket"
}

func resolveRemoteAddr(remoteAddr string, localAddr any) (net.Addr, error) {
if addr, ok := localAddr.(net.Addr); ok && isUnixNetwork(addr.Network()) {
return addr, nil
}

resolved, err := net.ResolveTCPAddr("tcp", remoteAddr)
if err == nil {
return resolved, nil
}

var addrErr *net.AddrError
if errors.As(err, &addrErr) && addrErr.Err == "missing port in address" {
remoteAddr = net.JoinHostPort(remoteAddr, "80")
resolved, err2 := net.ResolveTCPAddr("tcp", remoteAddr)
if err2 != nil {
return nil, fmt.Errorf("failed to resolve TCP address after adding port: %w", err2)
}
return resolved, nil
}
return nil, fmt.Errorf("failed to resolve TCP address: %w", err)
}

func handlerFunc(app *fiber.App, h ...fiber.Handler) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
req := fasthttp.AcquireRequest()
Expand All @@ -164,14 +192,10 @@ func handlerFunc(app *fiber.App, h ...fiber.Handler) http.HandlerFunc {
}
}

if _, _, err := net.SplitHostPort(r.RemoteAddr); err != nil && err.(*net.AddrError).Err == "missing port in address" { //nolint:errorlint,forcetypeassert,errcheck // overlinting
r.RemoteAddr = net.JoinHostPort(r.RemoteAddr, "80")
}

remoteAddr, err := net.ResolveTCPAddr("tcp", r.RemoteAddr)
remoteAddr, err := resolveRemoteAddr(r.RemoteAddr, r.Context().Value(http.LocalAddrContextKey))
if err != nil {
http.Error(w, utils.StatusMessage(fiber.StatusInternalServerError), fiber.StatusInternalServerError)
return
// fallback: fasthttp handles nil remoteAddr
remoteAddr = nil
}

// New fasthttp Ctx from pool
Expand Down
116 changes: 116 additions & 0 deletions middleware/adaptor/adaptor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ import (
"net/http"
"net/http/httptest"
"net/url"
"os"
"path/filepath"
"strings"
"testing"
"time"

"github.com/gofiber/fiber/v3"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -663,3 +666,116 @@ func Benchmark_HTTPHandler(b *testing.B) {

require.NoError(b, err)
}

func TestUnixSocketAdaptor(t *testing.T) {
dir := t.TempDir()
socketPath := filepath.Join(dir, "test.sock")
defer func() {
if err := os.Remove(socketPath); err != nil {
t.Logf("cleanup failed: %v", err)
}
}()

app := fiber.New()
app.Get("/hello", func(c fiber.Ctx) error {
return c.SendString("ok")
})
handler := FiberApp(app)

listener, err := net.Listen("unix", socketPath)
if err != nil {
// Skip on platforms where the "unix" network is unsupported
if strings.Contains(err.Error(), "unknown network") ||
strings.Contains(err.Error(), "address family not supported") {
t.Skipf("Unix domain sockets not supported on this platform: %v", err)
}
t.Fatal(err)
}
defer func() {
if closeErr := listener.Close(); closeErr != nil {
t.Logf("listener close failed: %v", closeErr)
}
}()

// start server with timeouts
srv := &http.Server{
Handler: handler,
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
}
done := make(chan struct{})
go func() {
if serveErr := srv.Serve(listener); serveErr != nil && serveErr != http.ErrServerClosed {
t.Errorf("http server failed: %v", serveErr)
}
close(done)
}()

conn, err := net.Dial("unix", socketPath)
require.NoError(t, err)
defer func() {
if closeErr := conn.Close(); closeErr != nil {
t.Logf("conn close failed: %v", closeErr)
}
}()

// set deadline for both write + read (2s)
require.NoError(t, conn.SetDeadline(time.Now().Add(2*time.Second)))

// write request
_, err = conn.Write([]byte("GET /hello HTTP/1.1\r\nHost: localhost\r\n\r\n"))
require.NoError(t, err)

// read response
buf := make([]byte, 1024)
n, err := conn.Read(buf)
require.NoError(t, err)

// clear deadline to avoid affecting further calls
require.NoError(t, conn.SetDeadline(time.Time{}))

raw := string(buf[:n])
t.Logf("Raw response:\n%s", raw)
require.Contains(t, raw, "HTTP/1.1 200 OK")
require.Contains(t, raw, "ok")

// now shutdown the server explicitly before waiting for done
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
require.NoError(t, srv.Shutdown(ctx))

select {
case <-done:
case <-time.After(5 * time.Second):
t.Fatal("server shutdown timed out")
}
}

func TestHandlerFunc_FallbackRemoteAddr(t *testing.T) {
app := fiber.New()
app.Get("/", func(c fiber.Ctx) error {
return c.SendString("ok")
})

handler := handlerFunc(app)

// Fake request with bad RemoteAddr
req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "/", nil)
require.NoError(t, err)
req.RemoteAddr = "bad-addr"

rr := httptest.NewRecorder()
handler(rr, req)

res := rr.Result()
defer func() {
closeErr := res.Body.Close()
require.NoError(t, closeErr)
}()

body, err := io.ReadAll(res.Body)
require.NoError(t, err)

require.Equal(t, http.StatusOK, res.StatusCode)
require.Contains(t, string(body), "ok")
}
Loading