Skip to content

Commit 5e4ff51

Browse files
committed
improve validation for supabaseUrl
1 parent 04a1397 commit 5e4ff51

File tree

3 files changed

+39
-4
lines changed

3 files changed

+39
-4
lines changed

src/SupabaseClient.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
DEFAULT_REALTIME_OPTIONS,
2020
} from './lib/constants'
2121
import { fetchWithAuth } from './lib/fetch'
22-
import { ensureTrailingSlash, applySettingDefaults } from './lib/helpers'
22+
import { applySettingDefaults, validateSupabaseUrl } from './lib/helpers'
2323
import { SupabaseAuthClient } from './lib/SupabaseAuthClient'
2424
import { Fetch, GenericSchema, SupabaseClientOptions, SupabaseAuthClientOptions } from './lib/types'
2525

@@ -101,11 +101,9 @@ export default class SupabaseClient<
101101
protected supabaseKey: string,
102102
options?: SupabaseClientOptions<SchemaName>
103103
) {
104-
if (!supabaseUrl) throw new Error('supabaseUrl is required.')
105104
if (!supabaseKey) throw new Error('supabaseKey is required.')
106105

107-
const _supabaseUrl = ensureTrailingSlash(supabaseUrl)
108-
const baseUrl = new URL(_supabaseUrl)
106+
const baseUrl = validateSupabaseUrl(supabaseUrl)
109107

110108
this.realtimeUrl = new URL('realtime/v1', baseUrl)
111109
this.realtimeUrl.protocol = this.realtimeUrl.protocol.replace('http', 'ws')

src/lib/helpers.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,26 @@ export function applySettingDefaults<
7171

7272
return result
7373
}
74+
75+
/**
76+
* Validates a Supabase client URL
77+
*
78+
* @param {string} supabaseUrl - The Supabase client URL string.
79+
* @returns {URL} - The validated base URL.
80+
* @throws {Error}
81+
*/
82+
export function validateSupabaseUrl(supabaseUrl: string): URL {
83+
if (!supabaseUrl) {
84+
throw new Error('supabaseUrl is required.')
85+
}
86+
87+
if (!supabaseUrl.match(/^https?:\/\/.+/i)) {
88+
throw new Error('Invalid supabaseUrl: Must be a valid HTTP or HTTPS URL.')
89+
}
90+
91+
try {
92+
return new URL(ensureTrailingSlash(supabaseUrl))
93+
} catch {
94+
throw Error('Invalid supabaseUrl: Provided URL is malformed.')
95+
}
96+
}

test/unit/SupabaseClient.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,20 @@ describe('SupabaseClient', () => {
2929
expect(() => createClient(URL, '')).toThrow('supabaseKey is required.')
3030
})
3131

32+
test('should validate supabaseUrl', () => {
33+
expect(() => createClient('https://xyz123.supabase.co', KEY)).not.toThrow()
34+
expect(() => createClient('http://localhost:54321', KEY)).not.toThrow()
35+
expect(() => createClient('http://[invalid', KEY)).toThrow(
36+
'Invalid supabaseUrl: Provided URL is malformed.'
37+
)
38+
expect(() =>
39+
createClient('postgresql://postgre:[email protected]:5432/postgres', KEY)
40+
).toThrow('Invalid supabaseUrl: Must be a valid HTTP or HTTPS URL.')
41+
expect(() => createClient('http:/localhost:3000', KEY)).toThrow(
42+
'Invalid supabaseUrl: Must be a valid HTTP or HTTPS URL.'
43+
)
44+
})
45+
3246
describe('URL Construction', () => {
3347
test('should construct URLs correctly', () => {
3448
const client = createClient(URL, KEY)

0 commit comments

Comments
 (0)