Skip to content

Commit

Permalink
Merge pull request #426 from swrlab/dev/undici-merge
Browse files Browse the repository at this point in the history
chore: merge `frytg/undici-wrapper` into this package
  • Loading branch information
frytg authored Jul 27, 2022
2 parents e3766f2 + e40b952 commit 1405f37
Show file tree
Hide file tree
Showing 9 changed files with 301 additions and 39 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ by [**SWR Audio Lab**](https://lab.swr.de/)

## Changelog

- 2022-07-26 - v1.0.10-beta
- chore: merge `frytg/undici-wrapper` into this package

- 2022-07-06 - v1.0.9-beta
- chore: update undici to v0.1.0 (with fix for `undici.request` instead of `Pool`)

Expand Down
11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@swrlab/utils",
"version": "1.0.9-beta",
"version": "1.0.10-beta",
"description": "Wrapping common SWR Audio Lab utils",
"main": "./src/index.js",
"engines": {
Expand All @@ -22,18 +22,19 @@
"license": "MIT",
"private": false,
"dependencies": {
"@google-cloud/storage": "6.2.2",
"aws-sdk": "2.1168.0",
"@google-cloud/storage": "^6.2.3",
"abort-controller": "^3.0.0",
"aws-sdk": "^2.1181.0",
"chai": "^4.3.6",
"node-crc": "rafaelmaeuer/node-crc#v2.0.15",
"undici-wrapper": "frytg/undici-wrapper#v0.1.0",
"undici": "^5.8.0",
"uuid": "8.3.2"
},
"devDependencies": {
"@swrlab/eslint-plugin-swr": "0.1.2",
"@swrlab/swr-prettier-config": "0.1.2",
"dotenv": "^16.0.1",
"eslint": "^8.19.0",
"eslint": "^8.20.0",
"eslint-plugin-json": "^3.1.0",
"mocha": "^10.0.0",
"prettier": "^2.7.1"
Expand Down
43 changes: 42 additions & 1 deletion packages/undici/README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,57 @@
# SWR Audio Lab / Undici

Please see [github/undici-wrapper](https://github.com/frytg/undici-wrapper) for the full configuration options.
See [undici.nodejs.org](https://undici.nodejs.org) for the full Undici configuration and usage.

- [SWR Audio Lab / Undici](#swr-audio-lab--undici)
- [Import](#import)
- [Request](#request)

## Import

Basic import:

```js
// load request handler
const undici = require('@swrlab/utils/packages/undici')

// export handler
module.exports = undici()
```

Import with Datadog tracer enabled:

```js
// add tracing
const tracer = process.env.DD_TRACE_ENABLED === 'true' ? require('../tracer') : null

// load request handler
const undici = require('@swrlab/utils/packages/undici')

// export handler
module.exports = undici(tracer)
```

## Request

Simple request:

```js
const data = await undici(someApiUrl)
```

Advanced usage:

```js
const data = await undici(someApiUrl, {
method: 'GET',
timeout: 6e3,
reject: false,
maxRedirections: 5
})
```

You can also use object desctructuring for easy access to the output:

```js
const { headers, statusCode, json } = await undici(someApiUrl)
```
13 changes: 13 additions & 0 deletions packages/undici/_options.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// load config
const { name, version } = require('../../package.json')

const userAgent = `${name.replace('@', '')}/${version}`

module.exports = {
keepAliveTimeout: 30e3,
headersTimeout: 0,
bodyTimeout: 0,
headers: {
'user-agent': process.env.USER_AGENT || userAgent,
},
}
18 changes: 18 additions & 0 deletions packages/undici/convertReadableStream.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// provide util to confert readable stream to buffer
module.exports = async (readable) => {
// create output details
let string = ''
const chunks = []

// handle each chunk
for await (const chunk of readable) {
string += chunk
chunks.push(chunk)
}

// reformat buffer
const buffer = Buffer.concat(chunks)

// return data
return { string, buffer }
}
8 changes: 4 additions & 4 deletions packages/undici/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// load request handler
const undici = require('undici-wrapper')
// load utils
const request = require('./request')

// export handler
module.exports = undici
// export handler with tracing, if enabled
module.exports = (tracer) => tracer?.wrap('undici.request', request) || request
77 changes: 77 additions & 0 deletions packages/undici/request.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/* eslint-disable prefer-promise-reject-errors */

// load node utils
const undici = require('undici')
const AbortController = require('abort-controller')

// fetch options and utils
const _options = require('./_options')
const convertReadableStream = require('./convertReadableStream')

const DEFAULT_TIMEOUT = 7e3

module.exports = async (url, options) => {
// use controller for timeouts
const abortController = new AbortController()
const abortTimeout = setTimeout(() => {
abortController.abort()
}, options?.timeout || DEFAULT_TIMEOUT)

// calculcate redirect
const maxRedirections =
options?.maxRedirections !== null && options?.maxRedirections !== undefined
? options.maxRedirections
: 5

// prepare options
const requestOptions = {
..._options,
method: options?.method || 'GET',
body: options?.body || undefined,
signal: abortController.signal,
maxRedirections,
}
if (options?.headers) requestOptions.headers = { ...requestOptions.headers, ...options.headers }

// make actual request
const { statusCode, headers, trailers, body } = await undici.request(url, requestOptions)

// remove timeout since request finished beforehand
clearTimeout(abortTimeout)

// set ok
const ok = statusCode >= 200 && statusCode < 300
if (!ok && (!options || options?.reject !== false)) return Promise.reject({ statusCode, ok, headers, url })

// turn stream into string
const { string, buffer } = await convertReadableStream(body)

// detect/ set redirect
const redirect =
statusCode >= 300 && statusCode < 400 && headers.location ? new URL(headers.location, url) : null

// fetch header vars
const contentType = headers['content-type']

// parse json if set
let json
try {
json = contentType?.indexOf('application/json') !== -1 ? JSON.parse(string) : null
} catch (error) {
json = null
}

// return data
return Promise.resolve({
statusCode,
ok,
redirect,
headers,
contentType,
trailers,
body,
string,
buffer,
json,
})
}
2 changes: 1 addition & 1 deletion utils/undici/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

// load request handler
const undici = require('undici-wrapper')
const undici = require('../../packages/undici/index')

// export handler
module.exports = undici()
Loading

0 comments on commit 1405f37

Please sign in to comment.