Skip to content

Commit e8d3a0d

Browse files
authored
fix(request): correct parsing headers (#35)
* fix(request): correct parsing headers * format
1 parent df56ece commit e8d3a0d

File tree

2 files changed

+140
-1
lines changed

2 files changed

+140
-1
lines changed

src/commands/request/index.test.ts

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,4 +165,136 @@ describe('requestCommand', () => {
165165

166166
expect(consoleLogSpy).toHaveBeenCalledWith(expectedOutput)
167167
})
168+
169+
it('should handle single header option correctly', async () => {
170+
const mockApp = new Hono()
171+
mockApp.get('/api/test', (c) => {
172+
const auth = c.req.header('Authorization')
173+
if (!auth) {
174+
return c.text('No auth header', 400)
175+
}
176+
return c.json({ auth })
177+
})
178+
179+
const expectedPath = 'test-app.js'
180+
setupBasicMocks(expectedPath, mockApp)
181+
182+
await program.parseAsync([
183+
'node',
184+
'test',
185+
'request',
186+
'-P',
187+
'/api/test',
188+
'-H',
189+
'Authorization: Bearer token123',
190+
'test-app.js',
191+
])
192+
193+
expect(consoleLogSpy).toHaveBeenCalledWith(
194+
JSON.stringify(
195+
{
196+
status: 200,
197+
body: '{"auth":"Bearer token123"}',
198+
headers: { 'content-type': 'application/json' },
199+
},
200+
null,
201+
2
202+
)
203+
)
204+
})
205+
206+
it('should handle multiple header options correctly', async () => {
207+
const mockApp = new Hono()
208+
mockApp.get('/api/multi', (c) => {
209+
const auth = c.req.header('Authorization')
210+
const userAgent = c.req.header('User-Agent')
211+
const custom = c.req.header('X-Custom-Header')
212+
return c.json({ auth, userAgent, custom })
213+
})
214+
215+
const expectedPath = 'test-app.js'
216+
setupBasicMocks(expectedPath, mockApp)
217+
218+
await program.parseAsync([
219+
'node',
220+
'test',
221+
'request',
222+
'-P',
223+
'/api/multi',
224+
'-H',
225+
'Authorization: Bearer token456',
226+
'-H',
227+
'User-Agent: TestClient/1.0',
228+
'-H',
229+
'X-Custom-Header: custom-value',
230+
'test-app.js',
231+
])
232+
233+
expect(consoleLogSpy).toHaveBeenCalledWith(
234+
JSON.stringify(
235+
{
236+
status: 200,
237+
body: '{"auth":"Bearer token456","userAgent":"TestClient/1.0","custom":"custom-value"}',
238+
headers: { 'content-type': 'application/json' },
239+
},
240+
null,
241+
2
242+
)
243+
)
244+
})
245+
246+
it('should handle no header options correctly', async () => {
247+
const mockApp = new Hono()
248+
mockApp.get('/api/noheader', (c) => {
249+
const headers = Object.fromEntries(c.req.raw.headers.entries())
250+
return c.json({ receivedHeaders: headers })
251+
})
252+
253+
const expectedPath = 'test-app.js'
254+
setupBasicMocks(expectedPath, mockApp)
255+
256+
await program.parseAsync(['node', 'test', 'request', '-P', '/api/noheader', 'test-app.js'])
257+
258+
// Should not include any custom headers, only default ones
259+
const output = consoleLogSpy.mock.calls[0][0] as string
260+
const result = JSON.parse(output)
261+
expect(result.status).toBe(200)
262+
expect(result.headers['content-type']).toBe('application/json')
263+
})
264+
265+
it('should handle malformed header gracefully', async () => {
266+
const mockApp = new Hono()
267+
mockApp.get('/api/malformed', (c) => {
268+
return c.json({ success: true })
269+
})
270+
271+
const expectedPath = 'test-app.js'
272+
setupBasicMocks(expectedPath, mockApp)
273+
274+
await program.parseAsync([
275+
'node',
276+
'test',
277+
'request',
278+
'-P',
279+
'/api/malformed',
280+
'-H',
281+
'MalformedHeader', // Missing colon
282+
'-H',
283+
'ValidHeader: value',
284+
'test-app.js',
285+
])
286+
287+
// Should still work, malformed header is ignored
288+
expect(consoleLogSpy).toHaveBeenCalledWith(
289+
JSON.stringify(
290+
{
291+
status: 200,
292+
body: '{"success":true}',
293+
headers: { 'content-type': 'application/json' },
294+
},
295+
null,
296+
2
297+
)
298+
)
299+
})
168300
})

src/commands/request/index.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,14 @@ export function requestCommand(program: Command) {
2222
.option('-P, --path <path>', 'Request path', '/')
2323
.option('-X, --method <method>', 'HTTP method', 'GET')
2424
.option('-d, --data <data>', 'Request body data')
25-
.option('-H, --header <header>', 'Custom headers', [])
25+
.option(
26+
'-H, --header <header>',
27+
'Custom headers',
28+
(value: string, previous: string[]) => {
29+
return previous ? [...previous, value] : [value]
30+
},
31+
[] as string[]
32+
)
2633
.action(async (file: string | undefined, options: RequestOptions) => {
2734
const path = options.path || '/'
2835
const result = await executeRequest(file, path, options)

0 commit comments

Comments
 (0)