diff --git a/src/WebJobs.Script.NuGet/WebJobs.Script.nuspec b/src/WebJobs.Script.NuGet/WebJobs.Script.nuspec index a7a679006d..9aff41c176 100644 --- a/src/WebJobs.Script.NuGet/WebJobs.Script.nuspec +++ b/src/WebJobs.Script.NuGet/WebJobs.Script.nuspec @@ -19,7 +19,7 @@ - + diff --git a/src/WebJobs.Script.WebHost/GlobalSuppressions.cs b/src/WebJobs.Script.WebHost/GlobalSuppressions.cs index 61944f0102..c41eece0e3 100644 --- a/src/WebJobs.Script.WebHost/GlobalSuppressions.cs +++ b/src/WebJobs.Script.WebHost/GlobalSuppressions.cs @@ -108,4 +108,5 @@ [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Scope = "member", Target = "Microsoft.Azure.WebJobs.Script.WebHost.DefaultSecretManagerFactory.#Create(Microsoft.Azure.WebJobs.Script.Config.ScriptSettingsManager,Microsoft.Azure.WebJobs.Host.TraceWriter,Microsoft.Extensions.Logging.ILoggerFactory,Microsoft.Azure.WebJobs.Script.WebHost.ISecretsRepository)")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors", Scope = "member", Target = "Microsoft.Azure.WebJobs.Script.WebHost.SecretManager.#.ctor(Microsoft.Azure.WebJobs.Script.WebHost.ISecretsRepository,Microsoft.Azure.WebJobs.Script.WebHost.IKeyValueConverterFactory,Microsoft.Azure.WebJobs.Host.TraceWriter,Microsoft.Extensions.Logging.ILoggerFactory,System.Boolean)")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "host", Scope = "member", Target = "Microsoft.Azure.WebJobs.Script.WebHost.StandbyManager.#WarmUp(Microsoft.Azure.WebJobs.Script.ScriptHost)")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "settings", Scope = "member", Target = "Microsoft.Azure.WebJobs.Script.WebHost.WebHostResolver.#GetPerformanceManager(Microsoft.Azure.WebJobs.Script.WebHost.WebHostSettings)")] \ No newline at end of file +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "settings", Scope = "member", Target = "Microsoft.Azure.WebJobs.Script.WebHost.WebHostResolver.#GetPerformanceManager(Microsoft.Azure.WebJobs.Script.WebHost.WebHostSettings)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed", MessageId = "_httpFunctionsOnlyRoutes", Scope = "member", Target = "Microsoft.Azure.WebJobs.Script.WebHost.WebScriptHostManager.#Dispose(System.Boolean)")] \ No newline at end of file diff --git a/src/WebJobs.Script.WebHost/ProxyFunctionExecutor.cs b/src/WebJobs.Script.WebHost/ProxyFunctionExecutor.cs index aacab582d0..93fb3ef762 100644 --- a/src/WebJobs.Script.WebHost/ProxyFunctionExecutor.cs +++ b/src/WebJobs.Script.WebHost/ProxyFunctionExecutor.cs @@ -22,7 +22,6 @@ public class ProxyFunctionExecutor : IFuncExecutor { private readonly WebScriptHostManager _scriptHostManager; private readonly ISecretManager _secretManager; - private readonly string _httpPrefix; private WebHookReceiverManager _webHookReceiverManager; @@ -31,18 +30,6 @@ internal ProxyFunctionExecutor(WebScriptHostManager scriptHostManager, WebHookRe _scriptHostManager = scriptHostManager; _webHookReceiverManager = webHookReceiverManager; _secretManager = secretManager; - - _httpPrefix = HttpExtensionConstants.DefaultRoutePrefix; - - if (_scriptHostManager.Instance != null) - { - var json = _scriptHostManager.Instance.ScriptConfig.HostConfig.HostConfigMetadata; - - if (json != null && json["http"] != null && json["http"]["routePrefix"] != null) - { - _httpPrefix = json["http"]["routePrefix"].ToString().Trim(new char[] { '/' }); - } - } } public async Task ExecuteFuncAsync(string funcName, Dictionary arguments, CancellationToken cancellationToken) @@ -50,62 +37,9 @@ public async Task ExecuteFuncAsync(string funcName, Dictionary a HttpRequestMessage request = arguments[ScriptConstants.AzureFunctionsHttpRequestKey] as HttpRequestMessage; FunctionDescriptor function = null; - var path = request.RequestUri.AbsolutePath.Trim(new char[] { '/' }); - - if (path.StartsWith(_httpPrefix)) - { - path = path.Remove(0, _httpPrefix.Length); - } - path = path.Trim(new char[] { '/' }); - - // This is a call to the local function app, before handing the route to asp.net to pick the FunctionDescriptor the following will be run: - // 1. If the request maps to a local http trigger function name then that function will be picked. - // 2. Else if the request maps to a custom route of a local http trigger function then that function will be picked - // 3. Otherwise the request will be given to asp.net to pick the appropriate route. - foreach (var func in _scriptHostManager.HttpFunctions.Values) - { - if (!func.Metadata.IsProxy) - { - if (path.Equals(func.Metadata.Name, StringComparison.OrdinalIgnoreCase)) - { - function = func; - break; - } - else - { - foreach (var binding in func.InputBindings) - { - if (binding.Metadata.IsTrigger) - { - string functionRoute = null; - var jsonContent = binding.Metadata.Raw; - if (jsonContent != null && jsonContent["route"] != null) - { - functionRoute = jsonContent["route"].ToString(); - } - - // BUG: Known issue, This does not work on dynamic routes like products/{category:alpha}/{id:int?} - if (!string.IsNullOrEmpty(functionRoute) && path.Equals(functionRoute, StringComparison.OrdinalIgnoreCase)) - { - function = func; - break; - } - } - } - - if (function != null) - { - break; - } - } - } - } - - if (function == null) - { - function = _scriptHostManager.GetHttpFunctionOrNull(request); - } + // This is a call to the local function app from proxy, in this scenario first match will be against local http triggers then rest of the proxies to avoid infinite redirect for * mappings in proxies. + function = _scriptHostManager.GetHttpFunctionOrNull(request, functionRoutesFirst: true); var functionRequestInvoker = new FunctionRequestInvoker(function, _secretManager); var response = await functionRequestInvoker.PreprocessRequestAsync(request); diff --git a/src/WebJobs.Script.WebHost/WebJobs.Script.WebHost.csproj b/src/WebJobs.Script.WebHost/WebJobs.Script.WebHost.csproj index 067b5b5679..e9a7fd12e7 100644 --- a/src/WebJobs.Script.WebHost/WebJobs.Script.WebHost.csproj +++ b/src/WebJobs.Script.WebHost/WebJobs.Script.WebHost.csproj @@ -81,7 +81,7 @@ ..\..\packages\Microsoft.ApplicationInsights.2.4.0\lib\net46\Microsoft.ApplicationInsights.dll - ..\..\packages\Microsoft.Azure.AppService.Proxy.0.3.2.20\lib\net461\Microsoft.AspNet.Razor.dll + ..\..\packages\Microsoft.Azure.AppService.Proxy.1.0.0.1\lib\net461\Microsoft.AspNet.Razor.dll ..\..\packages\Microsoft.AspNet.WebHooks.Common.1.2.0\lib\net45\Microsoft.AspNet.WebHooks.Common.dll @@ -176,14 +176,14 @@ ..\..\packages\Microsoft.Azure.ApiHub.Sdk.0.7.2-alpha\lib\net45\Microsoft.Azure.ApiHub.Sdk.dll True - - ..\..\packages\Microsoft.Azure.AppService.Proxy.0.3.2.20\lib\net461\Microsoft.Azure.AppService.Proxy.Client.dll + + ..\..\packages\Microsoft.Azure.AppService.Proxy.1.0.0.1\lib\net461\Microsoft.Azure.AppService.Proxy.Client.dll - - ..\..\packages\Microsoft.Azure.AppService.Proxy.0.3.2.20\lib\net461\Microsoft.Azure.AppService.Proxy.Common.dll + + ..\..\packages\Microsoft.Azure.AppService.Proxy.1.0.0.1\lib\net461\Microsoft.Azure.AppService.Proxy.Common.dll - - ..\..\packages\Microsoft.Azure.AppService.Proxy.0.3.2.20\lib\net461\Microsoft.Azure.AppService.Proxy.Runtime.dll + + ..\..\packages\Microsoft.Azure.AppService.Proxy.1.0.0.1\lib\net461\Microsoft.Azure.AppService.Proxy.Runtime.dll ..\..\packages\Microsoft.Azure.DocumentDB.ChangeFeedProcessor.1.0.0\lib\net45\Microsoft.Azure.Documents.ChangeFeedProcessor.dll diff --git a/src/WebJobs.Script.WebHost/WebScriptHostManager.cs b/src/WebJobs.Script.WebHost/WebScriptHostManager.cs index 7254fcec1e..0324f3fed2 100644 --- a/src/WebJobs.Script.WebHost/WebScriptHostManager.cs +++ b/src/WebJobs.Script.WebHost/WebScriptHostManager.cs @@ -48,6 +48,7 @@ public class WebScriptHostManager : ScriptHostManager private bool _hostStarted = false; private IDictionary _httpFunctions; private HttpRouteCollection _httpRoutes; + private HttpRouteCollection _httpFunctionsOnlyRoutes; private HttpRequestManager _httpRequestManager; public WebScriptHostManager(ScriptHostConfiguration config, @@ -218,6 +219,7 @@ protected override void Dispose(bool disposing) { (_secretManager as IDisposable)?.Dispose(); _metricsLogger?.Dispose(); + _httpFunctionsOnlyRoutes?.Dispose(); _httpRoutes?.Dispose(); } @@ -276,7 +278,7 @@ private static object GetWebHookData(Type dataType, WebHookHandlerContext contex return getDataMethod.Invoke(null, new object[] { context }); } - public FunctionDescriptor GetHttpFunctionOrNull(HttpRequestMessage request) + public FunctionDescriptor GetHttpFunctionOrNull(HttpRequestMessage request, bool functionRoutesFirst = false) { if (request == null) { @@ -289,7 +291,25 @@ public FunctionDescriptor GetHttpFunctionOrNull(HttpRequestMessage request) } FunctionDescriptor function = null; - var routeData = _httpRoutes.GetRouteData(request); + + // if true, the match will first be against local http trigger functions otherwise it will be against proxies and functions combined with proxies matching first which is the default behavior. + if (functionRoutesFirst) + { + function = GetFunctionDescriptorFromRoute(request, _httpFunctionsOnlyRoutes.GetRouteData(request)); + } + + if (function == null) + { + function = GetFunctionDescriptorFromRoute(request, _httpRoutes.GetRouteData(request)); + } + + return function; + } + + private FunctionDescriptor GetFunctionDescriptorFromRoute(HttpRequestMessage request, IHttpRouteData routeData) + { + FunctionDescriptor function = null; + if (routeData != null) { _httpFunctions.TryGetValue(routeData.Route, out function); @@ -392,6 +412,7 @@ private void InitializeHttpFunctions(IEnumerable functions, _httpFunctions = new Dictionary(); _httpRoutes = new HttpRouteCollection(); + _httpFunctionsOnlyRoutes = new HttpRouteCollection(); // Proxy routes will take precedence over http trigger functions and http trigger // routes so they will be added first to the list of http routes. @@ -413,6 +434,11 @@ private void InitializeHttpFunctions(IEnumerable functions, { _httpFunctions.Add(httpRoute, function); } + + if (!function.Metadata.IsProxy) + { + functionHttpRouteFactory.TryAddRoute(function.Metadata.Name, httpTrigger.Route, httpMethods, _httpFunctionsOnlyRoutes, out httpRoute); + } } } } diff --git a/src/WebJobs.Script.WebHost/packages.config b/src/WebJobs.Script.WebHost/packages.config index 6d914ea3ad..d24a31a58e 100644 --- a/src/WebJobs.Script.WebHost/packages.config +++ b/src/WebJobs.Script.WebHost/packages.config @@ -38,7 +38,7 @@ - + diff --git a/src/WebJobs.Script/Description/Proxies/ProxyFunctionInvoker.cs b/src/WebJobs.Script/Description/Proxies/ProxyFunctionInvoker.cs index 2ebad5a0df..26630c9310 100644 --- a/src/WebJobs.Script/Description/Proxies/ProxyFunctionInvoker.cs +++ b/src/WebJobs.Script/Description/Proxies/ProxyFunctionInvoker.cs @@ -14,7 +14,7 @@ internal class ProxyFunctionInvoker : FunctionInvokerBase private ProxyClientExecutor _proxyClient; public ProxyFunctionInvoker(ScriptHost host, FunctionMetadata functionMetadata, ProxyClientExecutor proxyClient) - : base(host, functionMetadata, logDirName: "Proxy") + : base(host, functionMetadata) { _proxyClient = proxyClient; } diff --git a/src/WebJobs.Script/WebJobs.Script.csproj b/src/WebJobs.Script/WebJobs.Script.csproj index b76ac6dc16..ed73fedc94 100644 --- a/src/WebJobs.Script/WebJobs.Script.csproj +++ b/src/WebJobs.Script/WebJobs.Script.csproj @@ -81,20 +81,20 @@ ..\..\packages\Microsoft.ApplicationInsights.2.4.0\lib\net46\Microsoft.ApplicationInsights.dll - ..\..\packages\Microsoft.Azure.AppService.Proxy.0.3.2.20\lib\net461\Microsoft.AspNet.Razor.dll + ..\..\packages\Microsoft.Azure.AppService.Proxy.1.0.0.1\lib\net461\Microsoft.AspNet.Razor.dll ..\..\packages\Microsoft.Azure.ApiHub.Sdk.0.7.2-alpha\lib\net45\Microsoft.Azure.ApiHub.Sdk.dll True - - ..\..\packages\Microsoft.Azure.AppService.Proxy.0.3.2.20\lib\net461\Microsoft.Azure.AppService.Proxy.Client.dll + + ..\..\packages\Microsoft.Azure.AppService.Proxy.1.0.0.1\lib\net461\Microsoft.Azure.AppService.Proxy.Client.dll - - ..\..\packages\Microsoft.Azure.AppService.Proxy.0.3.2.20\lib\net461\Microsoft.Azure.AppService.Proxy.Common.dll + + ..\..\packages\Microsoft.Azure.AppService.Proxy.1.0.0.1\lib\net461\Microsoft.Azure.AppService.Proxy.Common.dll - - ..\..\packages\Microsoft.Azure.AppService.Proxy.0.3.2.20\lib\net461\Microsoft.Azure.AppService.Proxy.Runtime.dll + + ..\..\packages\Microsoft.Azure.AppService.Proxy.1.0.0.1\lib\net461\Microsoft.Azure.AppService.Proxy.Runtime.dll ..\..\packages\Microsoft.Azure.DocumentDB.ChangeFeedProcessor.1.0.0\lib\net45\Microsoft.Azure.Documents.ChangeFeedProcessor.dll diff --git a/src/WebJobs.Script/packages.config b/src/WebJobs.Script/packages.config index 061c55170b..6ee9689b52 100644 --- a/src/WebJobs.Script/packages.config +++ b/src/WebJobs.Script/packages.config @@ -14,7 +14,7 @@ - + diff --git a/test/WebJobs.Script.Tests.Integration/ProxyEndToEndTests.cs b/test/WebJobs.Script.Tests.Integration/ProxyEndToEndTests.cs index 314b669117..be8af29b4e 100644 --- a/test/WebJobs.Script.Tests.Integration/ProxyEndToEndTests.cs +++ b/test/WebJobs.Script.Tests.Integration/ProxyEndToEndTests.cs @@ -94,15 +94,23 @@ public async Task CatchAllApis() } [Fact] - public async Task CatchAll() + public async Task CatchAllWithCustomRoutes() { - HttpResponseMessage response = await _fixture.HttpClient.GetAsync($"proxy/blahblah"); + HttpResponseMessage response = await _fixture.HttpClient.GetAsync($"proxy/api/myroute/mysubroute"); string content = await response.Content.ReadAsStringAsync(); Assert.Equal("200", response.StatusCode.ToString("D")); Assert.Equal("Pong", content); } + [Fact] + public async Task CatchAllWithCustomRoutesWithInvalidVerb() + { + HttpResponseMessage response = await _fixture.HttpClient.PutAsync($"proxy/api/myroute/mysubroute", null); + + Assert.Equal("404", response.StatusCode.ToString("D")); + } + [Fact] public async Task LongRoute() { @@ -116,6 +124,16 @@ public async Task LongRoute() Assert.Equal("200", response.StatusCode.ToString("D")); } + [Fact] + public async Task ProxyCallingLocalProxy() + { + HttpResponseMessage response = await _fixture.HttpClient.GetAsync($"/pr1/api/Ping"); + + string content = await response.Content.ReadAsStringAsync(); + Assert.Equal("200", response.StatusCode.ToString("D")); + Assert.Equal("Pong", content); + } + public class TestFixture : IDisposable { private readonly ScriptSettingsManager _settingsManager; diff --git a/test/WebJobs.Script.Tests.Integration/TestScripts/Proxies/PingRoute/function.json b/test/WebJobs.Script.Tests.Integration/TestScripts/Proxies/PingRoute/function.json index bc777c57b5..cc37c85ef8 100644 --- a/test/WebJobs.Script.Tests.Integration/TestScripts/Proxies/PingRoute/function.json +++ b/test/WebJobs.Script.Tests.Integration/TestScripts/Proxies/PingRoute/function.json @@ -5,7 +5,7 @@ "name": "req", "type": "httpTrigger", "direction": "in", - "route": "myroute" + "route": "myroute/mysubroute" }, { "name": "$return", diff --git a/test/WebJobs.Script.Tests.Integration/TestScripts/Proxies/proxies.json b/test/WebJobs.Script.Tests.Integration/TestScripts/Proxies/proxies.json index a10703e654..575c258b96 100644 --- a/test/WebJobs.Script.Tests.Integration/TestScripts/Proxies/proxies.json +++ b/test/WebJobs.Script.Tests.Integration/TestScripts/Proxies/proxies.json @@ -68,9 +68,10 @@ }, "catchAllRoutes": { "matchCondition": { - "route": "/proxy/{*path}" + "route": "/proxy/{*path}", + "methods": ["GET", "POST"] }, - "backendUri": "http://localhost/myroute", + "backendUri": "http://localhost/{path}", "requestOverrides": { "backend.request.headers.accept": "text/plain" } @@ -86,6 +87,24 @@ "requestOverrides": { "backend.request.headers.accept": "text/plain" } + }, + "ProxyCallingLocalProxy1": { + "matchCondition": { + "route": "/pr1/{*path}" + }, + "backendUri": "https://localhost/pr2/{path}", + "requestOverrides": { + "backend.request.headers.accept": "text/plain" + } + }, + "ProxyCallingLocalProxy2": { + "matchCondition": { + "route": "/pr2/{*path}" + }, + "backendUri": "https://localhost/{path}", + "requestOverrides": { + "backend.request.headers.accept": "text/plain" + } } } } diff --git a/test/WebJobs.Script.Tests.Integration/WebJobs.Script.Tests.Integration.csproj b/test/WebJobs.Script.Tests.Integration/WebJobs.Script.Tests.Integration.csproj index 76f4824182..3a02696e01 100644 --- a/test/WebJobs.Script.Tests.Integration/WebJobs.Script.Tests.Integration.csproj +++ b/test/WebJobs.Script.Tests.Integration/WebJobs.Script.Tests.Integration.csproj @@ -72,7 +72,7 @@ ..\..\packages\Microsoft.ApplicationInsights.2.4.0\lib\net46\Microsoft.ApplicationInsights.dll - ..\..\packages\Microsoft.Azure.AppService.Proxy.0.3.2.20\lib\net461\Microsoft.AspNet.Razor.dll + ..\..\packages\Microsoft.Azure.AppService.Proxy.1.0.0.1\lib\net461\Microsoft.AspNet.Razor.dll ..\..\packages\Microsoft.AspNet.WebHooks.Common.1.2.0\lib\net45\Microsoft.AspNet.WebHooks.Common.dll @@ -104,14 +104,14 @@ ..\..\packages\Microsoft.Azure.ApiHub.Sdk.0.7.2-alpha\lib\net45\Microsoft.Azure.ApiHub.Sdk.dll - - ..\..\packages\Microsoft.Azure.AppService.Proxy.0.3.2.20\lib\net461\Microsoft.Azure.AppService.Proxy.Client.dll + + ..\..\packages\Microsoft.Azure.AppService.Proxy.1.0.0.1\lib\net461\Microsoft.Azure.AppService.Proxy.Client.dll - - ..\..\packages\Microsoft.Azure.AppService.Proxy.0.3.2.20\lib\net461\Microsoft.Azure.AppService.Proxy.Common.dll + + ..\..\packages\Microsoft.Azure.AppService.Proxy.1.0.0.1\lib\net461\Microsoft.Azure.AppService.Proxy.Common.dll - - ..\..\packages\Microsoft.Azure.AppService.Proxy.0.3.2.20\lib\net461\Microsoft.Azure.AppService.Proxy.Runtime.dll + + ..\..\packages\Microsoft.Azure.AppService.Proxy.1.0.0.1\lib\net461\Microsoft.Azure.AppService.Proxy.Runtime.dll ..\..\packages\Microsoft.Azure.DocumentDB.ChangeFeedProcessor.1.0.0\lib\net45\Microsoft.Azure.Documents.ChangeFeedProcessor.dll diff --git a/test/WebJobs.Script.Tests.Integration/packages.config b/test/WebJobs.Script.Tests.Integration/packages.config index f16cd8393c..3624a15016 100644 --- a/test/WebJobs.Script.Tests.Integration/packages.config +++ b/test/WebJobs.Script.Tests.Integration/packages.config @@ -22,7 +22,7 @@ - + diff --git a/test/WebJobs.Script.Tests/WebJobs.Script.Tests.csproj b/test/WebJobs.Script.Tests/WebJobs.Script.Tests.csproj index 1a820b0a78..e9e5ce4ec5 100644 --- a/test/WebJobs.Script.Tests/WebJobs.Script.Tests.csproj +++ b/test/WebJobs.Script.Tests/WebJobs.Script.Tests.csproj @@ -79,7 +79,7 @@ ..\..\packages\Microsoft.ApplicationInsights.2.4.0\lib\net46\Microsoft.ApplicationInsights.dll - ..\..\packages\Microsoft.Azure.AppService.Proxy.0.3.2.20\lib\net461\Microsoft.AspNet.Razor.dll + ..\..\packages\Microsoft.Azure.AppService.Proxy.1.0.0.1\lib\net461\Microsoft.AspNet.Razor.dll ..\..\packages\Microsoft.AspNet.WebHooks.Common.1.2.0\lib\net45\Microsoft.AspNet.WebHooks.Common.dll @@ -114,14 +114,14 @@ ..\..\packages\Microsoft.Azure.ApiHub.Sdk.0.7.2-alpha\lib\net45\Microsoft.Azure.ApiHub.Sdk.dll True - - ..\..\packages\Microsoft.Azure.AppService.Proxy.0.3.2.20\lib\net461\Microsoft.Azure.AppService.Proxy.Client.dll + + ..\..\packages\Microsoft.Azure.AppService.Proxy.1.0.0.1\lib\net461\Microsoft.Azure.AppService.Proxy.Client.dll - - ..\..\packages\Microsoft.Azure.AppService.Proxy.0.3.2.20\lib\net461\Microsoft.Azure.AppService.Proxy.Common.dll + + ..\..\packages\Microsoft.Azure.AppService.Proxy.1.0.0.1\lib\net461\Microsoft.Azure.AppService.Proxy.Common.dll - - ..\..\packages\Microsoft.Azure.AppService.Proxy.0.3.2.20\lib\net461\Microsoft.Azure.AppService.Proxy.Runtime.dll + + ..\..\packages\Microsoft.Azure.AppService.Proxy.1.0.0.1\lib\net461\Microsoft.Azure.AppService.Proxy.Runtime.dll ..\..\packages\Microsoft.Azure.DocumentDB.ChangeFeedProcessor.1.0.0\lib\net45\Microsoft.Azure.Documents.ChangeFeedProcessor.dll diff --git a/test/WebJobs.Script.Tests/packages.config b/test/WebJobs.Script.Tests/packages.config index 66d82b16de..94c72f0347 100644 --- a/test/WebJobs.Script.Tests/packages.config +++ b/test/WebJobs.Script.Tests/packages.config @@ -23,7 +23,7 @@ - +