Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support native platform Http handlers for Xamarin.iOS and Xamarin.Android #5

Merged
merged 10 commits into from
Jun 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions Microsoft.Graph.Core.sln
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Graph.Core", "src
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Graph.DotnetCore.Core.Test", "tests\Microsoft.Graph.DotnetCore.Core.Test\Microsoft.Graph.DotnetCore.Core.Test.csproj", "{A337BD4B-5C76-4BC5-8EC2-2EE7B834D030}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Graph.Core.XamarinAndroid.Test", "tests\Microsoft.Graph.Core.XamarinAndroid.Test\Microsoft.Graph.Core.XamarinAndroid.Test.csproj", "{41E25C28-021A-4CFB-B02D-DB901021E720}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -54,13 +56,38 @@ Global
{A337BD4B-5C76-4BC5-8EC2-2EE7B834D030}.Release|x64.Build.0 = Release|Any CPU
{A337BD4B-5C76-4BC5-8EC2-2EE7B834D030}.Release|x86.ActiveCfg = Release|Any CPU
{A337BD4B-5C76-4BC5-8EC2-2EE7B834D030}.Release|x86.Build.0 = Release|Any CPU
{41E25C28-021A-4CFB-B02D-DB901021E720}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{41E25C28-021A-4CFB-B02D-DB901021E720}.Debug|Any CPU.Build.0 = Debug|Any CPU
{41E25C28-021A-4CFB-B02D-DB901021E720}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{41E25C28-021A-4CFB-B02D-DB901021E720}.Debug|ARM.ActiveCfg = Debug|Any CPU
{41E25C28-021A-4CFB-B02D-DB901021E720}.Debug|ARM.Build.0 = Debug|Any CPU
{41E25C28-021A-4CFB-B02D-DB901021E720}.Debug|ARM.Deploy.0 = Debug|Any CPU
{41E25C28-021A-4CFB-B02D-DB901021E720}.Debug|x64.ActiveCfg = Debug|Any CPU
{41E25C28-021A-4CFB-B02D-DB901021E720}.Debug|x64.Build.0 = Debug|Any CPU
{41E25C28-021A-4CFB-B02D-DB901021E720}.Debug|x64.Deploy.0 = Debug|Any CPU
{41E25C28-021A-4CFB-B02D-DB901021E720}.Debug|x86.ActiveCfg = Debug|Any CPU
{41E25C28-021A-4CFB-B02D-DB901021E720}.Debug|x86.Build.0 = Debug|Any CPU
{41E25C28-021A-4CFB-B02D-DB901021E720}.Debug|x86.Deploy.0 = Debug|Any CPU
{41E25C28-021A-4CFB-B02D-DB901021E720}.Release|Any CPU.ActiveCfg = Release|Any CPU
{41E25C28-021A-4CFB-B02D-DB901021E720}.Release|Any CPU.Build.0 = Release|Any CPU
{41E25C28-021A-4CFB-B02D-DB901021E720}.Release|Any CPU.Deploy.0 = Release|Any CPU
{41E25C28-021A-4CFB-B02D-DB901021E720}.Release|ARM.ActiveCfg = Release|Any CPU
{41E25C28-021A-4CFB-B02D-DB901021E720}.Release|ARM.Build.0 = Release|Any CPU
{41E25C28-021A-4CFB-B02D-DB901021E720}.Release|ARM.Deploy.0 = Release|Any CPU
{41E25C28-021A-4CFB-B02D-DB901021E720}.Release|x64.ActiveCfg = Release|Any CPU
{41E25C28-021A-4CFB-B02D-DB901021E720}.Release|x64.Build.0 = Release|Any CPU
{41E25C28-021A-4CFB-B02D-DB901021E720}.Release|x64.Deploy.0 = Release|Any CPU
{41E25C28-021A-4CFB-B02D-DB901021E720}.Release|x86.ActiveCfg = Release|Any CPU
{41E25C28-021A-4CFB-B02D-DB901021E720}.Release|x86.Build.0 = Release|Any CPU
{41E25C28-021A-4CFB-B02D-DB901021E720}.Release|x86.Deploy.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{9F04608C-D845-4445-83B1-E6D4EEE38CBC} = {5E0B65FC-67B7-41F8-87BF-96D6A342C438}
{A337BD4B-5C76-4BC5-8EC2-2EE7B834D030} = {6496B661-8321-4D07-ACC2-B6602649293C}
{41E25C28-021A-4CFB-B02D-DB901021E720} = {6496B661-8321-4D07-ACC2-B6602649293C}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0DB06E6E-58F0-497F-9ECC-00DD03BA9357}
Expand Down
3 changes: 3 additions & 0 deletions src/Microsoft.Graph.Core/CoreConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ public static class Headers
/// </summary>
public static class MimeTypeNames
{
/// <summary>
/// MimeTypeNames.Application constants.
/// </summary>
public static class Application
{
/// JSON content type value
Expand Down
4 changes: 2 additions & 2 deletions src/Microsoft.Graph.Core/Extensions/BaseRequestExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,13 @@ public static T WithPerRequestAuthProvider<T>(this T baseRequest) where T : IBas
}

/// <summary>
/// Sets a ShouldRetry <see cref="Func{HttpResponseMessage httpResponseMessage, Boolean}"/> delegate to the default Retry Middleware Handler for this request.
/// Sets a ShouldRetry delegate to the default Retry Middleware Handler for this request.
/// This only works with the default Retry Middleware Handler.
/// If you use a custom Retry Middleware Handler, you have to handle it's retreival in your implementation.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="baseRequest">The <see cref="BaseRequest"/> for the request.</param>
/// <param name="shouldRetry">A <see cref="Func{HttpResponseMessage, Boolean}"/> for the request.</param>
/// <param name="shouldRetry">A <see cref="Func{Int32, Int32, HttpResponseMessage, Boolean}"/> for the request.</param>
/// <returns></returns>
public static T WithShouldRetry<T>(this T baseRequest, Func<int, int, HttpResponseMessage, bool> shouldRetry) where T : IBaseRequest
{
Expand Down
55 changes: 46 additions & 9 deletions src/Microsoft.Graph.Core/Microsoft.Graph.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<Copyright>&#169; Microsoft Corporation. All rights reserved.</Copyright>
<AssemblyTitle>Microsoft Graph Core Client Library</AssemblyTitle>
<Authors>Microsoft</Authors>
<TargetFrameworks>netstandard1.1;net45</TargetFrameworks>
<TargetFrameworks>netstandard1.1;net45;Xamarin.iOS10;MonoAndroid70</TargetFrameworks>
<PreserveCompilationContext>false</PreserveCompilationContext>
<AssemblyName>Microsoft.Graph.Core</AssemblyName>
<PackageId>Microsoft.Graph.Core</PackageId>
Expand All @@ -21,10 +21,28 @@
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<VersionPrefix>1.16.0</VersionPrefix>
<VersionSuffix></VersionSuffix>
<PackageReleaseNotes>- Retry handler handles 504.
- Fix #470. Keep StreamWriter open for NetCore 2.x.
<PackageReleaseNotes>
- Fix #481. Use native HTTP client handlers for Xamarin.iOS and Xamarin.Android.
- Fix #482. Skip CompressionHandler when NSUrlSessionHandler is used.
</PackageReleaseNotes>
</PropertyGroup>
<!--We manually configure LanguageTargets for Xamarin due to .Net SDK TFMs limitation https://github.com/dotnet/sdk/issues/491 -->
<PropertyGroup Condition="'$(TargetFramework)' == 'Xamarin.iOS10'">
<TargetFrameworkIdentifier>Xamarin.iOS</TargetFrameworkIdentifier>
<TargetFrameworkVersion>v1.0</TargetFrameworkVersion>
<DefineConstants>$(DefineConstants);iOS</DefineConstants>
<DebugType>full</DebugType>
<LanguageTargets>$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets</LanguageTargets>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'MonoAndroid70'">
<TargetFrameworkIdentifier>MonoAndroid</TargetFrameworkIdentifier>
<TargetFrameworkVersion>v7.0</TargetFrameworkVersion>
<AndroidUseLatestPlatformSdk>False</AndroidUseLatestPlatformSdk>
<DebugType>full</DebugType>
<DefineConstants>$(DefineConstants);ANDROID</DefineConstants>
<LanguageTargets>$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets</LanguageTargets>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|netstandard1.1|AnyCPU'">
<DocumentationFile>bin\Release\netstandard1.1\Microsoft.Graph.Core.xml</DocumentationFile>
<NoWarn>1701;1702;1705;1591</NoWarn>
Expand All @@ -38,23 +56,42 @@
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net45|AnyCPU'">
<DocumentationFile>bin\Debug\net45\Microsoft.Graph.xml</DocumentationFile>
</PropertyGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net45' ">
<Reference Include="System.Net.Http" />
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
<PackageReference Include="Newtonsoft.Json" Version="6.0.1" />
<PackageReference Include="System.ValueTuple" Version="4.3.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.1' ">
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
<PackageReference Include="System.Net.Http" Version="4.3.3" />
<PackageReference Include="System.ValueTuple" Version="4.3.0" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\LICENSE.txt">
<Pack>True</Pack>
<PackagePath></PackagePath>
</None>
<ItemGroup Condition=" '$(TargetFramework)' == 'Xamarin.iOS10' ">
<Reference Include="Xamarin.iOS" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.1" />
<PackageReference Include="System.Net.Http" Version="4.3.3" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'MonoAndroid70' ">
<Reference Include="Mono.Android" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.1" />
<PackageReference Include="System.Net.Http" Version="4.3.3" />
<PackageReference Include="System.ValueTuple" Version="4.3.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.ValueTuple" Version="4.3.0" />
<None Include="..\..\LICENSE.txt">
<Pack>True</Pack>
<PackagePath></PackagePath>
</None>
</ItemGroup>
</Project>
11 changes: 11 additions & 0 deletions src/Microsoft.Graph.Core/Requests/Content/BatchRequestContent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,12 @@ private string GetRelativeUrl(Uri requestUri)
return requestUri.AbsoluteUri.Substring(requestUri.AbsoluteUri.IndexOf(version) + version.ToCharArray().Count());
}

/// <summary>
/// Serialize the HTTP content to a stream as an asynchronous operation.
/// </summary>
/// <param name="stream">The target stream.</param>
/// <param name="context">Information about the transport (channel binding token, for example). This parameter may be null.</param>
/// <returns></returns>
protected override async Task SerializeToStreamAsync(Stream stream, TransportContext context)
{
using (StreamWriter streamWritter = new StreamWriter(stream, new UTF8Encoding(), 1024, true))
Expand All @@ -218,6 +224,11 @@ protected override async Task SerializeToStreamAsync(Stream stream, TransportCon
}
}

/// <summary>
/// Determines whether the HTTP content has a valid length in bytes.
/// </summary>
/// <param name="length">The length in bytes of the HHTP content.</param>
/// <returns></returns>
protected override bool TryComputeLength(out long length)
{
length = -1;
Expand Down
22 changes: 11 additions & 11 deletions src/Microsoft.Graph.Core/Requests/FeatureFlag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,25 @@ namespace Microsoft.Graph
[Flags]
public enum FeatureFlag
{
// None set
/// None set
None = 0x00000000,
// Redirect Handler
/// Redirect Handler
RedirectHandler = 0x00000001,
// Retry Handler
/// Retry Handler
RetryHandler = 0x00000002,
// Auth Handler
/// Auth Handler
AuthHandler = 0x00000004,
// Default Handler
/// Default Handler
DefaultHttpProvider = 0x00000008,
// Logging Handler
/// Logging Handler
LoggingHandler = 0x00000010,
// Service Discovery Handler
/// Service Discovery Handler
ServiceDiscoveryHandler = 0x00000020,
// Compression Handler
/// Compression Handler
CompressionHandler = 0x00000040,
// Connection Pool Manager
/// Connection Pool Manager
ConnectionPoolManager = 0x00000080,
// Long Running Operation Handler
LongRunnungOperationHandler = 0x00000100
/// Long Running Operation Handler
LongRunningOperationHandler = 0x00000100
}
}
58 changes: 53 additions & 5 deletions src/Microsoft.Graph.Core/Requests/GraphClientFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ namespace Microsoft.Graph
using System.Net.Http;
using System.Reflection;
using System.Net.Http.Headers;

/// <summary>
/// GraphClientFactory class to create the HTTP client
/// </summary>
Expand Down Expand Up @@ -93,11 +92,17 @@ public static HttpClient Create(
HttpMessageHandler finalHandler = null)
{
if (finalHandler == null)
finalHandler = new HttpClientHandler { Proxy = proxy, AllowAutoRedirect = false };
{
finalHandler = GetNativePlatformHttpHandler(proxy);
}
else if ((finalHandler is HttpClientHandler) && (finalHandler as HttpClientHandler).Proxy == null && proxy != null)
{
(finalHandler as HttpClientHandler).Proxy = proxy;
}
else if ((finalHandler is HttpClientHandler) && (finalHandler as HttpClientHandler).Proxy != null && proxy != null)
{
throw new ArgumentException(ErrorConstants.Messages.InvalidProxyArgument);
}

var pipelineWithFlags = CreatePipelineWithFeatureFlags(handlers, finalHandler);
HttpClient client = new HttpClient(pipelineWithFlags.Pipeline);
Expand Down Expand Up @@ -156,14 +161,21 @@ internal static (HttpMessageHandler Pipeline, FeatureFlag FeatureFlags) CreatePi
FeatureFlag handlerFlags = FeatureFlag.None;
if (finalHandler == null)
{
finalHandler = new HttpClientHandler { AllowAutoRedirect = false };
finalHandler = GetNativePlatformHttpHandler();
}

if (handlers == null)
{
return (Pipeline: finalHandler, FeatureFlags: handlerFlags);
}

#if iOS
// Remove CompressionHandler because NSUrlSessionHandler automatically handles decompression and it can't be turned off.
// See issue https://github.com/microsoftgraph/msgraph-sdk-dotnet/issues/481 for more details.
if (finalHandler.GetType() == typeof(NSUrlSessionHandler))
{
RemoveHandler(handlers.ToList(), typeof(CompressionHandler));
}
#endif
HttpMessageHandler httpPipeline = finalHandler;
IEnumerable<DelegatingHandler> reversedHandlers = handlers.Reverse();
HashSet<Type> existingHandlerTypes = new HashSet<Type>();
Expand All @@ -179,7 +191,7 @@ internal static (HttpMessageHandler Pipeline, FeatureFlag FeatureFlags) CreatePi
throw new ArgumentException(String.Format("DelegatingHandler array has unexpected InnerHandler. {0} has unexpected InnerHandler.", handler, "handler"));
}

// Add duplicate check based on handler type.
// Check for duplicate handler by type.
if (!existingHandlerTypes.Add(handler.GetType()))
throw new ArgumentException($"DelegatingHandler array has a duplicate handler. {handler} has a duplicate handler.", "handlers");

Expand All @@ -193,6 +205,42 @@ internal static (HttpMessageHandler Pipeline, FeatureFlag FeatureFlags) CreatePi
return (Pipeline: httpPipeline, FeatureFlags: handlerFlags);
}

/// <summary>
/// Gets a platform's native http handler i.e. NSUrlSessionHandler for Xamarin.iOS, AndroidClientHandler for Xamarin.Android and HttpClientHandler for others.
/// </summary>
/// <param name="proxy">The proxy to be used with created client.</param>
/// <returns>
/// 1. NSUrlSessionHandler for Xamarin.iOS
/// 2. AndroidClientHandler for Xamarin.Android.
/// 3. HttpClientHandler for other platforms.
/// </returns>
internal static HttpMessageHandler GetNativePlatformHttpHandler(IWebProxy proxy = null)
{
#if iOS
return new NSUrlSessionHandler { AllowAutoRedirect = false };
#elif ANDROID
return new Xamarin.Android.Net.AndroidClientHandler { Proxy = proxy, AllowAutoRedirect = false, AutomaticDecompression = DecompressionMethods.None };
#else
return new HttpClientHandler { Proxy = proxy, AllowAutoRedirect = false, AutomaticDecompression = DecompressionMethods.None };
#endif
}

/// <summary>
/// Removes the specified targetHandlerType from the provided list of delegatingHandlers.
/// </summary>
/// <param name="delegatingHandlers">The list of <see cref="DelegatingHandler"/> to remove a <see cref="DelegatingHandler"/> type from.</param>
/// <param name="targetHandlerType">The <see cref="DelegatingHandler"/> type to remove.</param>
/// <returns></returns>
internal static bool RemoveHandler(IList<DelegatingHandler> delegatingHandlers, Type targetHandlerType)
{
if (delegatingHandlers == null)
{
throw new ArgumentNullException(nameof(delegatingHandlers), "DelegatingHandler list is null.");
}

return delegatingHandlers.Remove(delegatingHandlers.FirstOrDefault((h) => h.GetType().Equals(targetHandlerType)));
}

/// <summary>
/// Gets feature flag for the specified handler.
/// </summary>
Expand Down
4 changes: 2 additions & 2 deletions src/Microsoft.Graph.Core/Requests/HttpProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ public HttpProvider(HttpMessageHandler httpMessageHandler, bool disposeHandler,
// This check won't be needed once we re-write the HttpProvider to work with GraphClientFactory.
if (this.httpMessageHandler == null)
{
this.httpMessageHandler = new HttpClientHandler { AllowAutoRedirect = false };
this.httpClient = GraphClientFactory.Create(authenticationProvider: null, version: "v1.0", nationalCloud: GraphClientFactory.Global_Cloud, finalHandler: httpMessageHandler);
this.httpMessageHandler = GraphClientFactory.GetNativePlatformHttpHandler();
this.httpClient = GraphClientFactory.Create(authenticationProvider: null, version: "v1.0", nationalCloud: GraphClientFactory.Global_Cloud, finalHandler: this.httpMessageHandler);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace Microsoft.Graph
using System.Net.Http.Headers;

/// <summary>
/// An <see cref="DelegatingHandler"/> implementation using standard .NET libraries.
/// A <see cref="DelegatingHandler"/> implementation using standard .NET libraries.
/// </summary>
public class RetryHandler : DelegatingHandler
{
Expand Down
8 changes: 7 additions & 1 deletion src/Microsoft.Graph.Core/Requests/ResponseHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,16 @@ namespace Microsoft.Graph
using System.Net.Http;
using System.Threading.Tasks;

/// <summary>
/// Provides method(s) to deserialize raw HTTP responses into strong types.
/// </summary>
public class ResponseHandler
{
private readonly ISerializer serializer;

/// <summary>
/// Constructs a new <see cref="ResponseHandler"/>.
/// </summary>
/// <param name="serializer"></param>
public ResponseHandler(ISerializer serializer)
{
this.serializer = serializer;
Expand Down
4 changes: 2 additions & 2 deletions src/Microsoft.Graph.Core/Tasks/PageIterator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
using System.Threading;
using System.Threading.Tasks;

/**
/*
Spec
https://github.com/microsoftgraph/msgraph-sdk-design/blob/master/tasks/PageIteratorTask.md
**/
*/

namespace Microsoft.Graph
{
Expand Down
Loading