feat: updates CLI to use https flag (#814)

* feat: updates CLI to use https flag

* added changeset

* Added yalt to the changeset

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
This commit is contained in:
Chigala
2024-01-12 14:53:43 +01:00
committed by GitHub
parent 5bf125be0d
commit bc61d83764
5 changed files with 68 additions and 8 deletions
+6
View File
@@ -0,0 +1,6 @@
---
"@trigger.dev/cli": patch
"@trigger.dev/yalt": patch
---
updated the dev command to include -https flag
+1
View File
@@ -63,6 +63,7 @@ program
"-t, --tunnel <url>",
"An optional custom tunnel URL. Use only if you already have an open tunnel to your local dev server."
)
.option("-s, --https", "allows enabled https for the tunnel")
.version(getVersion(), "-v, --version", "Display the version number")
.action(async (path, options) => {
try {
+27 -6
View File
@@ -6,11 +6,12 @@ import ora, { Ora } from "ora";
import pRetry, { AbortError } from "p-retry";
import util from "util";
import { z } from "zod";
import https from "https";
import { Framework } from "../frameworks";
import { standardWatchFilePaths, standardWatchIgnoreRegex } from "../frameworks/watchConfig";
import { telemetryClient } from "../telemetry/telemetry";
import { getEnvFilename } from "../utils/env";
import fetch from "../utils/fetchUseProxy";
import fetch, {RequestInit} from "../utils/fetchUseProxy";
import { getTriggerApiDetails } from "../utils/getTriggerApiDetails";
import { JsRuntime, getJsRuntime } from "../utils/jsRuntime";
import { logger } from "../utils/logger";
@@ -35,6 +36,7 @@ export const DevCommandOptionsSchema = z.object({
.url()
.regex(/^(http|https).+/, "only http/https URLs are accepted")
.optional(),
https: z.boolean().default(false).optional(),
});
export type DevCommandOptions = z.infer<typeof DevCommandOptionsSchema>;
@@ -59,6 +61,7 @@ type ResolvedUrl = {
type: "resolved";
hostname: string;
port: number;
https: boolean;
};
type ServerUrl = TunnelUrl | ResolvedUrl;
@@ -349,6 +352,7 @@ async function resolveOptions(
handlerPath: unresolvedOptions.handlerPath,
clientId: unresolvedOptions.clientId,
tunnel: unresolvedOptions.tunnel,
https: unresolvedOptions.https,
};
}
@@ -362,6 +366,7 @@ async function resolveOptions(
handlerPath: unresolvedOptions.handlerPath,
clientId: unresolvedOptions.clientId,
tunnel: unresolvedOptions.tunnel,
https: unresolvedOptions.https,
};
}
@@ -375,10 +380,11 @@ async function verifyEndpoint(
//try each url
for (const serverUrl of serverUrls) {
const protocol = resolvedOptions.https ? "https" : "http";
const url =
serverUrl.type === "tunnel"
? serverUrl.url
: `http://${serverUrl.hostname}:${serverUrl.port}`;
: `${protocol}://${serverUrl.hostname}:${serverUrl.port}`;
const localEndpointHandlerUrl = `${url}${resolvedOptions.handlerPath}`;
const spinner = ora(
@@ -386,14 +392,22 @@ async function verifyEndpoint(
).start();
try {
const response = await fetch(localEndpointHandlerUrl, {
const agent = new https.Agent({
rejectUnauthorized: false, // Ignore self-signed certificates
});
// Conditionally include the agent in fetch options
const fetchOptions: RequestInit = {
method: "POST",
headers: {
"x-trigger-api-key": apiKey,
"x-trigger-action": "PING",
"x-trigger-endpoint-id": endpointId,
},
});
...(resolvedOptions.https && { agent }),
};
const response = await fetch(localEndpointHandlerUrl, fetchOptions);
if (!response.ok || response.status !== 200) {
spinner.fail(
@@ -404,7 +418,11 @@ async function verifyEndpoint(
spinner.succeed(`[trigger.dev] Found your trigger endpoint: ${localEndpointHandlerUrl}`);
return { ...serverUrl, handlerPath: resolvedOptions.handlerPath };
return {
...serverUrl,
handlerPath: resolvedOptions.handlerPath,
https: resolvedOptions.https ?? false,
};
} catch (err) {
spinner.fail(`[trigger.dev] No server found (${localEndpointHandlerUrl}).`);
}
@@ -451,7 +469,7 @@ function findServerUrls(resolvedOptions: ResolvedOptions, framework?: Framework)
const urls: ResolvedUrl[] = [];
for (const hostname of hostnames) {
for (const port of ports) {
urls.push({ type: "resolved", hostname, port });
urls.push({ type: "resolved", hostname, port, https: resolvedOptions.https ?? false });
}
}
@@ -480,6 +498,7 @@ async function resolveEndpointUrl(apiUrl: string, apiKey: string, endpoint: Serv
const tunnelUrl = await createNativeTunnel(
endpoint.hostname,
endpoint.port,
endpoint.https,
triggerApi,
tunnelSpinner
);
@@ -507,6 +526,7 @@ let yaltTunnel: YaltTunnel | null = null;
async function createNativeTunnel(
hostname: string,
port: number,
https: boolean,
triggerApi: TriggerApi,
spinner: Ora
) {
@@ -519,6 +539,7 @@ async function createNativeTunnel(
yaltTunnel = new YaltTunnel(
response.url,
`${hostname}:${port}`,
https,
{
WebSocket: WebSocket.default,
connectionTimeout: 1000,
+3
View File
@@ -31,7 +31,10 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
"https": "^1.0.0",
"node-fetch": "^3.3.2",
"partysocket": "^0.0.17",
"proxy-agent": "^6.3.0",
"zod": "3.22.3"
},
"devDependencies": {
+31 -2
View File
@@ -1,5 +1,12 @@
import { z } from "zod";
import { WebSocket } from "partysocket";
import node_fetch, {
RequestInfo as _RequestInfo,
RequestInit as _RequestInit,
Response,
} from "node-fetch";
import { ProxyAgent } from "proxy-agent";
import https from "https";
export const RequestMesssage = z.object({
type: z.literal("request"),
@@ -8,6 +15,7 @@ export const RequestMesssage = z.object({
method: z.string(),
url: z.string(),
body: z.string(),
https: z.boolean().default(false).optional(),
});
export type RequestMessage = z.infer<typeof RequestMesssage>;
@@ -28,6 +36,9 @@ export const ServerMessages = z.discriminatedUnion("type", [RequestMesssage]);
export type ClientMessage = z.infer<typeof ClientMessages>;
export type ServerMessage = z.infer<typeof ServerMessages>;
export type RequestInfo = _RequestInfo;
export type RequestInit = _RequestInit;
export async function createRequestMessage(id: string, request: Request): Promise<RequestMessage> {
const { headers, method, url } = request;
@@ -76,7 +87,7 @@ export class YaltApiClient {
throw new Error(`Could not create tunnel: ${response.status}`);
}
const body = await response.json();
const body = (await response.json()) as any;
return body.id;
}
@@ -102,6 +113,7 @@ export class YaltTunnel {
constructor(
private url: string,
private address: string,
private https: boolean,
private socketOptions: YaltTunnelSocketOptions = {},
private options: YaltTunnelOptions = {}
) {}
@@ -165,7 +177,9 @@ export class YaltTunnel {
const url = new URL(request.url);
// Construct the original url to be the same as the request URL but with a different hostname and using http instead of https
const originalUrl = new URL(`http://${this.address}${url.pathname}${url.search}${url.hash}`);
const originalUrl = new URL(
`${this.https ? "https" : "http"}://${this.address}${url.pathname}${url.search}${url.hash}`
);
let response: Response | null = null;
@@ -176,10 +190,14 @@ export class YaltTunnel {
});
try {
const agent = new https.Agent({
rejectUnauthorized: false, // Ignore self-signed certificates
});
response = await fetch(originalUrl.href, {
method: request.method,
headers: stripHeaders(request.headers),
body: request.body,
...(this.https && { agent }),
});
} catch (error) {
if (error instanceof Error) {
@@ -234,3 +252,14 @@ function stripHeaders(headers: Record<string, string>) {
Object.entries(headers).filter(([key]) => !blacklistHeaders.includes(key.toLowerCase()))
);
}
function fetch(url: RequestInfo, init?: RequestInit) {
const fetchInit: RequestInit = { ...init };
// If agent is not specified, specify proxy-agent and use environment variables such as HTTPS_PROXY.
if (!fetchInit.agent) {
fetchInit.agent = new ProxyAgent();
}
return node_fetch(url, fetchInit);
}