Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: enable proxy support in the cli #1608

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 43 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"fast-levenshtein": "^3.0.0",
"fs-extra": "^11.1.0",
"generator-v2": "npm:@asyncapi/generator@^2.4.1",
"https-proxy-agent": "^7.0.6",
"inquirer": "^8.2.0",
"js-yaml": "^4.1.0",
"lodash.template": "^4.4.0",
Expand Down Expand Up @@ -172,4 +173,4 @@
"action:test": "cd github-action && make test"
},
"types": "lib/index.d.ts"
}
}
18 changes: 15 additions & 3 deletions src/commands/convert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { SpecificationFileNotFound } from '../core/errors/specification-file';
import { convert, convertOpenAPI, convertPostman } from '@asyncapi/converter';
import type { AsyncAPIConvertVersion, OpenAPIConvertVersion } from '@asyncapi/converter';
import { cyan, green } from 'picocolors';

import { proxyFlags } from '../core/flags/proxy.flags';
// @ts-ignore
import specs from '@asyncapi/specs';
import { convertFlags } from '../core/flags/convert.flags';
Expand All @@ -20,15 +20,27 @@ export default class Convert extends Command {
static metricsMetadata: any = {};
static description = 'Convert asyncapi documents older to newer versions or OpenAPI/postman-collection documents to AsyncAPI';

static flags = convertFlags(latestVersion);
static flags = {
...convertFlags(latestVersion),
...proxyFlags()

};

static args = {
'spec-file': Args.string({description: 'spec path, url, or context-name', required: false}),
proxyHost: Args.string({description: 'Name of the Proxy Host', required: false}),
proxyPort: Args.string({description: 'Name of the Port of the ProxyHost', required: false}),
};

async run() {
const { args, flags } = await this.parse(Convert);
const filePath = args['spec-file'];
let filePath = args['spec-file'];
const proxyHost = flags['proxyHost'];
const proxyPort = flags['proxyPort'];
if (proxyHost && proxyPort) {
const proxyUrl = `http://${proxyHost}:${proxyPort}`;
filePath = `${filePath}+${proxyUrl}`; // Update filePath with proxyUrl
}
let convertedFile;
let convertedFileFormatted;

Expand Down
18 changes: 14 additions & 4 deletions src/commands/optimize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import chalk from 'chalk';
import { promises } from 'fs';
import { Parser } from '@asyncapi/parser';
import { optimizeFlags } from '../core/flags/optimize.flags';

import { proxyFlags } from '../core/flags/proxy.flags';
const { writeFile } = promises;

export enum Optimizations {
Expand Down Expand Up @@ -42,18 +42,28 @@ export default class Optimize extends Command {
'asyncapi optimize ./asyncapi.yaml --ignore=schema'
];

static flags = optimizeFlags();
static flags = {
...optimizeFlags(),
...proxyFlags(),
};

static args = {
'spec-file': Args.string({description: 'spec path, url, or context-name', required: false}),
proxyHost: Args.string({description: 'Name of the Proxy Host', required: false}),
proxyPort: Args.string({description: 'Name of the Port of the ProxyHost', required: false}),
};

parser = new Parser();

async run() {
const { args, flags } = await this.parse(Optimize); //NOSONAR
const filePath = args['spec-file'];

let filePath = args['spec-file'];
const proxyHost = flags['proxyHost'];
const proxyPort = flags['proxyPort'];
if (proxyHost && proxyPort) {
const proxyUrl = `http://${proxyHost}:${proxyPort}`;
filePath = `${filePath}+${proxyUrl}`; // Update filePath with proxyUrl
}
try {
this.specFile = await load(filePath);
} catch (err) {
Expand Down
21 changes: 15 additions & 6 deletions src/commands/validate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,41 @@ import { validate, ValidateOptions, ValidationStatus, parse } from '../core/pars
import { load } from '../core/models/SpecificationFile';
import { specWatcher } from '../core/globals';
import { validateFlags } from '../core/flags/validate.flags';
import { proxyFlags } from '../core/flags/proxy.flags';
import { calculateScore } from '../core/utils/scoreCalculator';

export default class Validate extends Command {
static description = 'validate asyncapi file';

static flags = validateFlags();
static flags = {
...validateFlags(),
...proxyFlags(), // Merge proxyFlags with validateFlags
};

static args = {
'spec-file': Args.string({description: 'spec path, url, or context-name', required: false}),
proxyHost: Args.string({description: 'Name of the Proxy Host', required: false}),
proxyPort: Args.string({description: 'Name of the Port of the ProxyHost', required: false}),
};

async run() {
const { args, flags } = await this.parse(Validate); //NOSONAR

const filePath = args['spec-file'];
let filePath = args['spec-file'];
const proxyHost = flags['proxyHost'];
const proxyPort = flags['proxyPort'];
if (proxyHost && proxyPort) {
const proxyUrl = `http://${proxyHost}:${proxyPort}`;
filePath = `${filePath}+${proxyUrl}`; // Update filePath with proxyUrl
}
this.specFile = await load(filePath);
const watchMode = flags.watch;
if (flags['score']) {
this.specFile = await load(filePath);
const { document } = await parse(this,this.specFile);
this.log(`The score of the asyncapi document is ${await calculateScore(document)}`);
}
this.specFile = await load(filePath);
if (watchMode) {
specWatcher({ spec: this.specFile, handler: this, handlerName: 'validate' });
}

const result = await validate(this, this.specFile, flags as ValidateOptions);
this.metricsMetadata.validation_result = result;

Expand Down
15 changes: 15 additions & 0 deletions src/core/flags/proxy.flags.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Flags } from '@oclif/core';

export const proxyFlags = () => {
return {
proxyHost: Flags.string({
description: 'Name of the ProxyHost',
required: false
}),
proxyPort: Flags.string({
description: 'Port number number for the proxyHost.',
required: false
})
};
};

37 changes: 32 additions & 5 deletions src/core/models/SpecificationFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { loadContext } from './Context';
import { ErrorLoadingSpec } from '../errors/specification-file';
import { MissingContextFileError } from '../errors/context-error';
import { fileFormat } from 'core/flags/format.flags';

import { HttpsProxyAgent } from 'https-proxy-agent';
const { readFile, lstat } = fs;
const allowedFileNames: string[] = [
'asyncapi.json',
Expand Down Expand Up @@ -87,15 +87,42 @@ export class Specification {

static async fromURL(URLpath: string) {
let response;
const delimiter = '+';
let targetUrl = URLpath;
let proxyUrl = '';

// Check if URLpath contains a proxy URL
if (URLpath.includes(delimiter)) {
[targetUrl, proxyUrl] = URLpath.split(delimiter);
}

try {
response = await fetch(URLpath, { method: 'GET' });
// Validate the target URL
new URL(targetUrl);

const fetchOptions: any = { method: 'GET' };

// If proxy URL is provided, create a proxy agent
if (proxyUrl) {
try {
new URL(proxyUrl);
const proxyAgent = new HttpsProxyAgent(proxyUrl,);
fetchOptions.agent = proxyAgent;
} catch (error) {
throw new Error(`Invalid proxy URL: ${proxyUrl}`);
}
}

// Fetch the target URL
response = await fetch(targetUrl, fetchOptions);
if (!response.ok) {
throw new ErrorLoadingSpec('url', URLpath);
throw new ErrorLoadingSpec('url', targetUrl);
}
} catch (error) {
throw new ErrorLoadingSpec('url', URLpath);
throw new ErrorLoadingSpec('url', targetUrl);
}
return new Specification(await response?.text() as string, { fileURL: URLpath });

return new Specification(await response?.text() as string, { fileURL: targetUrl });
}
}

Expand Down
Loading