Skip to content
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
7 changes: 7 additions & 0 deletions .changeset/fix-client-next-interceptor-order.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@hey-api/openapi-ts": patch
---

Fix `@hey-api/client-next` request interceptors so URL mutations are reflected in the final request URL.

Previously, the client built the URL before request interceptors ran, so interceptor changes to `baseUrl`, `url`, `path`, or `query` were ignored by the fetch call.
15 changes: 11 additions & 4 deletions examples/openapi-ts-next/src/client/client/client.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,8 @@ export const createClient = (config: Config = {}): Client => {
}

const resolvedOpts = opts as typeof opts & ResolvedRequestOptions<ThrowOnError, Url>;
const url = buildUrl(resolvedOpts);

return { opts: resolvedOpts, url };
return { opts: resolvedOpts };
};

// @ts-expect-error
Expand All @@ -79,14 +78,18 @@ export const createClient = (config: Config = {}): Client => {
let response: Response | undefined;

try {
const { opts, url } = await beforeRequest(options);
const { opts } = await beforeRequest(options);

for (const fn of interceptors.request.fns) {
if (fn) {
await fn(opts);
}
}

// Build the URL after request interceptors have run so any mutations to
// `opts.baseUrl`, `opts.url`, `opts.path`, or `opts.query` are honored.
const url = buildUrl(opts);

// fetch must be assigned here, otherwise it would throw the error:
// TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
const _fetch = opts.fetch!;
Expand Down Expand Up @@ -212,7 +215,11 @@ export const createClient = (config: Config = {}): Client => {
request({ ...options, method });

const makeSseFn = (method: Uppercase<HttpMethod>) => async (options: RequestOptions) => {
const { opts, url } = await beforeRequest(options);
const { opts } = await beforeRequest(options);
// The SSE path applies request interceptors again inside `onRequest`
// (see below), so the URL we seed `createSseClient` with is only the
// initial value; any per-request URL mutation happens there.
const url = buildUrl(opts);
return createSseClient({
...opts,
body: opts.body as BodyInit | null | undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,8 @@ export const createClient = (config: Config = {}): Client => {
}

const resolvedOpts = opts as typeof opts & ResolvedRequestOptions<ThrowOnError, Url>;
const url = buildUrl(resolvedOpts);

return { opts: resolvedOpts, url };
return { opts: resolvedOpts };
};

// @ts-expect-error
Expand All @@ -79,14 +78,18 @@ export const createClient = (config: Config = {}): Client => {
let response: Response | undefined;

try {
const { opts, url } = await beforeRequest(options);
const { opts } = await beforeRequest(options);

for (const fn of interceptors.request.fns) {
if (fn) {
await fn(opts);
}
}

// Build the URL after request interceptors have run so any mutations to
// `opts.baseUrl`, `opts.url`, `opts.path`, or `opts.query` are honored.
const url = buildUrl(opts);

// fetch must be assigned here, otherwise it would throw the error:
// TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
const _fetch = opts.fetch!;
Expand Down Expand Up @@ -212,7 +215,11 @@ export const createClient = (config: Config = {}): Client => {
request({ ...options, method });

const makeSseFn = (method: Uppercase<HttpMethod>) => async (options: RequestOptions) => {
const { opts, url } = await beforeRequest(options);
const { opts } = await beforeRequest(options);
// The SSE path applies request interceptors again inside `onRequest`
// (see below), so the URL we seed `createSseClient` with is only the
// initial value; any per-request URL mutation happens there.
const url = buildUrl(opts);
return createSseClient({
...opts,
body: opts.body as BodyInit | null | undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,8 @@ export const createClient = (config: Config = {}): Client => {
}

const resolvedOpts = opts as typeof opts & ResolvedRequestOptions<ThrowOnError, Url>;
const url = buildUrl(resolvedOpts);

return { opts: resolvedOpts, url };
return { opts: resolvedOpts };
};

// @ts-expect-error
Expand All @@ -79,14 +78,18 @@ export const createClient = (config: Config = {}): Client => {
let response: Response | undefined;

try {
const { opts, url } = await beforeRequest(options);
const { opts } = await beforeRequest(options);

for (const fn of interceptors.request.fns) {
if (fn) {
await fn(opts);
}
}

// Build the URL after request interceptors have run so any mutations to
// `opts.baseUrl`, `opts.url`, `opts.path`, or `opts.query` are honored.
const url = buildUrl(opts);

// fetch must be assigned here, otherwise it would throw the error:
// TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
const _fetch = opts.fetch!;
Expand Down Expand Up @@ -212,7 +215,11 @@ export const createClient = (config: Config = {}): Client => {
request({ ...options, method });

const makeSseFn = (method: Uppercase<HttpMethod>) => async (options: RequestOptions) => {
const { opts, url } = await beforeRequest(options);
const { opts } = await beforeRequest(options);
// The SSE path applies request interceptors again inside `onRequest`
// (see below), so the URL we seed `createSseClient` with is only the
// initial value; any per-request URL mutation happens there.
const url = buildUrl(opts);
return createSseClient({
...opts,
body: opts.body as BodyInit | null | undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,8 @@ export const createClient = (config: Config = {}): Client => {
}

const resolvedOpts = opts as typeof opts & ResolvedRequestOptions<ThrowOnError, Url>;
const url = buildUrl(resolvedOpts);

return { opts: resolvedOpts, url };
return { opts: resolvedOpts };
};

// @ts-expect-error
Expand All @@ -79,14 +78,18 @@ export const createClient = (config: Config = {}): Client => {
let response: Response | undefined;

try {
const { opts, url } = await beforeRequest(options);
const { opts } = await beforeRequest(options);

for (const fn of interceptors.request.fns) {
if (fn) {
await fn(opts);
}
}

// Build the URL after request interceptors have run so any mutations to
// `opts.baseUrl`, `opts.url`, `opts.path`, or `opts.query` are honored.
const url = buildUrl(opts);

// fetch must be assigned here, otherwise it would throw the error:
// TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
const _fetch = opts.fetch!;
Expand Down Expand Up @@ -212,7 +215,11 @@ export const createClient = (config: Config = {}): Client => {
request({ ...options, method });

const makeSseFn = (method: Uppercase<HttpMethod>) => async (options: RequestOptions) => {
const { opts, url } = await beforeRequest(options);
const { opts } = await beforeRequest(options);
// The SSE path applies request interceptors again inside `onRequest`
// (see below), so the URL we seed `createSseClient` with is only the
// initial value; any per-request URL mutation happens there.
const url = buildUrl(opts);
return createSseClient({
...opts,
body: opts.body as BodyInit | null | undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,8 @@ export const createClient = (config: Config = {}): Client => {
}

const resolvedOpts = opts as typeof opts & ResolvedRequestOptions<ThrowOnError, Url>;
const url = buildUrl(resolvedOpts);

return { opts: resolvedOpts, url };
return { opts: resolvedOpts };
};

// @ts-expect-error
Expand All @@ -79,14 +78,18 @@ export const createClient = (config: Config = {}): Client => {
let response: Response | undefined;

try {
const { opts, url } = await beforeRequest(options);
const { opts } = await beforeRequest(options);

for (const fn of interceptors.request.fns) {
if (fn) {
await fn(opts);
}
}

// Build the URL after request interceptors have run so any mutations to
// `opts.baseUrl`, `opts.url`, `opts.path`, or `opts.query` are honored.
const url = buildUrl(opts);

// fetch must be assigned here, otherwise it would throw the error:
// TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
const _fetch = opts.fetch!;
Expand Down Expand Up @@ -212,7 +215,11 @@ export const createClient = (config: Config = {}): Client => {
request({ ...options, method });

const makeSseFn = (method: Uppercase<HttpMethod>) => async (options: RequestOptions) => {
const { opts, url } = await beforeRequest(options);
const { opts } = await beforeRequest(options);
// The SSE path applies request interceptors again inside `onRequest`
// (see below), so the URL we seed `createSseClient` with is only the
// initial value; any per-request URL mutation happens there.
const url = buildUrl(opts);
return createSseClient({
...opts,
body: opts.body as BodyInit | null | undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,8 @@ export const createClient = (config: Config = {}): Client => {
}

const resolvedOpts = opts as typeof opts & ResolvedRequestOptions<ThrowOnError, Url>;
const url = buildUrl(resolvedOpts);

return { opts: resolvedOpts, url };
return { opts: resolvedOpts };
};

// @ts-expect-error
Expand All @@ -79,14 +78,18 @@ export const createClient = (config: Config = {}): Client => {
let response: Response | undefined;

try {
const { opts, url } = await beforeRequest(options);
const { opts } = await beforeRequest(options);

for (const fn of interceptors.request.fns) {
if (fn) {
await fn(opts);
}
}

// Build the URL after request interceptors have run so any mutations to
// `opts.baseUrl`, `opts.url`, `opts.path`, or `opts.query` are honored.
const url = buildUrl(opts);

// fetch must be assigned here, otherwise it would throw the error:
// TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
const _fetch = opts.fetch!;
Expand Down Expand Up @@ -212,7 +215,11 @@ export const createClient = (config: Config = {}): Client => {
request({ ...options, method });

const makeSseFn = (method: Uppercase<HttpMethod>) => async (options: RequestOptions) => {
const { opts, url } = await beforeRequest(options);
const { opts } = await beforeRequest(options);
// The SSE path applies request interceptors again inside `onRequest`
// (see below), so the URL we seed `createSseClient` with is only the
// initial value; any per-request URL mutation happens there.
const url = buildUrl(opts);
return createSseClient({
...opts,
body: opts.body as BodyInit | null | undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,8 @@ export const createClient = (config: Config = {}): Client => {
}

const resolvedOpts = opts as typeof opts & ResolvedRequestOptions<ThrowOnError, Url>;
const url = buildUrl(resolvedOpts);

return { opts: resolvedOpts, url };
return { opts: resolvedOpts };
};

// @ts-expect-error
Expand All @@ -79,14 +78,18 @@ export const createClient = (config: Config = {}): Client => {
let response: Response | undefined;

try {
const { opts, url } = await beforeRequest(options);
const { opts } = await beforeRequest(options);

for (const fn of interceptors.request.fns) {
if (fn) {
await fn(opts);
}
}

// Build the URL after request interceptors have run so any mutations to
// `opts.baseUrl`, `opts.url`, `opts.path`, or `opts.query` are honored.
const url = buildUrl(opts);

// fetch must be assigned here, otherwise it would throw the error:
// TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
const _fetch = opts.fetch!;
Expand Down Expand Up @@ -212,7 +215,11 @@ export const createClient = (config: Config = {}): Client => {
request({ ...options, method });

const makeSseFn = (method: Uppercase<HttpMethod>) => async (options: RequestOptions) => {
const { opts, url } = await beforeRequest(options);
const { opts } = await beforeRequest(options);
// The SSE path applies request interceptors again inside `onRequest`
// (see below), so the URL we seed `createSseClient` with is only the
// initial value; any per-request URL mutation happens there.
const url = buildUrl(opts);
return createSseClient({
...opts,
body: opts.body as BodyInit | null | undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,8 @@ export const createClient = (config: Config = {}): Client => {
}

const resolvedOpts = opts as typeof opts & ResolvedRequestOptions<ThrowOnError, Url>;
const url = buildUrl(resolvedOpts);

return { opts: resolvedOpts, url };
return { opts: resolvedOpts };
};

// @ts-expect-error
Expand All @@ -79,14 +78,18 @@ export const createClient = (config: Config = {}): Client => {
let response: Response | undefined;

try {
const { opts, url } = await beforeRequest(options);
const { opts } = await beforeRequest(options);

for (const fn of interceptors.request.fns) {
if (fn) {
await fn(opts);
}
}

// Build the URL after request interceptors have run so any mutations to
// `opts.baseUrl`, `opts.url`, `opts.path`, or `opts.query` are honored.
const url = buildUrl(opts);

// fetch must be assigned here, otherwise it would throw the error:
// TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
const _fetch = opts.fetch!;
Expand Down Expand Up @@ -212,7 +215,11 @@ export const createClient = (config: Config = {}): Client => {
request({ ...options, method });

const makeSseFn = (method: Uppercase<HttpMethod>) => async (options: RequestOptions) => {
const { opts, url } = await beforeRequest(options);
const { opts } = await beforeRequest(options);
// The SSE path applies request interceptors again inside `onRequest`
// (see below), so the URL we seed `createSseClient` with is only the
// initial value; any per-request URL mutation happens there.
const url = buildUrl(opts);
return createSseClient({
...opts,
body: opts.body as BodyInit | null | undefined,
Expand Down
Loading
Loading