denoland / deno

A modern runtime for JavaScript and TypeScript.
https://deno.com
MIT License
98.07k stars 5.4k forks source link

[BUG]: Fetch throw "http2 error: stream error received: refused stream before processing any application logic" #21548

Open RodrigoTomeES opened 11 months ago

RodrigoTomeES commented 11 months ago

Version: Deno 1.38.5

This is an example that when you run it throw the error TypeError: error sending request for url (https://resa.es/en/residences/madrid/erasmo/): http2 error: stream error received: refused stream before processing any application logic. If you try to fetch that url individually it works but when you run the script a lot of pages failed.

Total: 177/621, skipped: 444

.env

SITEMAP="https://resa.es/sitemap.xml"

main.ts

import { load as loadEnv } from "https://deno.land/std@0.208.0/dotenv/mod.ts";

import Sitemapper from "npm:sitemapper";

await loadEnv({ export: true });

const Website = new Sitemapper({
  url: Deno.env.get("SITEMAP"),
  timeout: 15000,
});

try {
  const { sites } = await Website.fetch();

  const report: Array<boolean> = (
    await Promise.all(
      sites.map(async (url) => {
        try {
          await (await fetch(url)).text();
          return true;
        } catch (error) {
          console.error(error);
          return false;
        }
      })
    )
  ).filter(Boolean);

  const urls = sites.length;
  const total = report.length;

  console.log(`Total: ${total}/${urls}, skipped: ${urls - total}`);
} catch (error) {
  console.error(error);
}

EDIT: I updated the code with a minimal reproduction

RodrigoTomeES commented 11 months ago

@littledivy I think the problem is related with the asynchrony because this version of the code works well.

import { load as loadEnv } from "https://deno.land/std@0.208.0/dotenv/mod.ts";

import Sitemapper from "npm:sitemapper";

await loadEnv({ export: true });

const Website = new Sitemapper({
  url: Deno.env.get("SITEMAP"),
  timeout: 15000,
});

try {
  const { sites } = await Website.fetch();

  const report = [];

  for (const url of sites) {
    try {
      await (await fetch(url)).text();

      report.push(true);
    } catch (error) {
      console.error(error);
    }
  }

  const urls = sites.length;
  const total = report.length;

  console.log(`Total: ${total}/${urls}, skipped: ${urls - total}`);
} catch (error) {
  console.error(error);
}
RodrigoTomeES commented 11 months ago

I think I found the issue, the problem is related with the number of asynchronous functions (650 more or less). In node only about 10-15 calls fails but in Deno almost. I will change the code to launch the fetch in async but with a limit of number of concurrent calls.

Despite all this, I think Deno should handle this better or release a clearer bug about the issue.