diff --git a/.changeset/healthy-buckets-drum.md b/.changeset/healthy-buckets-drum.md new file mode 100644 index 00000000..fb129dfe --- /dev/null +++ b/.changeset/healthy-buckets-drum.md @@ -0,0 +1,5 @@ +--- +"@web-io/fetch": patch +--- + +If locationURL’s scheme is not an HTTP(S) scheme, then return a network error. https://fetch.spec.whatwg.org/#http-redirect-fetch diff --git a/.github/workflows/blob.yml b/.github/workflows/blob.yml index c147ad9c..8346c0db 100644 --- a/.github/workflows/blob.yml +++ b/.github/workflows/blob.yml @@ -17,6 +17,7 @@ jobs: name: Typecheck runs-on: ubuntu-latest strategy: + fail-fast: false matrix: node-version: - 16 @@ -42,9 +43,9 @@ jobs: runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: node-version: - - 14 - 16 os: - ubuntu-latest diff --git a/.github/workflows/fetch.yml b/.github/workflows/fetch.yml index 663430c7..65d022fc 100644 --- a/.github/workflows/fetch.yml +++ b/.github/workflows/fetch.yml @@ -18,6 +18,7 @@ jobs: name: Typecheck runs-on: ubuntu-latest strategy: + fail-fast: false matrix: node-version: - 16 @@ -44,9 +45,9 @@ jobs: runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: node-version: - - 14 - 16 os: - ubuntu-latest @@ -54,12 +55,6 @@ jobs: - macos-latest project: - fetch - exclude: - - os: windows-latest - node-version: 14 - # On macOS, run tests with only the LTS environments. - - os: macos-latest - node-version: 14 steps: - uses: actions/checkout@v2 @@ -75,12 +70,5 @@ jobs: - name: Test (ESM) run: yarn --cwd packages/${{matrix.project}} test -- --colors - # upload coverage only once - - name: Coveralls - uses: coverallsapp/github-action@master - if: matrix.node == '14' && matrix.os == 'ubuntu-latest' - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - - name: Test (CJS) run: yarn --cwd packages/${{matrix.project}} test:cjs diff --git a/.github/workflows/file.yml b/.github/workflows/file.yml index 5ffe24c1..04c49b8e 100644 --- a/.github/workflows/file.yml +++ b/.github/workflows/file.yml @@ -17,6 +17,7 @@ jobs: name: Typecheck runs-on: ubuntu-latest strategy: + fail-fast: false matrix: node-version: - 16 @@ -42,9 +43,9 @@ jobs: runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: node-version: - - 14 - 16 os: - ubuntu-latest diff --git a/.github/workflows/form-data.yml b/.github/workflows/form-data.yml index 6238204b..0cf3ada8 100644 --- a/.github/workflows/form-data.yml +++ b/.github/workflows/form-data.yml @@ -18,6 +18,7 @@ jobs: name: Typecheck runs-on: ubuntu-latest strategy: + fail-fast: false matrix: node-version: - 16 @@ -43,9 +44,9 @@ jobs: runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: node-version: - - 14 - 16 os: - ubuntu-latest diff --git a/.github/workflows/stream.yml b/.github/workflows/stream.yml index e93c5349..321ef927 100644 --- a/.github/workflows/stream.yml +++ b/.github/workflows/stream.yml @@ -17,6 +17,7 @@ jobs: name: Typecheck runs-on: ubuntu-latest strategy: + fail-fast: false matrix: node-version: - 16 @@ -43,9 +44,9 @@ jobs: runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: node-version: - - 14 - 16 os: - ubuntu-latest @@ -76,6 +77,7 @@ jobs: runs-on: ubuntu-latest strategy: + fail-fast: false matrix: node-version: - 16 diff --git a/packages/fetch/src/fetch.js b/packages/fetch/src/fetch.js index 6a765428..8ced2170 100644 --- a/packages/fetch/src/fetch.js +++ b/packages/fetch/src/fetch.js @@ -180,6 +180,14 @@ async function fetch(url, options_ = {}) { return; } + // https://fetch.spec.whatwg.org/#http-redirect-fetch + // 6. If locationURL’s scheme is not an HTTP(S) scheme, then return a network error. + if (locationURL.protocol !== 'http:' && locationURL.protocol !== 'https:') { + reject(new FetchError('URL scheme must be a HTTP(S) scheme', 'bad-redirect-scheme')); + finalize(); + return; + } + // HTTP-redirect fetch step 6 (counter increment) // Create a new Request object. const requestOptions = { diff --git a/packages/fetch/test/main.js b/packages/fetch/test/main.js index 96dc2cdf..70dcc1e6 100644 --- a/packages/fetch/test/main.js +++ b/packages/fetch/test/main.js @@ -442,6 +442,15 @@ describe('node-fetch', () => { }); }); + it("should not follow non HTTP(s) redirect", () => { + const url = `${base}redirect/301/file`; + const options = { + }; + return expect(fetch(url, options)) + .to.eventually.be.rejected.and.be.an.instanceOf(FetchError) + .and.have.property("type", "bad-redirect-scheme"); + }); + it('should allow not following redirect', () => { const url = `${base}redirect/301`; const options = { @@ -1601,7 +1610,7 @@ describe('node-fetch', () => { const parameters = new URLSearchParams(); parameters.append('key', 'value'); const request = new Request(base, { - method: 'POST', + method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, diff --git a/packages/fetch/test/utils/server.js b/packages/fetch/test/utils/server.js index 2c28ab81..eaa3925b 100644 --- a/packages/fetch/test/utils/server.js +++ b/packages/fetch/test/utils/server.js @@ -235,6 +235,12 @@ export default class TestServer { res.end(); } + if (p === '/redirect/301/file') { + res.statusCode = 301; + res.setHeader('Location', 'file://inspect'); + res.end(); + } + if (p === '/redirect/301/rn') { res.statusCode = 301 res.setHeader('Location', '/403')