Skip to content

Commit bc2b712

Browse files
committed
support for json as request payload
1 parent f150ade commit bc2b712

File tree

2 files changed

+67
-11
lines changed

2 files changed

+67
-11
lines changed

src/http-data-source.ts

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import sjson from 'secure-json-parse'
88
import { KeyValueCache } from 'apollo-server-caching'
99
import { ResponseData } from 'undici/types/dispatcher'
1010
import { toApolloError } from 'apollo-server-errors'
11-
import { EventEmitter, Readable } from 'stream'
11+
import { EventEmitter } from 'stream'
1212
import { Logger } from 'apollo-server-types'
1313
import { URLSearchParams } from 'url'
1414

@@ -42,19 +42,14 @@ interface Dictionary<T> {
4242
[Key: string]: T | undefined
4343
}
4444

45-
export type RequestOptions = {
46-
context?: Dictionary<string>
47-
query?: Dictionary<string | number>
48-
body?: string | Buffer | Uint8Array | Readable | null
49-
headers?: Dictionary<string>
50-
signal?: AbortSignal
51-
} & CacheTTLOptions
45+
export type RequestOptions = Omit<Partial<Request>, 'origin' | 'path' | 'method'>
5246

5347
export type Request = {
5448
context: Dictionary<string>
5549
query: Dictionary<string | number>
56-
body: string | Buffer | Uint8Array | Readable | null
50+
body: any
5751
signal?: AbortSignal | EventEmitter | null
52+
json?: boolean
5853
origin: string
5954
path: string
6055
method: string
@@ -274,14 +269,23 @@ export abstract class HTTPDataSource<TContext = any> extends DataSource {
274269
await this.onRequest?.(request)
275270

276271
try {
277-
const responseData = await this.pool.request({
272+
const requestOptions = {
278273
method: request.method,
279274
origin: request.origin,
280275
path: request.path,
281276
body: request.body,
282277
headers: request.headers,
283278
signal: request.signal,
284-
})
279+
}
280+
281+
if (request.json === true) {
282+
if (requestOptions.headers['content-type'] === undefined) {
283+
requestOptions.headers['content-type'] = 'application/json; charset=utf-8'
284+
}
285+
requestOptions.body = JSON.stringify(requestOptions.body)
286+
}
287+
288+
const responseData = await this.pool.request(requestOptions)
285289
responseData.body.setEncoding('utf8')
286290

287291
let data = ''

test/http-data-source.test.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,58 @@ test('Should be able to make a simple POST call', async (t) => {
9999
t.deepEqual(response.body, { name: 'foo' })
100100
})
101101

102+
test('Should be able to make a simple POST with JSON body', async (t) => {
103+
t.plan(4)
104+
105+
const path = '/'
106+
107+
const wanted = { name: 'foo' }
108+
109+
const server = http.createServer((req, res) => {
110+
t.is(req.method, 'POST')
111+
t.is(req.headers['content-type'], 'application/json; charset=utf-8')
112+
113+
let data = ''
114+
115+
req.on('data', (chunk) => {
116+
data += chunk
117+
})
118+
req.on('end', () => {
119+
t.deepEqual(data, '{"foo":"bar"}')
120+
res.writeHead(200, {
121+
'content-type': 'application/json',
122+
})
123+
res.write(JSON.stringify(wanted))
124+
res.end()
125+
res.socket?.unref()
126+
})
127+
})
128+
129+
t.teardown(server.close.bind(server))
130+
131+
server.listen()
132+
133+
const baseURL = `http://localhost:${(server.address() as AddressInfo)?.port}`
134+
135+
const dataSource = new (class extends HTTPDataSource {
136+
constructor() {
137+
super(baseURL)
138+
}
139+
postFoo() {
140+
return this.post(path, {
141+
json: true,
142+
body: {
143+
foo: 'bar',
144+
},
145+
})
146+
}
147+
})()
148+
149+
const response = await dataSource.postFoo()
150+
151+
t.deepEqual(response.body, { name: 'foo' })
152+
})
153+
102154
test('Should be able to make a simple DELETE call', async (t) => {
103155
t.plan(2)
104156

0 commit comments

Comments
 (0)