Skip to content

Commit

Permalink
fix: replace throw on missing env with warning
Browse files Browse the repository at this point in the history
  • Loading branch information
CahidArda committed Oct 8, 2024
1 parent 45ed724 commit 6ab0fb8
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 39 deletions.
2 changes: 1 addition & 1 deletion pkg/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export class UpstashError extends Error {
export class UrlError extends Error {
constructor(url: string) {
super(
`Upstash Redis client was passed an invalid URL. You should pass the URL together with https. Received: "${url}". `
`Upstash Redis client was passed an invalid URL. You should pass a URL starting with https. Received: "${url}". `
);
this.name = "UrlError";
}
Expand Down
12 changes: 11 additions & 1 deletion pkg/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ export class HttpClient implements Requester {
};
public readYourWrites: boolean;
public upstashSyncToken = "";
private hasCredentials: boolean;

public readonly retry: {
attempts: number;
Expand Down Expand Up @@ -157,7 +158,7 @@ export class HttpClient implements Requester {
* - `$` asserts the position at the end of the string.
*/
const urlRegex = /^https?:\/\/[^\s#$./?].\S*$/;
if (!urlRegex.test(this.baseUrl)) {
if (this.baseUrl && !urlRegex.test(this.baseUrl)) {
throw new UrlError(this.baseUrl);
}

Expand All @@ -167,6 +168,8 @@ export class HttpClient implements Requester {
...config.headers,
};

this.hasCredentials = Boolean(this.baseUrl && this.headers.authorization.split(" ")[1]);

if (this.options.responseEncoding === "base64") {
this.headers["Upstash-Encoding"] = "base64";
}
Expand Down Expand Up @@ -206,6 +209,13 @@ export class HttpClient implements Requester {
backend: this.options.backend,
};

if (!this.hasCredentials) {
throw new Error(
"[Upstash Redis] Redis client was initialized without url or token." +
" Failed to execute command."
);
}

/**
* We've recieved a new `upstash-sync-token` in the previous response. We use it in the next request to observe the effects of previous requests.
*/
Expand Down
31 changes: 19 additions & 12 deletions platforms/cloudflare.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import type { RequesterConfig } from "../pkg/http";
import { HttpClient } from "../pkg/http";
import * as core from "../pkg/redis";
Expand Down Expand Up @@ -56,27 +55,35 @@ export class Redis extends core.Redis {
*/
constructor(config: RedisConfigCloudflare, env?: Env) {
if (!config.url) {
throw new Error(
console.warn(
`[Upstash Redis] The 'url' property is missing or undefined in your Redis config.`
);
}

if (!config.token) {
throw new Error(
console.warn(
`[Upstash Redis] The 'token' property is missing or undefined in your Redis config.`
);
}

if (config.url.startsWith(" ") || config.url.endsWith(" ") || /\r|\n/.test(config.url)) {
console.warn("The redis url contains whitespace or newline, which can cause errors!");
if (config.url!.startsWith(" ") || config.url!.endsWith(" ") || /\r|\n/.test(config.url!)) {
console.warn(
"[Upstash Redis] The redis url contains whitespace or newline, which can cause errors!"
);
}
if (config.token.startsWith(" ") || config.token.endsWith(" ") || /\r|\n/.test(config.token)) {
console.warn("The redis token contains whitespace or newline, which can cause errors!");
if (
config.token!.startsWith(" ") ||
config.token!.endsWith(" ") ||
/\r|\n/.test(config.token!)
) {
console.warn(
"[Upstash Redis] The redis token contains whitespace or newline, which can cause errors!"
);
}

const client = new HttpClient({
retry: config.retry,
baseUrl: config.url,
baseUrl: config.url!,
headers: { authorization: `Bearer ${config.token}` },
responseEncoding: config.responseEncoding,
signal: config.signal,
Expand Down Expand Up @@ -127,13 +134,13 @@ export class Redis extends core.Redis {
const token = env?.UPSTASH_REDIS_REST_TOKEN ?? UPSTASH_REDIS_REST_TOKEN;

if (!url) {
throw new Error(
"Unable to find environment variable: `UPSTASH_REDIS_REST_URL`. Please add it via `wrangler secret put UPSTASH_REDIS_REST_URL`"
console.warn(
"[Upstash Redis] Unable to find environment variable: `UPSTASH_REDIS_REST_URL`. Please add it via `wrangler secret put UPSTASH_REDIS_REST_URL`"
);
}
if (!token) {
throw new Error(
"Unable to find environment variable: `UPSTASH_REDIS_REST_TOKEN`. Please add it via `wrangler secret put UPSTASH_REDIS_REST_TOKEN`"
console.warn(
"[Upstash Redis] Unable to find environment variable: `UPSTASH_REDIS_REST_TOKEN`. Please add it via `wrangler secret put UPSTASH_REDIS_REST_TOKEN`"
);
}
return new Redis({ ...opts, url, token }, env);
Expand Down
22 changes: 15 additions & 7 deletions platforms/fastly.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,26 +53,34 @@ export class Redis extends core.Redis {
*/
constructor(config: RedisConfigFastly) {
if (!config.url) {
throw new Error(
console.warn(
`[Upstash Redis] The 'url' property is missing or undefined in your Redis config.`
);
}

if (!config.token) {
throw new Error(
console.warn(
`[Upstash Redis] The 'token' property is missing or undefined in your Redis config.`
);
}

if (config.url.startsWith(" ") || config.url.endsWith(" ") || /\r|\n/.test(config.url)) {
console.warn("The redis url contains whitespace or newline, which can cause errors!");
if (config.url!.startsWith(" ") || config.url!.endsWith(" ") || /\r|\n/.test(config.url!)) {
console.warn(
"[Upstash Redis] The redis url contains whitespace or newline, which can cause errors!"
);
}
if (config.token.startsWith(" ") || config.token.endsWith(" ") || /\r|\n/.test(config.token)) {
console.warn("The redis token contains whitespace or newline, which can cause errors!");
if (
config.token!.startsWith(" ") ||
config.token!.endsWith(" ") ||
/\r|\n/.test(config.token!)
) {
console.warn(
"[Upstash Redis] The redis token contains whitespace or newline, which can cause errors!"
);
}

const client = new HttpClient({
baseUrl: config.url,
baseUrl: config.url!,
retry: config.retry,
headers: { authorization: `Bearer ${config.token}` },
options: { backend: config.backend },
Expand Down
40 changes: 22 additions & 18 deletions platforms/nodejs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,37 +102,41 @@ export class Redis extends core.Redis {
}

if (!configOrRequester.url) {
throw new Error(
console.warn(
`[Upstash Redis] The 'url' property is missing or undefined in your Redis config.`
);
}

if (!configOrRequester.token) {
throw new Error(
console.warn(
`[Upstash Redis] The 'token' property is missing or undefined in your Redis config.`
);
}

if (
configOrRequester.url.startsWith(" ") ||
configOrRequester.url.endsWith(" ") ||
/\r|\n/.test(configOrRequester.url)
configOrRequester.url!.startsWith(" ") ||
configOrRequester.url!.endsWith(" ") ||
/\r|\n/.test(configOrRequester.url!)
) {
console.warn("The redis url contains whitespace or newline, which can cause errors!");
console.warn(
"[Upstash Redis] The redis url contains whitespace or newline, which can cause errors!"
);
}
if (
configOrRequester.token.startsWith(" ") ||
configOrRequester.token.endsWith(" ") ||
/\r|\n/.test(configOrRequester.token)
configOrRequester.token!.startsWith(" ") ||
configOrRequester.token!.endsWith(" ") ||
/\r|\n/.test(configOrRequester.token!)
) {
console.warn("The redis token contains whitespace or newline, which can cause errors!");
console.warn(
"[Upstash Redis] The redis token contains whitespace or newline, which can cause errors!"
);
}

const client = new HttpClient({
baseUrl: configOrRequester.url,
baseUrl: configOrRequester.url!,
retry: configOrRequester.retry,
headers: { authorization: `Bearer ${configOrRequester.token}` },
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment

agent: configOrRequester.agent,
responseEncoding: configOrRequester.responseEncoding,
cache: configOrRequester.cache ?? "no-store",
Expand Down Expand Up @@ -172,21 +176,21 @@ export class Redis extends core.Redis {
*/
static fromEnv(config?: Omit<RedisConfigNodejs, "url" | "token">): Redis {
// @ts-ignore process will be defined in node
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition

if (process.env === undefined) {
throw new TypeError(
'Unable to get environment variables, `process.env` is undefined. If you are deploying to cloudflare, please import from "@upstash/redis/cloudflare" instead'
'[Upstash Redis] Unable to get environment variables, `process.env` is undefined. If you are deploying to cloudflare, please import from "@upstash/redis/cloudflare" instead'
);
}
// @ts-ignore process will be defined in node
const url = process.env.UPSTASH_REDIS_REST_URL;
if (!url) {
throw new Error("Unable to find environment variable: `UPSTASH_REDIS_REST_URL`");
console.warn("[Upstash Redis] Unable to find environment variable: `UPSTASH_REDIS_REST_URL`");
}
// @ts-ignore process will be defined in node
const token = process.env.UPSTASH_REDIS_REST_TOKEN;
if (!token) {
throw new Error("Unable to find environment variable: `UPSTASH_REDIS_REST_TOKEN`");
console.warn(
"[Upstash Redis] Unable to find environment variable: `UPSTASH_REDIS_REST_TOKEN`"
);
}
return new Redis({ ...config, url, token });
}
Expand Down
36 changes: 36 additions & 0 deletions platforms/platform.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { describe, expect, test } from "bun:test";
import { Redis as NodeRedis } from "./nodejs";
import { Redis as CloudflareRedis } from "./cloudflare";
import { Redis as FastlyRedis } from "./fastly";

describe("should allow creating a client without credentials but fail when requesting", () => {
test("nodejs", () => {
const redis = new NodeRedis({ url: undefined, token: undefined });

const throws = redis.get("foo");
expect(throws).toThrow(
"[Upstash Redis] Redis client was initialized without url or token." +
" Failed to execute command."
);
});

test("cloudflare", () => {
const redis = new CloudflareRedis({ url: undefined, token: undefined });

const throws = redis.get("foo");
expect(throws).toThrow(
"[Upstash Redis] Redis client was initialized without url or token." +
" Failed to execute command."
);
});

test("fastly", () => {
const redis = new FastlyRedis({ url: undefined, token: undefined, backend: "upstash-db" });

const throws = redis.get("foo");
expect(throws).toThrow(
"[Upstash Redis] Redis client was initialized without url or token." +
" Failed to execute command."
);
});
});

0 comments on commit 6ab0fb8

Please sign in to comment.