Skip to content

Commit

Permalink
fix: edge function should not operate if not targeting definition fil…
Browse files Browse the repository at this point in the history
…es (#2543)
  • Loading branch information
smoya authored Jan 9, 2024
1 parent d4ff322 commit cca81f7
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 12 deletions.
27 changes: 26 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,32 @@ All AsyncAPI JSON Schema definition files are being served within the `/definiti
This is possible thanks to the following:
1. A [Netlify Rewrite rule](https://docs.netlify.com/routing/redirects/rewrites-proxies/) located in the [netlify.toml](netlify.toml) file, which acts as proxy for all requests to the `/definitions/<file>` path, serving the content from GH without having an HTTP redirect.
2. A [Netlify Edge Function](https://docs.netlify.com/netlify-labs/experimental-features/edge-functions/) that modifies the `Content-Type` header of the rewrite response to become `application/schema+json`. This lets tooling, such as [Hyperjump](https://json-schema.hyperjump.io), to fetch the schemas directly from their URL.
2. A [Netlify Edge Function](https://docs.netlify.com/netlify-labs/experimental-features/edge-functions/) that modifies the `Content-Type` header of the rewrite response to become `application/schema+json`. This lets tooling, such as [Hyperjump](https://json-schema.hyperjump.io), to fetch the schemas directly from their URL.
Please find a flowchart explaining the flow this edge function should accomplish:
```mermaid
flowchart TD
Request(Request) -->schema-related{Is it requesting Schemas?}
schema-related -->|No| req_no_schemas[Let the original request go through]
req_no_schemas --> Response(Response)
schema-related -->|Yes| req_schemas[Fetch from GitHub]
req_schemas-->req_json{Was requesting a .json file?}
req_json -->|No| Response(Response)
req_json -->|Yes| response_status{Response Status?}
response_status -->|2xx| response_ok[OK]
response_status -->|304| response_cached[Not Modified]
response_status -->|Any other| response_ko
response_ok --> set_headers[Set Response Content-Type header to application/schema+json]
set_headers --> send_metric_success[Send success metric]
response_cached -- cached:true --> send_metric_success
response_ko --> send_metric_error[Send error metric]
send_metric_success -- file served from raw GH --> Response(Response)
send_metric_error --the errored response --> Response(Response)
```
## Project structure
Expand Down
22 changes: 11 additions & 11 deletions netlify/edge-functions/serve-definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,27 @@ const NR_METRICS_ENDPOINT = Deno.env.get("NR_METRICS_ENDPOINT") || "https://metr
const URL_DEST_SCHEMAS = "https://raw.githubusercontent.com/asyncapi/spec-json-schemas/master/schemas";
const URL_DEST_DEFINITIONS = "https://raw.githubusercontent.com/asyncapi/spec-json-schemas/master/definitions";

// Legitimate request:
// Schemas-related request:
// Patterns: /<source> OR /<source>/<file> OR /<source>/<version>/<file>
// Examples: /definitions OR /schema-store/2.5.0-without-$id.json OR /definitions/2.4.0/info.json
// Non-legitimate request:
// Schemas-unrelated request:
// Patterns: /<source>/<randompath>/*
// Examples: /definitions/asyncapi.yaml OR /schema-store/2.4.0.JSON (uppercase)
//
// Non-legitimate requests should not use our GitHub Token and affect the rate limit. Those shouldn't send metrics to NR either as they just add noise.
const legitimateRequestRegex = /^\/[\w\-]*\/?(?:([\w\-\.]*\/)?([\w\-$%\.]*\.json))?$/
// Schemas-unrelated requests should not use our GitHub Token and affect the rate limit. Those shouldn't send metrics to NR either as they just add noise.
const SchemasRelatedRequestRegex = /^\/[\w\-]*\/?(?:([\w\-\.]*\/)?([\w\-$%\.]*\.json))?$/

export default async (request: Request, context: Context) => {
let rewriteRequest = buildRewrite(request);
let response: Response;
if (rewriteRequest === null) {
rewriteRequest = request;

response = await context.next();
} else {
// Fetching the definition file
response = await fetch(rewriteRequest);
// This is a Schema-unrelated request. Let it go through and do not intercept it.
return await context.next();
}

// Fetching the definition file
response = await fetch(rewriteRequest);

const isRequestingAFile = request.url.endsWith('.json');
if (isRequestingAFile) {
var metricName: string
Expand Down Expand Up @@ -56,6 +55,7 @@ export default async (request: Request, context: Context) => {
default:
// Notifying NR of the error.
metricName = "asyncapi.jsonschema.download.error";
console.log("Error downloading JSON Schema file: " + response.status + " " + response.statusText);
break;
}
}
Expand All @@ -68,7 +68,7 @@ export default async (request: Request, context: Context) => {
};

function buildRewrite(originalRequest: Request): (Request | null) {
const extractResult = legitimateRequestRegex.exec(new URL(originalRequest.url).pathname);
const extractResult = SchemasRelatedRequestRegex.exec(new URL(originalRequest.url).pathname);
if (extractResult === null) {
return null;
}
Expand Down

0 comments on commit cca81f7

Please sign in to comment.