In WebJobsStartup, if merging original configuration with custom configuration, the routePrefix defined in host.json is ignored and all HttpTrigger functions use "api" as routePrefix
I have not deployed this to any Azure resource yet, and I'm only running locally, so please bear with the lack of investigative information
Please provide the following:
Use the following code in a WebJobsStartup to add support for custom config-files
[assembly: WebJobsStartup(typeof(Startup))]
namespace MyFuncApp {
public class Startup : IWebJobsStartup {
public void Configure(IWebJobsBuilder builder)
{
//Get the current config and merge it into a new ConfigurationBuilder to keep the old settings
ConfigurationBuilder configBuilder = new ConfigurationBuilder();
var descriptor = builder.Services.FirstOrDefault(d => d.ServiceType == typeof(IConfiguration));
if (descriptor?.ImplementationInstance is IConfigurationRoot configuration)
{
configBuilder.AddConfiguration(configuration);
}
IConfigurationRoot config = configBuilder.Build();
//replace the existing config with the new one
builder.Services.Replace(ServiceDescriptor.Singleton(typeof(IConfiguration), config));
}
}
This should use the existing configurations inside a new ConfigurationBuilder. I could now add .AddJsonFile(...) if I wanted to, however for this example I've just created a new ConfigurationBuilder, copied the existing config into this builder, created a new config object from this builder, and replace the old config object with the new one, so there are no custom configurations to override anything.
If I debug I can see that the config variable contains a (private) ChainedConfigurationProvider that contains all the default configurations, including the HostJsonFileConfigurationProvider that has routePrefix: "".
When starting the Function app locally I can see that the routePrefix is now ignored, and all my functions have "api" at the start of their route, even though my host.json has a blank value. Here's my host.json:
{
"version": "2.0",
"extensions": {
"http": {
"routePrefix": ""
}
}
}
It all boils down to this line of code:
builder.Services.Replace(ServiceDescriptor.Singleton(typeof(IConfiguration), config));
If I remove this the routePrefix is blank (as stated in the host.json file). If this line is used the routePrefix is "api".
It would therefore seem that there might be a bug in the routePrefix resolver that fails to read the prefix from host.json whenever a custom IConfiguration is used, even if this configuration should have merged in the settings from the old configuration.
Configurations should be merged without overwriting routePrefix functionality
routePrefix gets reset to "api" even if it is "" in host.json
N/A
This just bit me yesterday for a couple hours. Some guidance in #4726 may help in determining what the correct way to do this is without losing this information.
So sorry for the huge delay here. I thought we had resolved this one.
@fabiocav / @brettsam had insights about this one.
@gthvidsten as a workaround you can do the following in the startup:
IServiceProvider provider = builder.Services.BuildServiceProvider();
IConfiguration existingConfig = provider.GetRequiredService<IConfiguration>();
var yourBuilder = new ConfigurationBuilder().AddConfiguration(existingConfiguration);//add your providers as needed
services.Replace(ServiceDescriptor.Singleton(typeof(IConfiguration), yourBuilder.Build()));
This works for functions runtime V3, tested both locally and in the cloud.
@gthvidsten Also, I started to see random OOM exceptions in my V3 funcs, I'm not sure whether it's connected to config replacement(I think not) but still wanted to mention a possible problem.
@Badabum do you have details on the OOM exception you ran into? Would you be able to share that in a different issue?
@fabiocav yup, I added a comment in another related issue.
I'm still seeing this bug / behaviour in functions v2 when attempting to build custom configuration. The routePrefix that I have set to an empty string in the host json file is being ignored and all routes are being prefixed with /api.
@joshua-hayes @fabiocav I see the same in v3(empty routePrefix) results in /api prefix.
Same here
Any news?
Woked around with .Configure<HttpOptions>(fun (options : HttpOptions) -> options.RoutePrefix <- String.Empty; ()) for now. But it is weird
What I seem to have observed in testing this out is that the value specified in host.json using the above approach is obeyed if you use a value other than "". Example, I set it to "foo" and my routes were discovered with a routePrefix of /foo. There seems to be something about empty string specifically.
The workaround mentioned by @xperiandri seemed to do the trick for now.
I added the the following line to to the Startup.cs:
services.Configure<HttpOptions>(options => options.RoutePrefix = string.Empty);
Confirmed what @andrewdmoreno says - works with any value but an empty string.
Assingning this to sprint 82 for validation using the new configuration APIs
I was able to reproduce the error - it appears that using Functions version 2.0.14248.0 (with the new API's expected), the issue persists. Filing as a bug.
Most helpful comment
What I seem to have observed in testing this out is that the value specified in
host.jsonusing the above approach is obeyed if you use a value other than"". Example, I set it to"foo"and my routes were discovered with a routePrefix of/foo. There seems to be something about empty string specifically.