Skip to content

Commit 05f558b

Browse files
feat(client): add support for endpoint-specific base URLs
1 parent 9eb4470 commit 05f558b

File tree

5 files changed

+43
-8
lines changed

5 files changed

+43
-8
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
"publint": "^0.2.12",
4646
"ts-jest": "^29.1.0",
4747
"ts-node": "^10.5.0",
48-
"tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.7/tsc-multi.tgz",
48+
"tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz",
4949
"tsconfig-paths": "^4.0.0",
5050
"typescript": "5.8.3",
5151
"ws": "^8.18.0",

src/client.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,13 @@ export class OpenAI {
372372
});
373373
}
374374

375+
/**
376+
* Check whether the base URL is set to its default.
377+
*/
378+
#baseURLOverridden(): boolean {
379+
return this.baseURL !== 'https://api.openai.com/v1';
380+
}
381+
375382
protected defaultQuery(): Record<string, string | undefined> | undefined {
376383
return this._options.defaultQuery;
377384
}
@@ -405,11 +412,16 @@ export class OpenAI {
405412
return Errors.APIError.generate(status, error, message, headers);
406413
}
407414

408-
buildURL(path: string, query: Record<string, unknown> | null | undefined): string {
415+
buildURL(
416+
path: string,
417+
query: Record<string, unknown> | null | undefined,
418+
defaultBaseURL?: string | undefined,
419+
): string {
420+
const baseURL = (!this.#baseURLOverridden() && defaultBaseURL) || this.baseURL;
409421
const url =
410422
isAbsoluteURL(path) ?
411423
new URL(path)
412-
: new URL(this.baseURL + (this.baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path));
424+
: new URL(baseURL + (baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path));
413425

414426
const defaultQuery = this.defaultQuery();
415427
if (!isEmptyObj(defaultQuery)) {
@@ -773,9 +785,9 @@ export class OpenAI {
773785
{ retryCount = 0 }: { retryCount?: number } = {},
774786
): { req: FinalizedRequestInit; url: string; timeout: number } {
775787
const options = { ...inputOptions };
776-
const { method, path, query } = options;
788+
const { method, path, query, defaultBaseURL } = options;
777789

778-
const url = this.buildURL(path!, query as Record<string, unknown>);
790+
const url = this.buildURL(path!, query as Record<string, unknown>, defaultBaseURL);
779791
if ('timeout' in options) validatePositiveInteger('timeout', options.timeout);
780792
options.timeout = options.timeout ?? this.timeout;
781793
const { bodyHeaders, body } = this.buildBody({ options });

src/internal/request-options.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export type RequestOptions = {
2121
fetchOptions?: MergedRequestInit;
2222
signal?: AbortSignal | undefined | null;
2323
idempotencyKey?: string;
24+
defaultBaseURL?: string | undefined;
2425

2526
__metadata?: Record<string, unknown>;
2627
__binaryResponse?: boolean | undefined;

tests/index.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,28 @@ describe('instantiate client', () => {
310310
const client = new OpenAI({ apiKey: 'My API Key' });
311311
expect(client.baseURL).toEqual('https://api.openai.com/v1');
312312
});
313+
314+
test('in request options', () => {
315+
const client = new OpenAI({ apiKey: 'My API Key' });
316+
expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual(
317+
'http://localhost:5000/option/foo',
318+
);
319+
});
320+
321+
test('in request options overridden by client options', () => {
322+
const client = new OpenAI({ apiKey: 'My API Key', baseURL: 'http://localhost:5000/client' });
323+
expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual(
324+
'http://localhost:5000/client/foo',
325+
);
326+
});
327+
328+
test('in request options overridden by env variable', () => {
329+
process.env['OPENAI_BASE_URL'] = 'http://localhost:5000/env';
330+
const client = new OpenAI({ apiKey: 'My API Key' });
331+
expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual(
332+
'http://localhost:5000/env/foo',
333+
);
334+
});
313335
});
314336

315337
test('maxRetries option is correctly set', () => {

yarn.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3302,9 +3302,9 @@ ts-node@^10.5.0:
33023302
v8-compile-cache-lib "^3.0.0"
33033303
yn "3.1.1"
33043304

3305-
"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.7/tsc-multi.tgz":
3306-
version "1.1.7"
3307-
resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.7/tsc-multi.tgz#52f40adf8b808bd0b633346d11cc4a8aeea465cd"
3305+
"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz":
3306+
version "1.1.8"
3307+
resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz#f544b359b8f05e607771ffacc280e58201476b04"
33083308
dependencies:
33093309
debug "^4.3.7"
33103310
fast-glob "^3.3.2"

0 commit comments

Comments
 (0)