Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fallback to Buffer.isUtf8 on platforms without icu #7

Closed
wants to merge 26 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
7fb8232
6.10.2
ronag Mar 27, 2024
d7f10e1
refactor(#3023): Pass headers as array instead (#3025)
metcoder95 Apr 1, 2024
2d5cbdf
fix: don't leak internal class (#3024)
ronag Apr 1, 2024
63968e0
build(deps): bump codecov/codecov-action from 4.1.0 to 4.1.1 (#3034)
dependabot[bot] Apr 1, 2024
63f0fee
build(deps-dev): bump tsd from 0.30.7 to 0.31.0 (#3038)
dependabot[bot] Apr 1, 2024
8dea744
build(deps-dev): bump borp from 0.9.1 to 0.10.0 (#2947)
dependabot[bot] Apr 1, 2024
3ac3682
Merge branch 'main' of github.com:nodejs/undici
mcollina Apr 2, 2024
6131341
enhancement: link to the contributing guide from the README (#3003)
FatumaA Mar 31, 2024
03e7b0c
fix: node:util instead of util (#3007)
mertcanaltin Mar 28, 2024
b197a01
fix(workflows): missing top-level content.read permissions (#3013)
fraxken Mar 28, 2024
4b86ede
chore: add automated CI testing with —no-intl node (#3015)
mweberxyz Mar 31, 2024
9e47216
chore(workflows/nightly.yml): create issue only on all fail (#3020)
mweberxyz Mar 30, 2024
c18df9c
chore(automerge): remove unnecessary actions:write permission (#3021)
fraxken Mar 31, 2024
c61b5f9
fix(#2364): concurrent aborts (#3005)
ronag Apr 2, 2024
f8bd60f
fixup
mcollina Apr 2, 2024
8b5e2c8
fixup
mcollina Apr 2, 2024
c8a43ae
fixup
mcollina Apr 2, 2024
31f9e67
build(deps): bump actions/checkout from 4.1.1 to 4.1.2 (#3036)
dependabot[bot] Apr 2, 2024
0f0f239
fix: regexp pattern (#3041)
tsctx Apr 2, 2024
71a6d74
Merge branch 'main' of github.com:nodejs/undici
mcollina Apr 2, 2024
ee5f892
Bumped v6.11.0
mcollina Apr 2, 2024
6805746
Merge pull request from GHSA-m4v8-wqvr-p9f7
mcollina Apr 2, 2024
d542b8c
Merge pull request from GHSA-9qxr-qj54-h672
mcollina Apr 2, 2024
c346b66
Revert "fix: don't leak internal class (#3024)"
mcollina Apr 2, 2024
6df3c73
Bumped v6.11.1
mcollina Apr 2, 2024
a676213
fallback to Buffer.isUtf8 on platforms without icu
KhafraDev Mar 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/bench.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
with:
persist-credentials: false
ref: ${{ github.base_ref }}
Expand All @@ -34,7 +34,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
with:
persist-credentials: false
- name: Setup Node
Expand All @@ -55,7 +55,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
with:
persist-credentials: false
ref: ${{ github.base_ref }}
Expand All @@ -77,7 +77,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
with:
persist-credentials: false
- name: Setup Node
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
egress-policy: audit

- name: Checkout repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/fuzz.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
with:
persist-credentials: false

Expand Down
38 changes: 26 additions & 12 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,40 @@ on:
schedule:
- cron: "0 10 * * *"

permissions:
contents: read

jobs:
test:
test-linux:
if: github.repository == 'nodejs/undici'
uses: ./.github/workflows/test.yml
with:
node-version: 22-nightly
runs-on: ubuntu-latest
secrets: inherit

test-windows:
if: github.repository == 'nodejs/undici'
uses: ./.github/workflows/test.yml
with:
node-version: 22-nightly
runs-on: windows-latest
secrets: inherit

test-macos:
if: github.repository == 'nodejs/undici'
strategy:
fail-fast: false
max-parallel: 0
matrix:
runs-on:
- ubuntu-latest
- windows-latest
- macos-latest
uses: ./.github/workflows/test.yml
with:
node-version: 22-nightly
runs-on: ${{ matrix.runs-on }}
runs-on: macos-latest
secrets: inherit

report-failure:
if: failure()
needs: test
if: ${{ always() && (needs.test-linux.result == 'failure' && needs.test-windows.result == 'failure' && needs.test-macos.result == 'failure') }}
needs:
- test-linux
- test-windows
- test-macos
runs-on: ubuntu-latest
permissions:
issues: write
Expand Down
79 changes: 75 additions & 4 deletions .github/workflows/nodejs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
egress-policy: audit

- name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
with:
persist-credentials: false

Expand All @@ -35,7 +35,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
with:
persist-credentials: false

Expand Down Expand Up @@ -69,13 +69,84 @@ jobs:
runs-on: ${{ matrix.runs-on }}
secrets: inherit

test-without-intl:
name: Test with Node.js ${{ matrix.version }} compiled --without-intl
strategy:
fail-fast: false
max-parallel: 0
matrix:
version: [20, 21]
runs-on: ubuntu-latest
timeout-minutes: 120
steps:
- name: Checkout
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
with:
persist-credentials: false

# Setup node, install deps, and build undici prior to building icu-less node and testing
- name: Setup Node.js@${{ inputs.version }}
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
node-version: ${{ inputs.version }}

- name: Install dependencies
run: npm install

- name: Build undici
run: npm run build:node

- name: Determine latest release
id: release
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
result-encoding: string
script: |
const req = await fetch('https://nodejs.org/download/release/index.json')
const releases = await req.json()

const latest = releases.find((r) => r.version.startsWith('v${{ matrix.version }}'))
return latest.version

- name: Download and extract source
run: curl https://nodejs.org/download/release/${{ steps.release.outputs.result }}/node-${{ steps.release.outputs.result }}.tar.xz | tar xfJ -

- name: Install ninja
run: sudo apt-get install ninja-build

- name: ccache
uses: hendrikmuhs/ccache-action@faf867a11c028c0b483fb2ae72b6fc8f7d842714 #v1.2.12
with:
key: node${{ matrix.version }}

- name: Build node
working-directory: ./node-${{ steps.release.outputs.result }}
run: |
export CC="ccache gcc"
export CXX="ccache g++"
./configure --without-intl --ninja --prefix=./final
make
make install
echo "$(pwd)/final/bin" >> $GITHUB_PATH

- name: Print version information
run: |
echo OS: $(node -p "os.version()")
echo Node.js: $(node --version)
echo npm: $(npm --version)
echo git: $(git --version)
echo icu config: $(node -e "console.log(process.config)" | grep icu)

- name: Run tests
run: npm run test:javascript:withoutintl

test-types:
name: Test TypeScript types
timeout-minutes: 15
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
with:
persist-credentials: false

Expand All @@ -97,12 +168,12 @@ jobs:
- dependency-review
- test
- test-types
- test-without-intl
- lint
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
actions: write
steps:
- name: Merge Dependabot PR
uses: fastify/github-action-merge-dependabot@9e7bfb249c69139d7bdcd8d984f9665edd49020b # v3.10.1
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish-undici-types.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
node-version: lts/*
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:

steps:
- name: "Checkout code"
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
with:
persist-credentials: false

Expand Down
7 changes: 5 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,17 @@ on:
required: true
type: string

permissions:
contents: read

jobs:
test:
name: Test with Node.js ${{ inputs.node-version }} on ${{ inputs.runs-on }}
timeout-minutes: 15
runs-on: ${{ inputs.runs-on }}
steps:
- name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
with:
persist-credentials: false

Expand Down Expand Up @@ -48,6 +51,6 @@ jobs:

- name: Coverage Report
if: inputs.runs-on == 'ubuntu-latest' && inputs.node-version == 20
uses: codecov/codecov-action@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # v4.1.0
uses: codecov/codecov-action@c16abc29c95fcf9174b58eb7e1abf4c866893bc8 # v4.1.1
with:
token: ${{ secrets.CODECOV_TOKEN }}
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@ An HTTP/1.1 client, written from scratch for Node.js.
> Undici means eleven in Italian. 1.1 -> 11 -> Eleven -> Undici.
It is also a Stranger Things reference.

## How to get involved

Have a question about using Undici? Open a [Q&A Discussion](https://github.com/nodejs/undici/discussions/new) or join our official OpenJS [Slack](https://openjs-foundation.slack.com/archives/C01QF9Q31QD) channel.

Looking to contribute? Start by reading the [contributing guide](./CONTRIBUTING.md)

## Install

```
Expand Down
24 changes: 24 additions & 0 deletions benchmarks/fetch/bytes-match.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { createHash } from 'node:crypto'
import { bench, run } from 'mitata'
import { bytesMatch } from '../../lib/web/fetch/util.js'

const body = Buffer.from('Hello world!')
const validSha256Base64 = `sha256-${createHash('sha256').update(body).digest('base64')}`
const invalidSha256Base64 = `sha256-${createHash('sha256').update(body).digest('base64')}`
const validSha256Base64Url = `sha256-${createHash('sha256').update(body).digest('base64url')}`
const invalidSha256Base64Url = `sha256-${createHash('sha256').update(body).digest('base64url')}`

bench('bytesMatch valid sha256 and base64', () => {
bytesMatch(body, validSha256Base64)
})
bench('bytesMatch invalid sha256 and base64', () => {
bytesMatch(body, invalidSha256Base64)
})
bench('bytesMatch valid sha256 and base64url', () => {
bytesMatch(body, validSha256Base64Url)
})
bench('bytesMatch invalid sha256 and base64url', () => {
bytesMatch(body, invalidSha256Base64Url)
})

await run()
3 changes: 0 additions & 3 deletions lib/core/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -246,9 +246,6 @@ function bufferToLowerCasedHeaderName (value) {
* @returns {Record<string, string | string[]>}
*/
function parseHeaders (headers, obj) {
// For H2 support
if (!Array.isArray(headers)) return headers

if (obj === undefined) obj = {}
for (let i = 0; i < headers.length; i += 2) {
const key = headerNameToString(headers[i])
Expand Down
28 changes: 27 additions & 1 deletion lib/dispatcher/client-h2.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,20 @@ const {
}
} = http2

function parseH2Headers (headers) {
// set-cookie is always an array. Duplicates are added to the array.
// For duplicate cookie headers, the values are joined together with '; '.
headers = Object.entries(headers).flat(2)

const result = []

for (const header of headers) {
result.push(Buffer.from(header))
}

return result
}

async function connectH2 (client, socket) {
client[kSocket] = socket

Expand Down Expand Up @@ -391,7 +405,19 @@ function writeH2 (client, request) {
const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers
request.onResponseStarted()

if (request.onHeaders(Number(statusCode), realHeaders, stream.resume.bind(stream), '') === false) {
// Due to the stream nature, it is possible we face a race condition
// where the stream has been assigned, but the request has been aborted
// the request remains in-flight and headers hasn't been received yet
// for those scenarios, best effort is to destroy the stream immediately
// as there's no value to keep it open.
if (request.aborted || request.completed) {
const err = new RequestAbortedError()
errorRequest(client, request, err)
util.destroy(stream, err)
return
}

if (request.onHeaders(Number(statusCode), parseH2Headers(realHeaders), stream.resume.bind(stream), '') === false) {
stream.pause()
}

Expand Down
4 changes: 2 additions & 2 deletions lib/handler/redirect-handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,9 @@ function shouldRemoveHeader (header, removeContent, unknownOrigin) {
if (removeContent && util.headerNameToString(header).startsWith('content-')) {
return true
}
if (unknownOrigin && (header.length === 13 || header.length === 6)) {
if (unknownOrigin && (header.length === 13 || header.length === 6 || header.length === 19)) {
const name = util.headerNameToString(header)
return name === 'authorization' || name === 'cookie'
return name === 'authorization' || name === 'cookie' || name === 'proxy-authorization'
}
return false
}
Expand Down
5 changes: 4 additions & 1 deletion lib/mock/pending-interceptors-formatter.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
const { Transform } = require('node:stream')
const { Console } = require('node:console')

const PERSISTENT = process.versions.icu ? '✅' : 'Y '
const NOT_PERSISTENT = process.versions.icu ? '❌' : 'N '

/**
* Gets the output of `console.table(…)` as a string.
*/
Expand All @@ -29,7 +32,7 @@ module.exports = class PendingInterceptorsFormatter {
Origin: origin,
Path: path,
'Status code': statusCode,
Persistent: persist ? '✅' : '❌',
Persistent: persist ? PERSISTENT : NOT_PERSISTENT,
Invocations: timesInvoked,
Remaining: persist ? Infinity : times - timesInvoked
}))
Expand Down
Loading