mirror of
https://github.com/langgenius/dify.git
synced 2026-07-22 03:08:33 +08:00
138 lines
4.0 KiB
TypeScript
138 lines
4.0 KiB
TypeScript
import type { AddressInfo } from 'node:net'
|
|
import { createServer } from 'node:http'
|
|
import { Readable } from 'node:stream'
|
|
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
|
|
import { HttpClient } from '../src/http/client'
|
|
|
|
const readBody = async (stream: NodeJS.ReadableStream): Promise<Buffer> => {
|
|
const chunks: Buffer[] = []
|
|
for await (const chunk of stream) {
|
|
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk))
|
|
}
|
|
return Buffer.concat(chunks)
|
|
}
|
|
|
|
describe('HttpClient integration', () => {
|
|
const requests: Array<{
|
|
url: string
|
|
method: string
|
|
headers: Record<string, string | string[] | undefined>
|
|
body: Buffer
|
|
}> = []
|
|
|
|
const server = createServer((req, res) => {
|
|
void (async () => {
|
|
const body = await readBody(req)
|
|
requests.push({
|
|
url: req.url ?? '',
|
|
method: req.method ?? '',
|
|
headers: req.headers,
|
|
body,
|
|
})
|
|
|
|
if (req.url?.startsWith('/json')) {
|
|
res.writeHead(200, { 'content-type': 'application/json', 'x-request-id': 'req-json' })
|
|
res.end(JSON.stringify({ ok: true }))
|
|
return
|
|
}
|
|
|
|
if (req.url === '/stream') {
|
|
res.writeHead(200, { 'content-type': 'text/event-stream' })
|
|
res.end('data: {"answer":"hello"}\n\ndata: {"delta":" world"}\n\n')
|
|
return
|
|
}
|
|
|
|
if (req.url === '/bytes') {
|
|
res.writeHead(200, { 'content-type': 'application/octet-stream' })
|
|
res.end(Buffer.from([1, 2, 3, 4]))
|
|
return
|
|
}
|
|
|
|
if (req.url === '/upload-stream') {
|
|
res.writeHead(200, { 'content-type': 'application/json' })
|
|
res.end(JSON.stringify({ received: body.toString('utf8') }))
|
|
return
|
|
}
|
|
|
|
res.writeHead(404, { 'content-type': 'application/json' })
|
|
res.end(JSON.stringify({ message: 'not found' }))
|
|
})()
|
|
})
|
|
|
|
let client: HttpClient
|
|
|
|
beforeAll(async () => {
|
|
await new Promise<void>((resolve) => {
|
|
server.listen(0, '127.0.0.1', () => resolve())
|
|
})
|
|
const address = server.address() as AddressInfo
|
|
client = new HttpClient({
|
|
apiKey: 'test-key',
|
|
baseUrl: `http://127.0.0.1:${address.port}`,
|
|
maxRetries: 0,
|
|
retryDelay: 0,
|
|
})
|
|
})
|
|
|
|
afterAll(async () => {
|
|
await new Promise<void>((resolve, reject) => {
|
|
server.close((error) => {
|
|
if (error) {
|
|
reject(error)
|
|
return
|
|
}
|
|
resolve()
|
|
})
|
|
})
|
|
})
|
|
|
|
it('uses real fetch for query serialization and json bodies', async () => {
|
|
const response = await client.request({
|
|
method: 'POST',
|
|
path: '/json',
|
|
query: { tag_ids: ['a', 'b'], limit: 2 },
|
|
data: { user: 'u' },
|
|
})
|
|
|
|
expect(response.requestId).toBe('req-json')
|
|
expect(response.data).toEqual({ ok: true })
|
|
expect(requests.at(-1)).toMatchObject({
|
|
url: '/json?tag_ids=a&tag_ids=b&limit=2',
|
|
method: 'POST',
|
|
})
|
|
expect(requests.at(-1)?.headers.authorization).toBe('Bearer test-key')
|
|
expect(requests.at(-1)?.headers['content-type']).toBe('application/json')
|
|
expect(requests.at(-1)?.body.toString('utf8')).toBe(JSON.stringify({ user: 'u' }))
|
|
})
|
|
|
|
it('supports streaming request bodies with duplex fetch', async () => {
|
|
const response = await client.request<{ received: string }>({
|
|
method: 'POST',
|
|
path: '/upload-stream',
|
|
data: Readable.from(['hello ', 'world']),
|
|
})
|
|
|
|
expect(response.data).toEqual({ received: 'hello world' })
|
|
expect(requests.at(-1)?.body.toString('utf8')).toBe('hello world')
|
|
})
|
|
|
|
it('parses real sse responses into text', async () => {
|
|
const stream = await client.requestStream({
|
|
method: 'GET',
|
|
path: '/stream',
|
|
})
|
|
|
|
await expect(stream.toText()).resolves.toBe('hello world')
|
|
})
|
|
|
|
it('parses real byte responses into buffers', async () => {
|
|
const response = await client.request<Buffer, 'bytes'>({
|
|
method: 'GET',
|
|
path: '/bytes',
|
|
responseType: 'bytes',
|
|
})
|
|
|
|
expect(Array.from(response.data.values())).toEqual([1, 2, 3, 4])
|
|
})
|
|
})
|