Skip to content

Commit a42dd5c

Browse files
author
v 1 r t l
authored
Merge pull request #2 from aarontravass/aaron/makefetch
Used random port for initialization
2 parents f3e5b28 + 9214db3 commit a42dd5c

3 files changed

Lines changed: 58 additions & 27 deletions

File tree

deps.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
export { getFreePort } from 'https://deno.land/x/free_port@v1.2.0/mod.ts'
21
export { expect } from 'https://deno.land/x/expect@v0.3.0/mod.ts'
32
export {
43
assertEquals,

mod.ts

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,26 @@
1-
import { assertEquals, assertMatch, getFreePort } from './deps.ts'
2-
import { HandlerOrListener } from './types.ts'
1+
import { assertEquals, assertMatch } from './deps.ts'
2+
import { Handler, HandlerOrListener } from './types.ts'
33

4-
const port = await getFreePort(8080)
4+
// credit - 'https://deno.land/x/free_port@v1.2.0/mod.ts'
5+
function random(min: number, max: number): number {
6+
return Math.round(Math.random() * (max - min)) + min
7+
}
8+
9+
// credit - 'https://deno.land/x/free_port@v1.2.0/mod.ts'
10+
const getFreeListener = (
11+
port: number,
12+
): { listener: Deno.Listener; port: number } => {
13+
try {
14+
const listener = Deno.listen({ port: port })
15+
return { listener, port }
16+
} catch (error) {
17+
if (error instanceof Deno.errors.AddrInUse) {
18+
const newPort = random(1024, 49151)
19+
return getFreeListener(newPort)
20+
}
21+
}
22+
throw Error
23+
}
524

625
const fetchEndpoint = async (
726
port: number,
@@ -20,10 +39,12 @@ const fetchEndpoint = async (
2039
else data = await res.arrayBuffer()
2140
return { res, data }
2241
}
23-
2442
const makeFetchPromise = (handlerOrListener: HandlerOrListener) => {
25-
// listener
26-
if ('rid' in handlerOrListener && 'addr' in handlerOrListener) {
43+
if ('rid' in handlerOrListener && 'adr' in handlerOrListener) {
44+
// this might never get invoked because of Deno's blocking issue
45+
const port = (handlerOrListener.addr as Deno.NetAddr).port;
46+
if(!port)
47+
throw new Error("Port cannot be found");
2748
return async (url: URL | string = '', params?: RequestInit) => {
2849
const p = new Promise<{ res: Response; data?: unknown }>((resolve) => {
2950
setTimeout(async () => {
@@ -36,31 +57,30 @@ const makeFetchPromise = (handlerOrListener: HandlerOrListener) => {
3657
const conn = await handlerOrListener.accept()
3758
return p
3859
}
39-
} // (req, conn) => Response listener
40-
else {
41-
const listener = Deno.listen({ port, hostname: 'localhost' })
42-
60+
} else {
61+
const { listener, port } = getFreeListener(random(1024, 49151))
4362
const serve = async (conn: Deno.Conn) => {
4463
const requests = Deno.serveHttp(conn)
4564
const { request, respondWith } = (await requests.nextRequest())!
46-
const response = await handlerOrListener(request, conn)
65+
66+
const response = await (handlerOrListener as Handler)(request, conn)
4767
if (response) {
4868
respondWith(response)
4969
}
5070
}
5171

5272
return async (url: URL | string = '', params?: RequestInit) => {
53-
const p = new Promise<{ res: Response; data?: unknown }>((resolve) => {
54-
setTimeout(async () => {
55-
const { res, data } = await fetchEndpoint(port, url, params)
56-
resolve({ res, data })
57-
Deno.close(conn.rid + 1)
58-
listener.close()
59-
})
60-
})
61-
const conn = await listener.accept()
62-
await serve(conn)
63-
return p
73+
const connector = async () => {
74+
const conn = await listener.accept()
75+
await serve(conn)
76+
return conn
77+
}
78+
const connection = connector()
79+
const res = await fetchEndpoint(port, url, params)
80+
await connection.then((con) => Deno.close(con.rid + 1)).finally(() =>
81+
listener.close()
82+
)
83+
return res
6484
}
6585
}
6686
}
@@ -69,6 +89,7 @@ export const makeFetch = (h: HandlerOrListener) => {
6989
const resp = makeFetchPromise(h)
7090
async function fetch(url: string | URL, options?: RequestInit) {
7191
const { data, res } = await resp(url, options)
92+
7293
const expectStatus = (a: number, b?: string) => {
7394
assertEquals(
7495
res.status,
@@ -82,7 +103,7 @@ export const makeFetch = (h: HandlerOrListener) => {
82103
expect: expectAll,
83104
expectStatus,
84105
expectHeader,
85-
expectBody,
106+
expectBody
86107
}
87108
}
88109
const expectHeader = (a: string, b: string | RegExp | null | string[]) => {
@@ -121,7 +142,7 @@ export const makeFetch = (h: HandlerOrListener) => {
121142
expect: expectAll,
122143
expectStatus,
123144
expectHeader,
124-
expectBody,
145+
expectBody
125146
}
126147
}
127148
const expectBody = (a: unknown) => {
@@ -143,12 +164,12 @@ export const makeFetch = (h: HandlerOrListener) => {
143164
expectBody,
144165
}
145166
}
146-
147167
return {
148168
expect: expectAll,
149169
expectStatus,
150170
expectHeader,
151171
expectBody,
172+
...res
152173
}
153174
}
154175
return fetch

mod_test.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,17 @@ describe('makeFetch', () => {
4343

4444
res.expect('')
4545
})
46+
it('should assign different ports if called many times', async () => {
47+
const handler: Handler = () => new Response("hello")
48+
const fetch = makeFetch(handler)
49+
const res = await fetch('/')
50+
res.expect("hello")
51+
52+
53+
const fetch_2 = makeFetch(handler)
54+
const res_2 = await fetch_2('/')
55+
res_2.expect("hello")
56+
})
4657
})
4758
describe('expectStatus', () => {
4859
it('should pass with a correct status', async () => {
@@ -178,4 +189,4 @@ describe('expect', () => {
178189
})
179190
})
180191

181-
run()
192+
run()

0 commit comments

Comments
 (0)