Skip to content

Commit 5913f9d

Browse files
committed
fix: add CORS plugin
1 parent a3be11b commit 5913f9d

File tree

5 files changed

+286
-27
lines changed

5 files changed

+286
-27
lines changed

packages/interop/package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@
1616
],
1717
"type": "module",
1818
"types": "./dist/src/index.d.ts",
19+
"files": [
20+
"src",
21+
"dist",
22+
"!dist/test",
23+
"!**/*.tsbuildinfo"
24+
],
1925
"exports": {
2026
".": {
2127
"types": "./dist/src/index.d.ts",

packages/server/package.json

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,22 @@
1616
],
1717
"type": "module",
1818
"types": "./dist/src/index.d.ts",
19+
"typesVersions": {
20+
"*": {
21+
"*": [
22+
"*",
23+
"dist/*",
24+
"dist/src/*",
25+
"dist/src/*/index"
26+
],
27+
"src/*": [
28+
"*",
29+
"dist/*",
30+
"dist/src/*",
31+
"dist/src/*/index"
32+
]
33+
}
34+
},
1935
"files": [
2036
"src",
2137
"dist",
@@ -26,6 +42,10 @@
2642
".": {
2743
"types": "./dist/src/index.d.ts",
2844
"import": "./dist/src/index.js"
45+
},
46+
"./routes": {
47+
"types": "./dist/src/routes/index.d.ts",
48+
"import": "./dist/src/routes/index.js"
2949
}
3050
},
3151
"eslintConfig": {
@@ -122,19 +142,23 @@
122142
"scripts": {
123143
"clean": "aegir clean",
124144
"lint": "aegir lint",
125-
"dep-check": "aegir dep-check",
145+
"dep-check": "aegir dep-check -i sinon",
126146
"build": "aegir build --bundle false",
127147
"test": "aegir test -t node",
128148
"test:node": "aegir test -t node --cov",
129149
"release": "aegir release"
130150
},
131151
"dependencies": {
152+
"@fastify/cors": "^8.3.0",
132153
"@helia/interface": "^1.1.1",
133154
"@libp2p/interfaces": "^3.3.2",
134155
"fastify": "^4.17.0",
135156
"multiformats": "^11.0.2"
136157
},
137158
"devDependencies": {
159+
"@libp2p/interface-peer-info": "^1.0.10",
160+
"@libp2p/peer-id-factory": "^2.0.3",
161+
"@multiformats/multiaddr": "^12.1.3",
138162
"@types/sinon": "^10.0.15",
139163
"aegir": "^39.0.4",
140164
"sinon": "^15.1.0",

packages/server/src/index.ts

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,87 @@
11
/**
22
* @packageDocumentation
33
*
4-
* Create a Helia node.
4+
* Implements HTTP routes for a Fastify server that conform to the [Routing V1 HTTP API](https://specs.ipfs.tech/routing/http-routing-v1/).
55
*
66
* @example
77
*
88
* ```typescript
9-
* import { MemoryDatastore } from 'datastore-core'
10-
* import { MemoryBlockstore } from 'blockstore-core'
119
* import { createHelia } from 'helia'
12-
* import { unixfs } from '@helia/unixfs'
13-
* import { CID } from 'multiformats/cid'
10+
* import { createRoutingV1HttpApiServer } from '@helia/routing-v1-http-api-server'
1411
*
15-
* const node = await createHelia({
16-
* blockstore: new MemoryBlockstore(),
17-
* datastore: new MemoryDatastore()
12+
* const helia = await createHelia()
13+
* const server = await createRoutingV1HttpApiServer(helia, {
14+
* fastify: {
15+
* // fastify options
16+
* },
17+
* listen: {
18+
* // fastify listen options
19+
* }
1820
* })
19-
* const fs = unixfs(node)
20-
* fs.cat(CID.parse('bafyFoo'))
21+
*
22+
* // now make http requests
23+
* ```
24+
*
25+
* Alternatively if you have a Fastify instance already you can add routes to it.
26+
*
27+
* @example
28+
*
29+
* ```typescript
30+
* import fastify from 'fastify'
31+
* import cors from '@fastify/cors'
32+
* import { createHelia } from 'helia'
33+
* import routes from '@helia/routing-v1-http-api-server/routes'
34+
*
35+
* const server = fastify({
36+
* // fastify options
37+
* })
38+
* await server.register(cors, {
39+
* origin: '*',
40+
* methods: ['GET', 'OPTIONS'],
41+
* strictPreflight: false
42+
* })
43+
*
44+
* const helia = await createHelia()
45+
*
46+
* // configure Routing V1 HTTP API routes
47+
* routes(server, helia)
48+
*
49+
* await server.listen({
50+
* // fastify listen options
51+
* })
52+
*
53+
* // now make http requests
2154
* ```
2255
*/
2356

24-
import fastify, { type FastifyHttpOptions, type FastifyHttpsOptions, type FastifyInstance } from 'fastify'
57+
import cors from '@fastify/cors'
58+
import fastify, { type FastifyListenOptions, type FastifyHttpOptions, type FastifyHttpsOptions, type FastifyInstance } from 'fastify'
2559
import routes from './routes/index.js'
2660
import type { Helia } from '@helia/interface'
2761
import type * as http from 'node:http'
2862
import type * as https from 'node:https'
2963

3064
export interface ServerInit {
31-
port?: number
3265
fastify?: FastifyHttpOptions<http.Server> | FastifyHttpsOptions<https.Server>
66+
listen?: FastifyListenOptions
3367
}
3468

3569
/**
3670
* Create and return a Helia node
3771
*/
3872
export async function createRoutingV1HttpApiServer (helia: Helia, init: ServerInit = {}): Promise<FastifyInstance> {
3973
const server = fastify(init.fastify)
74+
await server.register(cors, {
75+
origin: '*',
76+
methods: ['GET', 'OPTIONS'],
77+
strictPreflight: false
78+
})
4079

4180
routes(server, helia)
4281

43-
await server.listen({ port: init.port ?? 0 })
82+
await server.listen(init.listen ?? {
83+
port: 0
84+
})
4485

4586
return server
4687
}

packages/server/src/routes/routing/v1/providers/get.ts

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,29 +38,53 @@ export default function getProvidersV1 (fastify: FastifyInstance, helia: Helia):
3838
}
3939
},
4040
handler: async (request, reply) => {
41-
const { cid: cidStr } = request.params
42-
const cid = CID.parse(cidStr)
41+
let cid: CID
42+
43+
try {
44+
const { cid: cidStr } = request.params
45+
cid = CID.parse(cidStr)
46+
} catch (err) {
47+
// these are .thenables but not .catchables?
48+
reply.code(422).type('text/html').send('Unprocessable Entity') // eslint-disable-line @typescript-eslint/no-floating-promises
49+
return
50+
}
4351

4452
if (request.headers.accept?.includes('application/x-ndjson') === true) {
4553
const stream = new PassThrough()
4654

47-
// these are .thenables but not .catchables?
48-
reply.header('Content-Type', 'application/x-ndjson') // eslint-disable-line @typescript-eslint/no-floating-promises
49-
reply.send(stream) // eslint-disable-line @typescript-eslint/no-floating-promises
50-
5155
try {
56+
let found = 0
57+
5258
for await (const prov of streamingHandler(cid, helia)) {
59+
if (found === 0) {
60+
// these are .thenables but not .catchables?
61+
reply.header('Content-Type', 'application/x-ndjson') // eslint-disable-line @typescript-eslint/no-floating-promises
62+
reply.send(stream) // eslint-disable-line @typescript-eslint/no-floating-promises
63+
}
64+
65+
found++
66+
5367
stream.push(JSON.stringify(prov) + '\n')
5468
}
69+
70+
if (found > 0) {
71+
return
72+
}
5573
} finally {
5674
stream.end()
5775
}
5876
} else {
59-
// this is .thenable but not .catchable?
60-
reply.header('Content-Type', 'application/json') // eslint-disable-line @typescript-eslint/no-floating-promises
77+
const result = await nonStreamingHandler(cid, helia)
6178

62-
return nonStreamingHandler(cid, helia)
79+
if (result.Providers.length > 0) {
80+
// this is .thenable but not .catchable?
81+
reply.header('Content-Type', 'application/json') // eslint-disable-line @typescript-eslint/no-floating-promises
82+
83+
return reply.send(result)
84+
}
6385
}
86+
87+
reply.callNotFound()
6488
}
6589
})
6690
}

0 commit comments

Comments
 (0)