Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't Override request.url in beforeRequest hook #640

Open
kevbook opened this issue Sep 25, 2024 · 2 comments
Open

Can't Override request.url in beforeRequest hook #640

kevbook opened this issue Sep 25, 2024 · 2 comments

Comments

@kevbook
Copy link

kevbook commented Sep 25, 2024

Use case, we need to check and append token search-param because our some of our vendors use search parameters instead of headers. But request.url only has a getter.

@sindresorhus
Copy link
Owner

You can make a new request:

return new Request(newURL, request);

@kevbook
Copy link
Author

kevbook commented Sep 25, 2024

Something like this?

import type { BeforeRequestHook } from 'ky';

/**
 * Round-robin helper to rotate headers or search params (e.g. for API keys)
 *
 * Usage:
 * const client = await ky.create(url, {
 *   hooks: { beforeRequest: [
 *     roundRobin('headers', [
 *       { 'key': 'API_KEY_1', 'client-id': 'CLIENT_ID_1' ...},
 *       { 'key': 'API_KEY_2', 'client-id': 'CLIENT_ID_2' ...},
 *       { 'key': 'API_KEY_3', 'client-id': 'CLIENT_ID_3' ...}
 *     ])
 *   ]}
 * });
 */
export const roundRobin = function (
  paramType: 'headers' | 'searchParams',
  requestParamsArr: Record<string, string>[]
) {
  // Validate that each object has non-empty string values
  requestParamsArr.forEach(function (params, index) {
    if (
      Object.entries(params).some(function ([_key, value]) {
        return typeof value !== 'string' || value.trim() === '';
      })
    ) {
      throw new Error(`Request params at index ${index} contains non-string value`);
    }
  });

  const requestParamsLen = requestParamsArr.length;
  let state = 0; // Keeps track of which header set to use next

  return function (request) {
    // Get the current set of search params based on the state
    const currentParams = requestParamsArr[state] as Record<string, string>;

    // Apply each header in the current set
    if (paramType === 'headers') {
      for (const [key, value] of Object.entries(currentParams)) {
        request.headers.set(key, value);
      }

      // Move to the next header set in the array, loop back when at the end
      state = (state + 1) % requestParamsLen;
    } else if (paramType === 'searchParams') {
      const url = new URL(request.url);
      for (const [key, value] of Object.entries(currentParams)) {
        url.searchParams.set(key, value);
      }
      // Move to the next header set in the array, loop back when at the end
      state = (state + 1) % requestParamsLen;
      // console.log('===================', url);
      new Request(url, request);
    }
  } satisfies BeforeRequestHook;
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants