Skip to content

Commit d37890a

Browse files
committed
fix: add newline in NDJSON responses
1 parent 33e3f0c commit d37890a

File tree

2 files changed

+63
-0
lines changed

2 files changed

+63
-0
lines changed

routing/http/server/server.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,13 @@ func (s *server) findProvidersNDJSON(w http.ResponseWriter, provIter iter.Result
254254
logger.Warn("FindProviders ndjson write error", "Error", err)
255255
return
256256
}
257+
258+
_, err = w.Write([]byte{'\n'})
259+
if err != nil {
260+
logger.Warn("FindProviders ndjson write error", "Error", err)
261+
return
262+
}
263+
257264
if f, ok := w.(http.Flusher); ok {
258265
f.Flush()
259266
}

routing/http/server/server_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package server
22

33
import (
44
"context"
5+
"io"
56
"net/http"
67
"net/http/httptest"
78
"testing"
@@ -10,6 +11,7 @@ import (
1011
"github.com/ipfs/boxo/routing/http/types"
1112
"github.com/ipfs/boxo/routing/http/types/iter"
1213
"github.com/ipfs/go-cid"
14+
"github.com/libp2p/go-libp2p/core/peer"
1315
"github.com/stretchr/testify/mock"
1416
"github.com/stretchr/testify/require"
1517
)
@@ -48,6 +50,60 @@ func TestHeaders(t *testing.T) {
4850
require.Equal(t, "text/plain; charset=utf-8", header)
4951
}
5052

53+
func TestResponse(t *testing.T) {
54+
pidStr := "12D3KooWM8sovaEGU1bmiWGWAzvs47DEcXKZZTuJnpQyVTkRs2Vn"
55+
cidStr := "bafkreifjjcie6lypi6ny7amxnfftagclbuxndqonfipmb64f2km2devei4"
56+
57+
pid, err := peer.Decode(pidStr)
58+
require.NoError(t, err)
59+
60+
cid, err := cid.Decode(cidStr)
61+
require.NoError(t, err)
62+
63+
runTest := func(t *testing.T, contentType string, expected string) {
64+
t.Parallel()
65+
66+
results := iter.FromSlice([]iter.Result[types.ProviderResponse]{
67+
{Val: &types.ReadBitswapProviderRecord{
68+
Protocol: "transport-bitswap",
69+
Schema: types.SchemaBitswap,
70+
ID: &pid,
71+
Addrs: []types.Multiaddr{},
72+
}}},
73+
)
74+
75+
router := &mockContentRouter{}
76+
server := httptest.NewServer(Handler(router))
77+
t.Cleanup(server.Close)
78+
serverAddr := "http://" + server.Listener.Addr().String()
79+
router.On("FindProviders", mock.Anything, cid).Return(results, nil)
80+
urlStr := serverAddr + ProvidePath + cidStr
81+
82+
req, err := http.NewRequest(http.MethodGet, urlStr, nil)
83+
require.NoError(t, err)
84+
req.Header.Set("Accept", contentType)
85+
86+
resp, err := http.DefaultClient.Do(req)
87+
require.NoError(t, err)
88+
require.Equal(t, 200, resp.StatusCode)
89+
header := resp.Header.Get("Content-Type")
90+
require.Equal(t, contentType, header)
91+
92+
body, err := io.ReadAll(resp.Body)
93+
require.NoError(t, err)
94+
95+
require.Equal(t, string(body), expected)
96+
}
97+
98+
t.Run("JSON Response", func(t *testing.T) {
99+
runTest(t, mediaTypeJSON, `{"Providers":[{"Protocol":"transport-bitswap","Schema":"bitswap","ID":"12D3KooWM8sovaEGU1bmiWGWAzvs47DEcXKZZTuJnpQyVTkRs2Vn","Addrs":[]}]}`)
100+
})
101+
102+
t.Run("NDJSON Response", func(t *testing.T) {
103+
runTest(t, mediaTypeNDJSON, `{"Protocol":"transport-bitswap","Schema":"bitswap","ID":"12D3KooWM8sovaEGU1bmiWGWAzvs47DEcXKZZTuJnpQyVTkRs2Vn","Addrs":[]}`+"\n")
104+
})
105+
}
106+
51107
type mockContentRouter struct{ mock.Mock }
52108

53109
func (m *mockContentRouter) FindProviders(ctx context.Context, key cid.Cid) (iter.ResultIter[types.ProviderResponse], error) {

0 commit comments

Comments
 (0)