unjs / nitro

Next Generation Server Toolkit. Create web servers with everything you need and deploy them wherever you prefer.
https://nitro.unjs.io
MIT License
5.48k stars 472 forks source link

Allow routeRules.proxy.to to be a function. #2227

Closed alan-strickland-red closed 4 months ago

alan-strickland-red commented 4 months ago

Describe the feature

When using route rules for a proxy I would like to use environment variables to set the to property at runtime.

This would allow me to change the location of a proxy within a docker container.

Currently if you try to use environment variables to set the value of routeRule.proxy.to it uses the values from the environment on build.

I think the following changes would be required.

https://github.com/unjs/nitro/blob/674089b309e7e73c78f25c5e9ca20f035059706d/src/runtime/route-rules.ts#L47

    // Apply proxy options
    if (routeRules.proxy) {
      let target = routeRules.proxy.to;

      if(typeof target === 'function') target = target();

      if (target.endsWith("/**")) {
        let targetPath = event.path;
        const strpBase = (routeRules.proxy as any)._proxyStripBase;
        if (strpBase) {
          targetPath = withoutBase(targetPath, strpBase);
        }
        target = joinURL(target.slice(0, -3), targetPath);
      } else if (event.path.includes("?")) {
        const query = getQuery(event.path);
        target = withQuery(target, query);
      }
      return proxyRequest(event, target, {
        fetch: ctx.localFetch,
        ...routeRules.proxy,
      });
    }

https://github.com/unjs/nitro/blob/674089b309e7e73c78f25c5e9ca20f035059706d/src/types/nitro.ts#L204

export interface NitroRouteRules
  extends Omit<NitroRouteConfig, "redirect" | "cors" | "swr" | "static"> {
  redirect?: { to: string; statusCode: HTTPStatusCode };
  proxy?: { to: string | () => string } & ProxyOptions;
}

I haven't made use of 'redirect.to' yet but I suspect the same could apply.

Is there another way of accomplishing this, can you define route rules outside of the config file?

Usage

  routeRules: {
    '/_api/**': {
      proxy: {
        to: (): string => `https://${process.env.API_HOST || 'localhost'}:${process.env.API_PORT || '8080'}/**`,
      },
    },
}

Additional information

manniL commented 4 months ago

routeRules must be serializable. As a function is not, you can't provide one through the config. Other options would be an own endpoint or using https://github.com/unjs/nitro/pull/2043 (experimental)

alan-strickland-red commented 4 months ago

I see, just to expand my knowledge can you explain why must it be serializable?

The environment expansion change looks interesting, I will take a closer look at that.