feat: HTTP.Node.fetchProxy

This commit is contained in:
orion 2024-02-23 19:54:08 -06:00
parent d74d343165
commit 589a8b0eec
Signed by: orion
GPG Key ID: 6D4165AE4C928719
4 changed files with 63 additions and 1 deletions

BIN
bun.lockb

Binary file not shown.

View File

@ -14,5 +14,8 @@
"peerDependencies": {
"typescript": "^5.0.0"
},
"dependencies": {}
"dependencies": {},
"optionalDependencies": {
"fetch-socks": "^1.2.0"
}
}

19
src/HTTP/Node.js Normal file
View File

@ -0,0 +1,19 @@
import { fetch, ProxyAgent } from 'undici'
import { socksDispatcher } from 'fetch-socks'
/** @type {(_: URL) => (_: URL) => (_: string) => (_: Record<string, string>) => (_: null | string | FormData) => () => Promise<import('undici').Response>} */
export const fetchImpl = proxyURL => url => method => headers => body => () => {
const dispatcher = proxyURL.protocol.startsWith('https')
? new ProxyAgent(proxyURL.host)
: proxyURL.protocol.startsWith('socks')
? socksDispatcher({
type: 5,
host: proxyURL.hostname,
port: parseInt(proxyURL.port, 10),
})
: (() => {
throw new Error(`unsupported proxy scheme ${proxyURL.protocol}`)
})()
return fetch(url, { dispatcher })
}

40
src/HTTP/Node.purs Normal file
View File

@ -0,0 +1,40 @@
module HTTP.Node (fetchProxy, module X) where
import Prelude
import Control.Promise (Promise)
import Control.Promise as Promise
import Data.Nullable (Nullable)
import Data.Nullable as Nullable
import Data.URL (URL)
import Effect (Effect)
import Effect.Aff.Class (class MonadAff, liftAff)
import Foreign.Object (Object)
import Foreign.Object as Object
import HTTP.Header (Headers(..))
import HTTP.Header (headers) as X
import HTTP.Request (bodyToRaw)
import HTTP.Request (class Request, Method(..)) as X
import HTTP.Request as Req
import HTTP.Response (Response)
foreign import fetchImpl :: URL -> URL -> String -> Object String -> Nullable Req.RawRequestBody -> Effect (Promise Response)
fetchProxy :: forall m a. MonadAff m => Req.Request a => URL -> a -> m Response
fetchProxy pxy req = do
url <- Req.requestUrl req
method <- Req.requestMethod req
body <- Req.requestBody req
bodyRaw <- bodyToRaw body
Headers headers <- Req.requestHeaders req
let
methodStr = case method of
Req.GET -> "GET"
Req.PUT -> "PUT"
Req.POST -> "POST"
Req.PATCH -> "PATCH"
Req.DELETE -> "DELETE"
headers' = Object.fromFoldableWithIndex headers
liftAff $ Promise.toAffE $ fetchImpl pxy url methodStr headers' $ Nullable.toNullable bodyRaw