Set User-Agent header to ZipDeploy task

Closes #301
This commit is contained in:
Phil Henning 2019-03-28 14:50:19 -07:00
Родитель 945283e98b
Коммит fb63139ca7
7 изменённых файлов: 57 добавлений и 14 удалений

Просмотреть файл

@ -1,11 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\src\Microsoft.NET.Sdk.Functions.MSBuild\Targets\netstandard1.0\ExtensionsMetadataGeneratorVersion.props" />
<Import Project="..\..\src\Microsoft.NET.Sdk.Functions.MSBuild\Targets\netstandard1.0\Microsoft.NET.Sdk.Functions.Version.props" />
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net46</TargetFrameworks>
<PackageName>Microsoft.NET.Sdk.Functions</PackageName>
<Version>1.0.27</Version>
<Version>$(FunctionsSdkVersion)</Version>
<Authors>Microsoft</Authors>
<ProjectUrl>https://github.com/Azure/azure-functions-vs-build-sdk</ProjectUrl>
<PackageProjectUrl>https://github.com/Azure/azure-functions-vs-build-sdk</PackageProjectUrl>

Просмотреть файл

@ -10,9 +10,10 @@ namespace Microsoft.NET.Sdk.Functions.Http
{
internal static class HttpClientHelpers
{
public static async Task<IHttpResponse> PostWithBasicAuthAsync(this IHttpClient client, Uri uri, string username, string password, string contentType, Encoding encoding, Stream messageBody)
public static async Task<IHttpResponse> PostWithBasicAuthAsync(this IHttpClient client, Uri uri, string username, string password, string contentType, string userAgent, Encoding encoding, Stream messageBody)
{
AddBasicAuthToClient(username, password, client);
client.DefaultRequestHeaders.Add("User-Agent", userAgent);
StreamContent content = new StreamContent(messageBody ?? new MemoryStream())
{

Просмотреть файл

@ -39,12 +39,17 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and
-->
<Target Name="ZipDeploy" DependsOnTargets="CreateZipFile">
<PropertyGroup>
<ZipDeployUserAgent Condition="'$(VisualStudioVersion)' == ''">$(FunctionsSdkVersion)</ZipDeployUserAgent>
<ZipDeployUserAgent Condition="'$(VisualStudioVersion)' != ''">$(FunctionsSdkVersion)_VisualStudio_$(VisualStudioVersion)</ZipDeployUserAgent>
</PropertyGroup>
<ZipDeployTask
ZipToPublishPath="$(ZippedPublishContentsPath)"
DeploymentUsername="$(UserName)"
DeploymentPassword="$(Password)"
SiteName="$(DeployIisAppPath)"
PublishUrl="$(PublishUrl)" />
PublishUrl="$(PublishUrl)"
UserAgentVersion="$(ZipDeployUserAgent)"/>
</Target>
</Project>

Просмотреть файл

@ -0,0 +1,17 @@
<!--
***********************************************************************************************
Microsoft.NET.Sdk.Functions.Version.props
WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
created a backup copy. Incorrect changes to this file will make it
impossible to load or build your projects from the command-line or the IDE.
***********************************************************************************************
-->
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<FunctionsSdkVersion>1.0.28</FunctionsSdkVersion>
</PropertyGroup>
</Project>

Просмотреть файл

@ -10,6 +10,13 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and
-->
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!--
***********************************************************************************************
Import the Version Props
***********************************************************************************************
-->
<Import Project="$(MSBuildThisFileDirectory)Microsoft.NET.Sdk.Functions.Version.props" Condition="Exists('$(MSBuildThisFileDirectory)Microsoft.NET.Sdk.Functions.Version.props')" />
<!--
***********************************************************************************************
Import the Build Props

Просмотреть файл

@ -11,6 +11,8 @@ namespace Microsoft.NET.Sdk.Functions.Tasks
{
public class ZipDeployTask : Task
{
private const string UserAgentName = "functions-core-tools";
[Required]
public string ZipToPublishPath { get; set; }
@ -20,8 +22,12 @@ namespace Microsoft.NET.Sdk.Functions.Tasks
[Required]
public string DeploymentPassword { get; set; }
[Required]
public string UserAgentVersion { get; set; }
public string PublishUrl { get; set; }
/// <summary>
/// Our fallback if PublishUrl is not given, which is the case for ZIP Deploy profiles created prior to 15.8 Preview 4.
/// Using this will fail if the site is a slot.
@ -32,13 +38,13 @@ namespace Microsoft.NET.Sdk.Functions.Tasks
{
using(DefaultHttpClient client = new DefaultHttpClient())
{
System.Threading.Tasks.Task<bool> t = ZipDeployAsync(ZipToPublishPath, DeploymentUsername, DeploymentPassword, PublishUrl, SiteName, client, true);
System.Threading.Tasks.Task<bool> t = ZipDeployAsync(ZipToPublishPath, DeploymentUsername, DeploymentPassword, PublishUrl, SiteName, UserAgentVersion, client, true);
t.Wait();
return t.Result;
}
}
internal async System.Threading.Tasks.Task<bool> ZipDeployAsync(string zipToPublishPath, string userName, string password, string publishUrl, string siteName, IHttpClient client, bool logMessages)
internal async System.Threading.Tasks.Task<bool> ZipDeployAsync(string zipToPublishPath, string userName, string password, string publishUrl, string siteName, string userAgentVersion, IHttpClient client, bool logMessages)
{
if (!File.Exists(zipToPublishPath) || client == null)
{
@ -77,10 +83,10 @@ namespace Microsoft.NET.Sdk.Functions.Tasks
Uri uri = new Uri(zipDeployPublishUrl, UriKind.Absolute);
FileStream stream = File.OpenRead(zipToPublishPath);
IHttpResponse response = await client.PostWithBasicAuthAsync(uri, userName, password, "application/zip", Encoding.UTF8, stream);
if(response.StatusCode != HttpStatusCode.OK && response.StatusCode != HttpStatusCode.Accepted)
IHttpResponse response = await client.PostWithBasicAuthAsync(uri, userName, password, "application/zip", $"{UserAgentName}/{userAgentVersion}", Encoding.UTF8, stream);
if (response.StatusCode != HttpStatusCode.OK && response.StatusCode != HttpStatusCode.Accepted)
{
if(logMessages)
if (logMessages)
{
Log.LogError(String.Format(Resources.ZipDeployFailureErrorMessage, zipDeployPublishUrl, response.StatusCode));
}

Просмотреть файл

@ -16,6 +16,8 @@ namespace ZipDeployPublish.Test
{
private static string _testZippedPublishContentsPath;
private static string TestAssemblyToTestZipPath = @"Resources\TestPublishContents.zip";
private static string UserAgentName = "functions-core-tools";
private static string UserAgentVersion = "1.0";
public static string TestZippedPublishContentsPath
{
@ -39,7 +41,7 @@ namespace ZipDeployPublish.Test
Mock<IHttpClient> client = new Mock<IHttpClient>();
ZipDeployTask zipDeployer = new ZipDeployTask();
bool result = await zipDeployer.ZipDeployAsync(string.Empty, "username", "password", "publishUrl", null, client.Object, false);
bool result = await zipDeployer.ZipDeployAsync(string.Empty, "username", "password", "publishUrl", null, "Foo", client.Object, false);
client.Verify(c => c.PostAsync(It.IsAny<Uri>(), It.IsAny<StreamContent>()), Times.Never);
Assert.False(result);
@ -62,10 +64,11 @@ namespace ZipDeployPublish.Test
It.Is<Uri>(uri => string.Equals(uri.AbsoluteUri, expectedZipDeployEndpoint, StringComparison.Ordinal)),
It.Is<StreamContent>(streamContent => IsStreamContentEqualToFileContent(streamContent, TestZippedPublishContentsPath))),
Times.Once);
Assert.Equal($"{UserAgentName}/{UserAgentVersion}", client.Object.DefaultRequestHeaders.GetValues("User-Agent").FirstOrDefault());
Assert.True(result);
};
await RunZipDeployAsyncTest(publishUrl, siteName, HttpStatusCode.OK, verifyStep);
await RunZipDeployAsyncTest(publishUrl, siteName, UserAgentVersion, HttpStatusCode.OK, verifyStep);
}
[Theory]
@ -81,10 +84,11 @@ namespace ZipDeployPublish.Test
It.IsAny<Uri>(),
It.IsAny<StreamContent>()),
Times.Never);
Assert.False(client.Object.DefaultRequestHeaders.TryGetValues("User-Agent", out _));
Assert.False(result);
};
await RunZipDeployAsyncTest(publishUrl, siteName, HttpStatusCode.OK, verifyStep);
await RunZipDeployAsyncTest(publishUrl, siteName, UserAgentVersion, HttpStatusCode.OK, verifyStep);
}
[Theory]
@ -96,19 +100,21 @@ namespace ZipDeployPublish.Test
[InlineData(HttpStatusCode.InternalServerError, false)]
public async Task ExecuteZipDeploy_VaryingHttpResponseStatuses(HttpStatusCode responseStatusCode, bool expectedResult)
{
;
Action<Mock<IHttpClient>, bool> verifyStep = (client, result) =>
{
client.Verify(c => c.PostAsync(
It.Is<Uri>(uri => string.Equals(uri.AbsoluteUri, "https://sitename.scm.azurewebsites.net/api/zipdeploy", StringComparison.Ordinal)),
It.Is<StreamContent>(streamContent => IsStreamContentEqualToFileContent(streamContent, TestZippedPublishContentsPath))),
Times.Once);
Assert.Equal($"{UserAgentName}/{UserAgentVersion}", client.Object.DefaultRequestHeaders.GetValues("User-Agent").FirstOrDefault());
Assert.Equal(expectedResult, result);
};
await RunZipDeployAsyncTest("https://sitename.scm.azurewebsites.net", null, responseStatusCode, verifyStep);
await RunZipDeployAsyncTest("https://sitename.scm.azurewebsites.net", null, UserAgentVersion, responseStatusCode, verifyStep);
}
private async Task RunZipDeployAsyncTest(string publishUrl, string siteName, HttpStatusCode responseStatusCode, Action<Mock<IHttpClient>, bool> verifyStep)
private async Task RunZipDeployAsyncTest(string publishUrl, string siteName, string userAgentVersion, HttpStatusCode responseStatusCode, Action<Mock<IHttpClient>, bool> verifyStep)
{
Mock<IHttpClient> client = new Mock<IHttpClient>();
@ -133,7 +139,7 @@ namespace ZipDeployPublish.Test
ZipDeployTask zipDeployer = new ZipDeployTask();
bool result = await zipDeployer.ZipDeployAsync(TestZippedPublishContentsPath, "username", "password", publishUrl, siteName, client.Object, false);
bool result = await zipDeployer.ZipDeployAsync(TestZippedPublishContentsPath, "username", "password", publishUrl, siteName, userAgentVersion, client.Object, false);
verifyStep(client, result);
}