Skip to content

Commit 895cccd

Browse files
committed
Fixing WEBSITE_HOSTNAME issue (#4162)
1 parent f462d89 commit 895cccd

20 files changed

+239
-46
lines changed

src/WebJobs.Script.WebHost/App_Start/WebHostResolver.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,9 @@ internal void EnsureInitialized(WebHostSettings settings)
153153
// settings configured by the user (WEBSITE_TIME_ZONE) are honored.
154154
// DateTime caches timezone information, so we need to clear the cache.
155155
TimeZoneInfo.ClearCachedData();
156+
157+
// ensure we reinitialize hostname after specialization
158+
HostNameProvider.Reset();
156159
}
157160

158161
if (_standbyHostManager != null)

src/WebJobs.Script.WebHost/Extensions/FunctionMetadataExtensions.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,8 @@ internal static string GetScmBaseUrl()
170170
{
171171
// VFS APIs aren't exposed by the v1 runtime, so we must redirect
172172
// to the SCM site
173-
string hostName = Environment.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteHostName);
174-
173+
string hostName = HostNameProvider.Value;
174+
175175
string scmHostName = null;
176176
if (!string.IsNullOrEmpty(hostName))
177177
{
@@ -195,7 +195,7 @@ internal static string GetScmBaseUrl()
195195

196196
internal static string GetAppBaseUrl()
197197
{
198-
string hostName = Environment.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteHostName) ?? "localhost";
198+
string hostName = HostNameProvider.Value ?? "localhost";
199199
return $"https://{hostName}";
200200
}
201201

src/WebJobs.Script.WebHost/Handlers/SystemTraceHandler.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage
2929
.WithDefaults(ScriptConstants.TraceSourceHttpHandler);
3030

3131
SetRequestId(request);
32+
HostNameProvider.Synchronize(request, traceWriter);
33+
3234
if (request.IsColdStart())
3335
{
3436
// for cold start requests we want to measure the request
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the MIT License. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Linq;
7+
using System.Net.Http;
8+
using Microsoft.Azure.WebJobs.Host;
9+
using Microsoft.Azure.WebJobs.Script.Config;
10+
11+
namespace Microsoft.Azure.WebJobs.Script.WebHost
12+
{
13+
/// <summary>
14+
/// Provides the current HostName for the Function App.
15+
/// <remarks>
16+
/// The environment value for WEBSITE_HOSTNAME is unreliable and shouldn't be used directly. AppService site swaps change
17+
/// the site’s hostname under the covers, and the worker process is NOT recycled (for performance reasons). That means the
18+
/// site will continue to run with the same hostname environment variable, leading to an incorrect host name.
19+
///
20+
/// WAS_DEFAULT_HOSTNAME is a header injected by front end on every request which provides the correct hostname. We check
21+
/// this header on all http requests, and updated the cached hostname value as needed.
22+
/// </remarks>
23+
/// </summary>
24+
public static class HostNameProvider
25+
{
26+
private static string _hostName;
27+
28+
public static string Value
29+
{
30+
get
31+
{
32+
if (string.IsNullOrEmpty(_hostName))
33+
{
34+
// default to the the value specified in environment
35+
var settings = ScriptSettingsManager.Instance;
36+
_hostName = settings.GetSetting(EnvironmentSettingNames.AzureWebsiteHostName);
37+
if (string.IsNullOrEmpty(_hostName))
38+
{
39+
string websiteName = settings.GetSetting(EnvironmentSettingNames.AzureWebsiteName);
40+
if (!string.IsNullOrEmpty(websiteName))
41+
{
42+
_hostName = $"{websiteName}.azurewebsites.net";
43+
}
44+
}
45+
}
46+
return _hostName;
47+
}
48+
}
49+
50+
public static void Synchronize(HttpRequestMessage request, TraceWriter traceWriter)
51+
{
52+
string hostNameHeaderValue = request.GetHeaderValueOrDefault(ScriptConstants.AntaresDefaultHostNameHeader);
53+
if (!string.IsNullOrEmpty(hostNameHeaderValue) &&
54+
string.Compare(Value, hostNameHeaderValue) != 0)
55+
{
56+
traceWriter.InfoFormat("HostName updated from '{0}' to '{1}'", Value, hostNameHeaderValue);
57+
_hostName = hostNameHeaderValue;
58+
}
59+
}
60+
61+
internal static void Reset()
62+
{
63+
_hostName = null;
64+
}
65+
}
66+
}

src/WebJobs.Script.WebHost/Management/FunctionsSyncManager.cs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -387,18 +387,13 @@ private async Task<Dictionary<string, string>> ReadDurableTaskConfig()
387387
internal static HttpRequestMessage BuildSetTriggersRequest()
388388
{
389389
var protocol = "https";
390-
// On private stamps with no ssl certificate use http instead.
391390
if (Environment.GetEnvironmentVariable(EnvironmentSettingNames.SkipSslValidation) == "1")
392391
{
392+
// On private stamps with no ssl certificate use http instead.
393393
protocol = "http";
394394
}
395395

396-
var hostname = Environment.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteHostName);
397-
// Linux Dedicated on AppService doesn't have WEBSITE_HOSTNAME
398-
hostname = string.IsNullOrWhiteSpace(hostname)
399-
? $"{Environment.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteName)}.azurewebsites.net"
400-
: hostname;
401-
396+
var hostname = HostNameProvider.Value;
402397
var url = $"{protocol}://{hostname}/operations/settriggers";
403398

404399
return new HttpRequestMessage(HttpMethod.Post, url);

src/WebJobs.Script.WebHost/Security/ScriptSecrets.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ public abstract class ScriptSecrets
1717
{
1818
protected ScriptSecrets()
1919
{
20-
HostName = ScriptSettingsManager.Instance.GetSetting(EnvironmentSettingNames.AzureWebsiteHostName);
2120
InstanceId = ScriptSettingsManager.Instance.InstanceId;
2221
Source = ScriptConstants.Runtime;
2322
}

src/WebJobs.Script.WebHost/Security/SecretManager.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@ public SecretManager(ISecretsRepository repository, IKeyValueConverterFactory ke
4747

4848
if (createHostSecretsIfMissing)
4949
{
50-
// The SecretManager implementation of GetHostSecrets will
51-
// create a host secret if one is not present.
50+
// GetHostSecrets will create host secrets if not present
5251
GetHostSecretsAsync().GetAwaiter().GetResult();
5352
}
5453

@@ -461,6 +460,11 @@ private Task RefreshSecretsAsync<T>(T secrets, string keyScope = null) where T :
461460

462461
private async Task PersistSecretsAsync<T>(T secrets, string keyScope = null, bool isNonDecryptable = false) where T : ScriptSecrets
463462
{
463+
if (secrets != null)
464+
{
465+
secrets.HostName = HostNameProvider.Value;
466+
}
467+
464468
ScriptSecretsType secretsType = secrets.SecretsType;
465469
string secretsContent = ScriptSecretSerializer.SerializeSecrets<T>(secrets);
466470
if (isNonDecryptable)

src/WebJobs.Script.WebHost/Swagger/SwaggerDocumentManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public SwaggerDocumentManager(ScriptHostConfiguration hostConfig)
3636
public JObject GenerateSwaggerDocument(HttpRouteCollection routes)
3737
{
3838
var swaggerDocument = new SwaggerDocument();
39-
string hostname = ScriptSettingsManager.Instance.GetSetting(EnvironmentSettingNames.AzureWebsiteHostName);
39+
string hostname = HostNameProvider.Value;
4040
swaggerDocument.SwaggerInfo.FunctionAppName = hostname;
4141
swaggerDocument.Host = hostname;
4242
swaggerDocument.ApiEndpoints = GetEndpointsData(routes);

src/WebJobs.Script.WebHost/WebHooks/WebJobsSdkExtensionHookProvider.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,7 @@ public Uri GetUrl(IExtensionConfigProvider extension)
5252
// Provides the URL for accessing the admin extensions WebHook route.
5353
private Uri GetExtensionWebHookRoute(string extensionName)
5454
{
55-
var settings = ScriptSettingsManager.Instance;
56-
var hostName = settings.GetSetting(EnvironmentSettingNames.AzureWebsiteHostName);
55+
var hostName = HostNameProvider.Value;
5756
if (hostName == null)
5857
{
5958
return null;

src/WebJobs.Script.WebHost/WebJobs.Script.WebHost.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,7 @@
510510
<Compile Include="Extensions\IEnumerableTasksExtensions.cs" />
511511
<Compile Include="Filters\EnableDebugModeAttribute.cs" />
512512
<Compile Include="Filters\RequiresRunningHostAttribute.cs" />
513+
<Compile Include="HostNameProvider.cs" />
513514
<Compile Include="Management\FunctionsSyncManager.cs" />
514515
<Compile Include="Management\IFunctionsSyncManager.cs" />
515516
<Compile Include="Management\IWebFunctionsManager.cs" />

0 commit comments

Comments
 (0)