Skip to content

Commit fd31159

Browse files
authored
Tolerate specref API failures during local dev (#4167)
Since #4124 was merged, all builds require an HTTP request to api.specref.org in order to resolve additional bibliographical references. This may cause issues in local dev in the case of being offline due to travel or internet hiccups, behind a proxy, etc. This commit adds a reusable function for cases where a HTTP failure during local dev is tolerable, and uses it for the bibrefs request. Running `npm build` will still result in an immediate failure and stack trace; this is intentional to ensure that nothing slips by during builds for PR previews, GitHub Pages, or w3.org.
1 parent 079df5e commit fd31159

File tree

2 files changed

+31
-5
lines changed

2 files changed

+31
-5
lines changed

11ty/biblio.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { readFile } from "fs/promises";
33
import { glob } from "glob";
44
import uniq from "lodash-es/uniq";
55

6+
import { wrapAxiosRequest } from "./common";
7+
68
export const biblioPattern = /\[\[\??([\w-]+)\]\]/g;
79

810
/** Compiles URLs from local biblio + specref for linking in Understanding documents. */
@@ -12,24 +14,26 @@ export async function getBiblio() {
1214
.replace(/^respecConfig\.localBiblio\s*=\s*/, "(")
1315
.replace("};", "})")
1416
);
15-
17+
1618
const refs: string[] = [];
1719
for (const path of await glob(["guidelines/**/*.html", "understanding/*/*.html"])) {
1820
const content = await readFile(path, "utf8");
1921
let match;
2022
while ((match = biblioPattern.exec(content))) if (!localBiblio[match[1]]) refs.push(match[1]);
2123
}
2224
const uniqueRefs = uniq(refs);
23-
24-
const response = await axios.get(`https://api.specref.org/bibrefs?refs=${uniqueRefs.join(",")}`);
25+
26+
const response = await wrapAxiosRequest(
27+
axios.get(`https://api.specref.org/bibrefs?refs=${uniqueRefs.join(",")}`)
28+
);
2529
const fullBiblio = {
2630
...response.data,
2731
...localBiblio,
2832
};
29-
33+
3034
const resolvedRefs = Object.keys(fullBiblio);
3135
const unresolvedRefs = uniqueRefs.filter((ref) => !resolvedRefs.includes(ref));
3236
if (unresolvedRefs.length) console.warn(`Unresolved biblio refs: ${unresolvedRefs.join(", ")}`);
33-
37+
3438
return fullBiblio;
3539
}

11ty/common.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
/** @fileoverview Common functions used by multiple parts of the build process */
22

3+
import { AxiosError, type AxiosResponse } from "axios";
4+
35
import type { Guideline, Principle, SuccessCriterion } from "./guidelines";
46

57
/** Generates an ID for heading permalinks. Equivalent to wcag:generate-id in base.xslt. */
@@ -28,3 +30,23 @@ export function wcagSort(
2830
}
2931
return 0;
3032
}
33+
34+
/**
35+
* Handles HTTP error responses from Axios requests in local dev;
36+
* re-throws error during builds to fail loudly.
37+
* This should only be used for non-critical requests that can tolerate null data
38+
* without major side effects.
39+
*/
40+
export const wrapAxiosRequest = <T, D>(promise: Promise<AxiosResponse<T, D>>) =>
41+
promise.catch((error) => {
42+
if (!(error instanceof AxiosError) || !error.response || !error.request) throw error;
43+
const { response, request } = error;
44+
console.warn(
45+
`AxiosError: status ${response.status} received from ${
46+
request.protocol + "//" + request.host
47+
}${request.path || ""}`
48+
);
49+
50+
if (process.env.ELEVENTY_RUN_MODE === "build") throw error;
51+
else return { data: null };
52+
});

0 commit comments

Comments
 (0)