Skip to content

Commit

Permalink
Merge pull request #5 from microsoftgraph/po/xamarinNariveHttpHandler
Browse files Browse the repository at this point in the history
Support native platform Http handlers for Xamarin.iOS and Xamarin.Android
  • Loading branch information
peombwa authored Jun 10, 2019
2 parents efa2b5c + 08d3653 commit 1f0d0f1
Show file tree
Hide file tree
Showing 54 changed files with 8,256 additions and 290 deletions.
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

0 comments on commit 1f0d0f1

Please sign in to comment.