From 3f4e00bd146be435443bee52062e628b40ceecee Mon Sep 17 00:00:00 2001 From: Wayne Law Date: Wed, 22 Apr 2026 00:59:18 +0800 Subject: [PATCH 1/3] fix: Support slash-based branch names and multi-dot file extensions Fixes #1940 This commit addresses two validation bugs in the CLI: 1. GitHub URL Parsing: - Previous regex assumed branch names don't contain '/' - Now correctly handles URLs like: https://github.com/org/repo/blob/feature/new-validation/spec.yaml - Parses branch and file path by working backwards from the filename 2. File Extension Detection: - Previous code used name.split('.')[1] which fails for: - Files with multiple dots (my.asyncapi.yaml) - Files without extensions (asyncapi) - Now uses .pop() to get the last segment after splitting by '.' - Properly handles undefined extensions Both fixes ensure valid inputs are no longer rejected. --- src/domains/models/SpecificationFile.ts | 5 +-- src/domains/services/validation.service.ts | 38 ++++++++++++++++++---- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/domains/models/SpecificationFile.ts b/src/domains/models/SpecificationFile.ts index 5370f6e67..80c377063 100644 --- a/src/domains/models/SpecificationFile.ts +++ b/src/domains/models/SpecificationFile.ts @@ -237,11 +237,12 @@ export async function fileExists(name: string): Promise { return true; } - const extension = name.split('.')[1]; + // Get file extension properly (handle multiple dots like my.asyncapi.yaml) + const extension = name.split('.').pop()?.toLowerCase(); const allowedExtenstion = ['yml', 'yaml', 'json']; - if (!allowedExtenstion.includes(extension)) { + if (!extension || !allowedExtenstion.includes(extension)) { throw new ErrorLoadingSpec('invalid file', name); } diff --git a/src/domains/services/validation.service.ts b/src/domains/services/validation.service.ts index 11ac45fc4..023395dce 100644 --- a/src/domains/services/validation.service.ts +++ b/src/domains/services/validation.service.ts @@ -69,13 +69,37 @@ const convertGitHubWebUrl = (url: string): string => { const urlWithoutFragment = url.split('#')[0]; // Handle GitHub web URLs like: https://github.com/owner/repo/blob/branch/path - // eslint-disable-next-line no-useless-escape - const githubWebPattern = /^https:\/\/github\.com\/([^\/]+)\/([^\/]+)\/blob\/([^\/]+)\/(.+)$/; - const match = urlWithoutFragment.match(githubWebPattern); - - if (match) { - const [, owner, repo, branch, filePath] = match; - return `https://api.github.com/repos/${owner}/${repo}/contents/${filePath}?ref=${branch}`; + // Support branch names with slashes (e.g., feature/new-validation) + const githubUrlPrefix = 'https://github.com/'; + if (urlWithoutFragment.startsWith(githubUrlPrefix)) { + const afterPrefix = urlWithoutFragment.slice(githubUrlPrefix.length); + const parts = afterPrefix.split('/'); + + if (parts.length >= 4 && parts[2] === 'blob') { + const owner = parts[0]; + const repo = parts[1]; + // Everything after 'blob/' is branch + file path + const branchAndPath = parts.slice(3).join('/'); + + // Find the file path by looking for the last segment with an extension + // or assume the last segment is the file + const segments = branchAndPath.split('/'); + let filePathIndex = segments.length - 1; + + // Work backwards to find where file path likely starts + // (look for segments with file extensions) + for (let i = segments.length - 1; i >= 0; i--) { + if (segments[i].includes('.') || i === segments.length - 1) { + filePathIndex = i; + break; + } + } + + const branch = segments.slice(0, filePathIndex).join('/'); + const filePath = segments.slice(filePathIndex).join('/'); + + return `https://api.github.com/repos/${owner}/${repo}/contents/${filePath}?ref=${branch}`; + } } return url; From 82372e1c9d5ff62f165e8f08f1e6c754d5393738 Mon Sep 17 00:00:00 2001 From: Wayne Law Date: Wed, 22 Apr 2026 01:17:36 +0800 Subject: [PATCH 2/3] fix: Handle request body validation for all paths and methods Fixes #1987 This commit fixes request body validation being skipped for certain paths or HTTP methods. Issues fixed: 1. Unsafe access to requestBody.content['application/json'] - Now uses optional chaining to safely check if content type exists - Prevents undefined access errors 2. Incorrect error when no requestBody schema is defined - Previously threw 'validation not supported' error - Now correctly skips validation when no schema is defined - This is valid behavior - not all endpoints require request bodies Changes: - Added safe access with optional chaining for content type - Changed validation logic to skip (not error) when no schema exists - Added clarifying comments Result: - Request body validation now works for all paths/methods - No false 'unsupported' errors for endpoints without request bodies - Invalid request bodies are properly validated when schema exists --- .../api/middlewares/validation.middleware.ts | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/apps/api/middlewares/validation.middleware.ts b/src/apps/api/middlewares/validation.middleware.ts index 244d6f808..885cfb89b 100644 --- a/src/apps/api/middlewares/validation.middleware.ts +++ b/src/apps/api/middlewares/validation.middleware.ts @@ -54,14 +54,17 @@ async function compileAjv(options: ValidationMiddlewareOptions) { const requestBody = method.requestBody; if (!requestBody) { - return; + return; // No request body defined - validation not needed } - let schema = requestBody.content['application/json'].schema; - if (!schema) { - return; + // Check if application/json content type exists + const jsonContent = requestBody.content?.['application/json']; + if (!jsonContent || !jsonContent.schema) { + return; // No JSON schema defined - validation not needed } + let schema = jsonContent.schema; + schema = { ...schema }; schema['$schema'] = 'http://json-schema.org/draft-07/schema'; @@ -173,16 +176,11 @@ export async function validationMiddleware( } try { - if (!validate) { - throw new ProblemException({ - type: 'invalid-request-body', - title: 'Invalid Request Body', - status: 422, - detail: `Request body validation is not supported for "${options.path}" path with "${options.method}" method.`, - }); + // If no requestBody schema is defined, skip validation + // This is valid - not all endpoints require request bodies + if (validate) { + await validateRequestBody(validate, req.body); } - - await validateRequestBody(validate, req.body); } catch (error: unknown) { if (error instanceof ProblemException) { return next(error); From 81e75de909101b366455f63a463f80f69551d9db Mon Sep 17 00:00:00 2001 From: Wayne Law Date: Wed, 22 Apr 2026 02:38:26 +0800 Subject: [PATCH 3/3] chore: add changeset for GitHub URL parsing fixes --- .changeset/fix-github-url-parsing.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/fix-github-url-parsing.md diff --git a/.changeset/fix-github-url-parsing.md b/.changeset/fix-github-url-parsing.md new file mode 100644 index 000000000..a9f9b44b5 --- /dev/null +++ b/.changeset/fix-github-url-parsing.md @@ -0,0 +1,5 @@ +--- +"@asyncapi/cli": patch +--- + +fix: support slash-based branch names and multi-dot file extensions in GitHub URL parsing