Skip to content

Commit

Permalink
feat(http): basic support for proxy agent
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Feb 11, 2024
1 parent c2ff28a commit fea2f99
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 12 deletions.
11 changes: 8 additions & 3 deletions packages/http/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "Axios-style HTTP client service for Cordis",
"version": "0.1.0",
"type": "module",
"module": "lib/index.js",
"main": "lib/index.js",
"types": "lib/index.d.ts",
"exports": {
".": {
Expand Down Expand Up @@ -42,20 +42,25 @@
"cordis",
"http",
"fetch",
"axios",
"undici",
"client",
"request",
"service",
"plugin"
],
"devDependencies": {
"cordis": "^3.9.2"
"cordis": "^3.9.2",
"undici": "^6.6.2"
},
"peerDependencies": {
"cordis": "^3.9.2"
},
"dependencies": {
"cosmokit": "^1.5.2",
"file-type": "^16.5.4",
"unws": "^0.2.4",
"http-proxy-agent": "^7.0.0",
"https-proxy-agent": "^7.0.2",
"ws": "^8.16.0"
}
}
4 changes: 4 additions & 0 deletions packages/http/src/adapter/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
import { LookupAddress } from 'dns'
import { HTTP } from '../index.js'

const ws = typeof WebSocket !== 'undefined' ? WebSocket : null

export { ws as WebSocket }

const v4 = /^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$/

const v6seg = '[a-fA-F\\d]{1,4}'
Expand Down
1 change: 1 addition & 0 deletions packages/http/src/adapter/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { LookupAddress } from 'dns'
import { HTTP } from '../index.ts'

export { WebSocket }
export function loadFile(url: string): Promise<HTTP.FileResponse | undefined>
export function lookup(address: string): Promise<LookupAddress>
1 change: 1 addition & 0 deletions packages/http/src/adapter/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { fromBuffer } from 'file-type'
import { HTTP } from '../index.js'
import { readFile } from 'node:fs/promises'

export { WebSocket } from 'ws'
export { lookup } from 'node:dns/promises'

export async function loadFile(url: string): Promise<HTTP.FileResponse | undefined> {
Expand Down
46 changes: 37 additions & 9 deletions packages/http/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Context } from 'cordis'
import { base64ToArrayBuffer, Dict, trimSlash } from 'cosmokit'
import { WebSocket } from 'unws'
import { ClientOptions } from 'ws'
import { loadFile, lookup } from './adapter/index.js'
import { loadFile, lookup, WebSocket } from './adapter/index.js'
import { isLocalAddress } from './utils.js'
import type * as undici from 'undici'
import type * as http from 'http'

declare module 'cordis' {
interface Context {
Expand All @@ -13,6 +14,11 @@ declare module 'cordis' {
interface Intercept {
http: HTTP.Config
}

interface Events {
'http/dispatcher'(url: URL): undici.Dispatcher | undefined
'http/http-agent'(url: URL): http.Agent | undefined
}
}

const _Error = Error
Expand Down Expand Up @@ -135,11 +141,15 @@ export function apply(ctx: Context, config?: HTTP.Config) {
}

function resolveURL(url: string | URL, config: HTTP.RequestConfig) {
try {
return new URL(url, config.baseURL).href
} catch {
return trimSlash(config.endpoint || '') + url
if (config.endpoint) {
ctx.emit('internal/warning', 'endpoint is deprecated, please use baseURL instead')
url = trimSlash(config.endpoint) + url
}
url = new URL(url, config.baseURL)
for (const [key, value] of Object.entries(config.params ?? {})) {
url.searchParams.append(key, value)
}
return url
}

function decode(response: Response) {
Expand All @@ -153,6 +163,14 @@ export function apply(ctx: Context, config?: HTTP.Config) {
}
}

function resolveDispatcher(href?: string) {
if (!href) return
const url = new URL(href)
const agent = ctx.bail('http/dispatcher', url)
if (agent) return agent
throw new Error(`Cannot resolve proxy agent ${url}`)
}

const http = async function http(this: Context, ...args: any[]) {
let method: HTTP.Method | undefined
if (typeof args[1] === 'string' || args[1] instanceof URL) {
Expand All @@ -176,6 +194,7 @@ export function apply(ctx: Context, config?: HTTP.Config) {
body: config.data,
headers: config.headers,
signal: controller.signal,
['dispatcher' as never]: resolveDispatcher(config?.proxyAgent),
}).catch((cause) => {
const error = new HTTP.Error(cause.message)
error.cause = cause
Expand Down Expand Up @@ -247,11 +266,20 @@ export function apply(ctx: Context, config?: HTTP.Config) {
return response.headers
}

http.ws = async function (this: HTTP, url: string, init?: HTTP.Config) {
function resolveAgent(href?: string) {
if (!href) return
const url = new URL(href)
const agent = ctx.bail('http/http-agent', url)
if (agent) return agent
throw new Error(`Cannot resolve proxy agent ${url}`)
}

http.ws = async function (this: HTTP, url: string | URL, init?: HTTP.Config) {
const caller = this[Context.current]
const config = mergeConfig(caller, init)
url = resolveURL(url, config)
const socket = new WebSocket(url, 'Server' in WebSocket ? {
// agent: caller.agent(config?.proxyAgent),
agent: resolveAgent(config?.proxyAgent),
handshakeTimeout: config?.timeout,
headers: config?.headers,
} as ClientOptions as never : undefined)
Expand All @@ -275,7 +303,7 @@ export function apply(ctx: Context, config?: HTTP.Config) {
responseType: 'arraybuffer',
timeout: +options.timeout! || undefined,
})
const mime = headers['content-type']
const mime = headers.get('Content-Type') ?? undefined
const [, name] = responseUrl.match(/.+\/([^/?]*)(?=\?)?/)!
return { mime, name, data }
}
Expand Down

0 comments on commit fea2f99

Please sign in to comment.