@azure-typespec/http-client-csharp-mgmt 1.0.0-alpha.20250409.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/emitter/emitter.d.ts +4 -0
- package/dist/emitter/emitter.d.ts.map +1 -0
- package/dist/emitter/emitter.js +77 -0
- package/dist/emitter/emitter.js.map +1 -0
- package/dist/emitter/index.d.ts +2 -0
- package/dist/emitter/index.d.ts.map +1 -0
- package/dist/emitter/index.js +4 -0
- package/dist/emitter/index.js.map +1 -0
- package/dist/emitter/resource-type.d.ts +2 -0
- package/dist/emitter/resource-type.d.ts.map +1 -0
- package/dist/emitter/resource-type.js +31 -0
- package/dist/emitter/resource-type.js.map +1 -0
- package/dist/emitter/sdk-context-options.d.ts +3 -0
- package/dist/emitter/sdk-context-options.d.ts.map +1 -0
- package/dist/emitter/sdk-context-options.js +23 -0
- package/dist/emitter/sdk-context-options.js.map +1 -0
- package/dist/generator/Azure.Core.dll +0 -0
- package/dist/generator/Azure.Generator.Mgmt.deps.json +998 -0
- package/dist/generator/Azure.Generator.Mgmt.dll +0 -0
- package/dist/generator/Azure.Generator.Mgmt.pdb +0 -0
- package/dist/generator/Azure.Generator.Mgmt.xml +818 -0
- package/dist/generator/Azure.Generator.dll +0 -0
- package/dist/generator/Azure.Generator.pdb +0 -0
- package/dist/generator/Azure.Generator.xml +163 -0
- package/dist/generator/Azure.ResourceManager.dll +0 -0
- package/dist/generator/CommandLine.dll +0 -0
- package/dist/generator/Humanizer.dll +0 -0
- package/dist/generator/Microsoft.Bcl.AsyncInterfaces.dll +0 -0
- package/dist/generator/Microsoft.Build.Framework.dll +0 -0
- package/dist/generator/Microsoft.Build.dll +0 -0
- package/dist/generator/Microsoft.CodeAnalysis.CSharp.Workspaces.dll +0 -0
- package/dist/generator/Microsoft.CodeAnalysis.CSharp.dll +0 -0
- package/dist/generator/Microsoft.CodeAnalysis.Workspaces.dll +0 -0
- package/dist/generator/Microsoft.CodeAnalysis.dll +0 -0
- package/dist/generator/Microsoft.Extensions.Logging.Abstractions.dll +0 -0
- package/dist/generator/Microsoft.NET.StringTools.dll +0 -0
- package/dist/generator/Microsoft.TypeSpec.Generator.ClientModel.dll +0 -0
- package/dist/generator/Microsoft.TypeSpec.Generator.Input.dll +0 -0
- package/dist/generator/Microsoft.TypeSpec.Generator.dll +0 -0
- package/dist/generator/Microsoft.TypeSpec.Generator.runtimeconfig.json +12 -0
- package/dist/generator/NuGet.Common.dll +0 -0
- package/dist/generator/NuGet.Configuration.dll +0 -0
- package/dist/generator/NuGet.Frameworks.dll +0 -0
- package/dist/generator/Shared/Core/AppContextSwitchHelper.cs +42 -0
- package/dist/generator/Shared/Core/AsyncLockWithValue.cs +260 -0
- package/dist/generator/Shared/Core/AzureKeyCredentialPolicy.cs +50 -0
- package/dist/generator/Shared/Core/ClientDiagnostics.cs +73 -0
- package/dist/generator/Shared/Core/DiagnosticScope.cs +473 -0
- package/dist/generator/Shared/Core/DiagnosticScopeFactory.cs +104 -0
- package/dist/generator/Shared/Core/FixedDelayWithNoJitterStrategy.cs +26 -0
- package/dist/generator/Shared/Core/HttpMessageSanitizer.cs +198 -0
- package/dist/generator/Shared/Core/IOperationSource.cs +14 -0
- package/dist/generator/Shared/Core/NextLinkOperationImplementation.cs +690 -0
- package/dist/generator/Shared/Core/OperationFinalStateVia.cs +16 -0
- package/dist/generator/Shared/Core/OperationInternal.cs +256 -0
- package/dist/generator/Shared/Core/OperationInternalBase.cs +234 -0
- package/dist/generator/Shared/Core/OperationInternalOfT.cs +422 -0
- package/dist/generator/Shared/Core/OperationPoller.cs +114 -0
- package/dist/generator/Shared/Core/RawRequestUriBuilder.cs +192 -0
- package/dist/generator/Shared/Core/SequentialDelayStrategy.cs +38 -0
- package/dist/generator/Shared/Core/TaskExtensions.cs +313 -0
- package/dist/generator/Shared/Core/VoidValue.cs +10 -0
- package/dist/generator/System.ClientModel.dll +0 -0
- package/dist/generator/System.ComponentModel.Composition.dll +0 -0
- package/dist/generator/System.Composition.AttributedModel.dll +0 -0
- package/dist/generator/System.Composition.Convention.dll +0 -0
- package/dist/generator/System.Composition.Hosting.dll +0 -0
- package/dist/generator/System.Composition.Runtime.dll +0 -0
- package/dist/generator/System.Composition.TypedParts.dll +0 -0
- package/dist/generator/System.Configuration.ConfigurationManager.dll +0 -0
- package/dist/generator/System.Diagnostics.EventLog.dll +0 -0
- package/dist/generator/System.IO.Pipelines.dll +0 -0
- package/dist/generator/System.Memory.Data.dll +0 -0
- package/dist/generator/System.Reflection.MetadataLoadContext.dll +0 -0
- package/dist/generator/System.Security.Cryptography.ProtectedData.dll +0 -0
- package/dist/generator/cs/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/dist/generator/cs/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/dist/generator/cs/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/dist/generator/cs/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/dist/generator/de/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/dist/generator/de/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/dist/generator/de/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/dist/generator/de/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/dist/generator/es/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/dist/generator/es/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/dist/generator/es/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/dist/generator/es/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/dist/generator/fr/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/dist/generator/fr/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/dist/generator/fr/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/dist/generator/fr/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/dist/generator/it/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/dist/generator/it/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/dist/generator/it/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/dist/generator/it/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/dist/generator/ja/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/dist/generator/ja/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/dist/generator/ja/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/dist/generator/ja/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/dist/generator/ko/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/dist/generator/ko/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/dist/generator/ko/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/dist/generator/ko/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/dist/generator/net8.0/Azure.Core.dll +0 -0
- package/dist/generator/net8.0/Azure.Generator.Mgmt.deps.json +998 -0
- package/dist/generator/net8.0/Azure.Generator.Mgmt.dll +0 -0
- package/dist/generator/net8.0/Azure.Generator.Mgmt.pdb +0 -0
- package/dist/generator/net8.0/Azure.Generator.Mgmt.xml +818 -0
- package/dist/generator/net8.0/Azure.Generator.dll +0 -0
- package/dist/generator/net8.0/Azure.Generator.pdb +0 -0
- package/dist/generator/net8.0/Azure.Generator.xml +163 -0
- package/dist/generator/net8.0/Azure.ResourceManager.dll +0 -0
- package/dist/generator/net8.0/CommandLine.dll +0 -0
- package/dist/generator/net8.0/Humanizer.dll +0 -0
- package/dist/generator/net8.0/Microsoft.Bcl.AsyncInterfaces.dll +0 -0
- package/dist/generator/net8.0/Microsoft.Build.Framework.dll +0 -0
- package/dist/generator/net8.0/Microsoft.Build.dll +0 -0
- package/dist/generator/net8.0/Microsoft.CodeAnalysis.CSharp.Workspaces.dll +0 -0
- package/dist/generator/net8.0/Microsoft.CodeAnalysis.CSharp.dll +0 -0
- package/dist/generator/net8.0/Microsoft.CodeAnalysis.Workspaces.dll +0 -0
- package/dist/generator/net8.0/Microsoft.CodeAnalysis.dll +0 -0
- package/dist/generator/net8.0/Microsoft.Extensions.Logging.Abstractions.dll +0 -0
- package/dist/generator/net8.0/Microsoft.NET.StringTools.dll +0 -0
- package/dist/generator/net8.0/Microsoft.TypeSpec.Generator.ClientModel.dll +0 -0
- package/dist/generator/net8.0/Microsoft.TypeSpec.Generator.Input.dll +0 -0
- package/dist/generator/net8.0/Microsoft.TypeSpec.Generator.dll +0 -0
- package/dist/generator/net8.0/NuGet.Common.dll +0 -0
- package/dist/generator/net8.0/NuGet.Configuration.dll +0 -0
- package/dist/generator/net8.0/NuGet.Frameworks.dll +0 -0
- package/dist/generator/net8.0/Shared/Core/AppContextSwitchHelper.cs +42 -0
- package/dist/generator/net8.0/Shared/Core/AsyncLockWithValue.cs +260 -0
- package/dist/generator/net8.0/Shared/Core/AzureKeyCredentialPolicy.cs +50 -0
- package/dist/generator/net8.0/Shared/Core/ClientDiagnostics.cs +73 -0
- package/dist/generator/net8.0/Shared/Core/DiagnosticScope.cs +473 -0
- package/dist/generator/net8.0/Shared/Core/DiagnosticScopeFactory.cs +104 -0
- package/dist/generator/net8.0/Shared/Core/FixedDelayWithNoJitterStrategy.cs +26 -0
- package/dist/generator/net8.0/Shared/Core/HttpMessageSanitizer.cs +198 -0
- package/dist/generator/net8.0/Shared/Core/IOperationSource.cs +14 -0
- package/dist/generator/net8.0/Shared/Core/NextLinkOperationImplementation.cs +690 -0
- package/dist/generator/net8.0/Shared/Core/OperationFinalStateVia.cs +16 -0
- package/dist/generator/net8.0/Shared/Core/OperationInternal.cs +256 -0
- package/dist/generator/net8.0/Shared/Core/OperationInternalBase.cs +234 -0
- package/dist/generator/net8.0/Shared/Core/OperationInternalOfT.cs +422 -0
- package/dist/generator/net8.0/Shared/Core/OperationPoller.cs +114 -0
- package/dist/generator/net8.0/Shared/Core/RawRequestUriBuilder.cs +192 -0
- package/dist/generator/net8.0/Shared/Core/SequentialDelayStrategy.cs +38 -0
- package/dist/generator/net8.0/Shared/Core/TaskExtensions.cs +313 -0
- package/dist/generator/net8.0/Shared/Core/VoidValue.cs +10 -0
- package/dist/generator/net8.0/System.ClientModel.dll +0 -0
- package/dist/generator/net8.0/System.ComponentModel.Composition.dll +0 -0
- package/dist/generator/net8.0/System.Composition.AttributedModel.dll +0 -0
- package/dist/generator/net8.0/System.Composition.Convention.dll +0 -0
- package/dist/generator/net8.0/System.Composition.Hosting.dll +0 -0
- package/dist/generator/net8.0/System.Composition.Runtime.dll +0 -0
- package/dist/generator/net8.0/System.Composition.TypedParts.dll +0 -0
- package/dist/generator/net8.0/System.Configuration.ConfigurationManager.dll +0 -0
- package/dist/generator/net8.0/System.Diagnostics.EventLog.dll +0 -0
- package/dist/generator/net8.0/System.IO.Pipelines.dll +0 -0
- package/dist/generator/net8.0/System.Memory.Data.dll +0 -0
- package/dist/generator/net8.0/System.Reflection.MetadataLoadContext.dll +0 -0
- package/dist/generator/net8.0/System.Security.Cryptography.ProtectedData.dll +0 -0
- package/dist/generator/net8.0/cs/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/dist/generator/net8.0/cs/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/dist/generator/net8.0/cs/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/dist/generator/net8.0/cs/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/dist/generator/net8.0/de/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/dist/generator/net8.0/de/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/dist/generator/net8.0/de/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/dist/generator/net8.0/de/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/dist/generator/net8.0/es/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/dist/generator/net8.0/es/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/dist/generator/net8.0/es/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/dist/generator/net8.0/es/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/dist/generator/net8.0/fr/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/dist/generator/net8.0/fr/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/dist/generator/net8.0/fr/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/dist/generator/net8.0/fr/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/dist/generator/net8.0/it/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/dist/generator/net8.0/it/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/dist/generator/net8.0/it/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/dist/generator/net8.0/it/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/dist/generator/net8.0/ja/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/dist/generator/net8.0/ja/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/dist/generator/net8.0/ja/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/dist/generator/net8.0/ja/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/dist/generator/net8.0/ko/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/dist/generator/net8.0/ko/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/dist/generator/net8.0/ko/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/dist/generator/net8.0/ko/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/dist/generator/net8.0/pl/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/dist/generator/net8.0/pl/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/dist/generator/net8.0/pl/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/dist/generator/net8.0/pl/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/dist/generator/net8.0/pt-BR/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/dist/generator/net8.0/pt-BR/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/dist/generator/net8.0/pt-BR/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/dist/generator/net8.0/pt-BR/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/dist/generator/net8.0/ru/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/dist/generator/net8.0/ru/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/dist/generator/net8.0/ru/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/dist/generator/net8.0/ru/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/dist/generator/net8.0/runtimes/win/lib/net8.0/System.Diagnostics.EventLog.Messages.dll +0 -0
- package/dist/generator/net8.0/runtimes/win/lib/net8.0/System.Diagnostics.EventLog.dll +0 -0
- package/dist/generator/net8.0/tr/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/dist/generator/net8.0/tr/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/dist/generator/net8.0/tr/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/dist/generator/net8.0/tr/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/dist/generator/net8.0/zh-Hans/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/dist/generator/net8.0/zh-Hans/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/dist/generator/net8.0/zh-Hans/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/dist/generator/net8.0/zh-Hans/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/dist/generator/net8.0/zh-Hant/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/dist/generator/net8.0/zh-Hant/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/dist/generator/net8.0/zh-Hant/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/dist/generator/net8.0/zh-Hant/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/dist/generator/pl/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/dist/generator/pl/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/dist/generator/pl/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/dist/generator/pl/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/dist/generator/pt-BR/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/dist/generator/pt-BR/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/dist/generator/pt-BR/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/dist/generator/pt-BR/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/dist/generator/ru/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/dist/generator/ru/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/dist/generator/ru/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/dist/generator/ru/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/dist/generator/runtimes/win/lib/net8.0/System.Diagnostics.EventLog.Messages.dll +0 -0
- package/dist/generator/runtimes/win/lib/net8.0/System.Diagnostics.EventLog.dll +0 -0
- package/dist/generator/tr/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/dist/generator/tr/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/dist/generator/tr/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/dist/generator/tr/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/dist/generator/zh-Hans/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/dist/generator/zh-Hans/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/dist/generator/zh-Hans/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/dist/generator/zh-Hans/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/dist/generator/zh-Hant/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +0 -0
- package/dist/generator/zh-Hant/Microsoft.CodeAnalysis.CSharp.resources.dll +0 -0
- package/dist/generator/zh-Hant/Microsoft.CodeAnalysis.Workspaces.resources.dll +0 -0
- package/dist/generator/zh-Hant/Microsoft.CodeAnalysis.resources.dll +0 -0
- package/package.json +67 -0
|
@@ -0,0 +1,690 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
#nullable enable
|
|
5
|
+
|
|
6
|
+
using System;
|
|
7
|
+
using System.ClientModel.Primitives;
|
|
8
|
+
using System.Collections.Generic;
|
|
9
|
+
using System.IO;
|
|
10
|
+
using System.Linq;
|
|
11
|
+
using System.Net;
|
|
12
|
+
using System.Text.Json;
|
|
13
|
+
using System.Threading;
|
|
14
|
+
using System.Threading.Tasks;
|
|
15
|
+
using Azure.Core.Pipeline;
|
|
16
|
+
|
|
17
|
+
namespace Azure.Core
|
|
18
|
+
{
|
|
19
|
+
internal class NextLinkOperationImplementation : IOperation
|
|
20
|
+
{
|
|
21
|
+
internal const string NotSet = "NOT_SET";
|
|
22
|
+
internal const string RehydrationTokenVersion = "1.0.0";
|
|
23
|
+
private const string ApiVersionParam = "api-version";
|
|
24
|
+
private static readonly string[] FailureStates = { "failed", "canceled" };
|
|
25
|
+
private static readonly string[] SuccessStates = { "succeeded" };
|
|
26
|
+
|
|
27
|
+
private readonly HeaderSource _headerSource;
|
|
28
|
+
private readonly Uri _startRequestUri;
|
|
29
|
+
private readonly OperationFinalStateVia _finalStateVia;
|
|
30
|
+
private readonly HttpPipeline _pipeline;
|
|
31
|
+
private readonly string? _apiVersion;
|
|
32
|
+
|
|
33
|
+
private string? _lastKnownLocation;
|
|
34
|
+
private string _nextRequestUri;
|
|
35
|
+
|
|
36
|
+
// We can only get OperationId when
|
|
37
|
+
// - The operation is still in progress and nextRequestUri contains it
|
|
38
|
+
// - During rehydration, rehydrationToken.Id is the operation id
|
|
39
|
+
public string OperationId { get; private set; } = NotSet;
|
|
40
|
+
public RequestMethod RequestMethod { get; }
|
|
41
|
+
|
|
42
|
+
public static IOperation Create(
|
|
43
|
+
HttpPipeline pipeline,
|
|
44
|
+
RequestMethod requestMethod,
|
|
45
|
+
Uri startRequestUri,
|
|
46
|
+
Response response,
|
|
47
|
+
OperationFinalStateVia finalStateVia,
|
|
48
|
+
bool skipApiVersionOverride = false,
|
|
49
|
+
string? apiVersionOverrideValue = null)
|
|
50
|
+
{
|
|
51
|
+
string? apiVersionStr = null;
|
|
52
|
+
if (apiVersionOverrideValue is not null)
|
|
53
|
+
{
|
|
54
|
+
apiVersionStr = apiVersionOverrideValue;
|
|
55
|
+
}
|
|
56
|
+
else
|
|
57
|
+
{
|
|
58
|
+
apiVersionStr = !skipApiVersionOverride && TryGetApiVersion(startRequestUri, out ReadOnlySpan<char> apiVersion) ? apiVersion.ToString() : null;
|
|
59
|
+
}
|
|
60
|
+
var headerSource = GetHeaderSource(requestMethod, startRequestUri, response, apiVersionStr, out string nextRequestUri, out bool isNextRequestPolling);
|
|
61
|
+
if (headerSource == HeaderSource.None && IsFinalState(response, headerSource, out var failureState, out _))
|
|
62
|
+
{
|
|
63
|
+
return new CompletedOperation(failureState ?? GetOperationStateFromFinalResponse(requestMethod, response));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
string? lastKnownLocation;
|
|
67
|
+
if (!response.Headers.TryGetValue("Location", out lastKnownLocation))
|
|
68
|
+
{
|
|
69
|
+
lastKnownLocation = null;
|
|
70
|
+
}
|
|
71
|
+
return new NextLinkOperationImplementation(pipeline, requestMethod, startRequestUri, nextRequestUri, headerSource, lastKnownLocation, finalStateVia, apiVersionStr, isNextRequestPolling : isNextRequestPolling);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
public static IOperation<T> Create<T>(
|
|
75
|
+
IOperationSource<T> operationSource,
|
|
76
|
+
HttpPipeline pipeline,
|
|
77
|
+
RequestMethod requestMethod,
|
|
78
|
+
Uri startRequestUri,
|
|
79
|
+
Response response,
|
|
80
|
+
OperationFinalStateVia finalStateVia,
|
|
81
|
+
bool skipApiVersionOverride = false,
|
|
82
|
+
string? apiVersionOverrideValue = null)
|
|
83
|
+
{
|
|
84
|
+
var operation = Create(pipeline, requestMethod, startRequestUri, response, finalStateVia, skipApiVersionOverride, apiVersionOverrideValue);
|
|
85
|
+
return new OperationToOperationOfT<T>(operationSource, operation);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
public static IOperation<T> Create<T>(
|
|
89
|
+
IOperationSource<T> operationSource,
|
|
90
|
+
IOperation operation)
|
|
91
|
+
=> new OperationToOperationOfT<T>(operationSource, operation);
|
|
92
|
+
|
|
93
|
+
public static IOperation Create(
|
|
94
|
+
HttpPipeline pipeline,
|
|
95
|
+
RehydrationToken rehydrationToken)
|
|
96
|
+
{
|
|
97
|
+
AssertNotNull(rehydrationToken, nameof(rehydrationToken));
|
|
98
|
+
AssertNotNull(pipeline, nameof(pipeline));
|
|
99
|
+
|
|
100
|
+
// TODO: Once we remove NextLinkOperationImplementation from internal shared and make it internal to Azure.Core only in https://github.com/Azure/azure-sdk-for-net/issues/43260
|
|
101
|
+
// We can access the internal members from RehydrationToken directly
|
|
102
|
+
var data = ModelReaderWriter.Write(rehydrationToken!, ModelReaderWriterOptions.Json);
|
|
103
|
+
using var document = JsonDocument.Parse(data);
|
|
104
|
+
var lroDetails = document.RootElement;
|
|
105
|
+
|
|
106
|
+
// We are sure that the following properties exists in the serialized rehydrationToken
|
|
107
|
+
var initialUri = lroDetails.GetProperty("initialUri").GetString();
|
|
108
|
+
if (!Uri.TryCreate(initialUri, UriKind.Absolute, out var startRequestUri))
|
|
109
|
+
{
|
|
110
|
+
throw new ArgumentException($"\"initialUri\" property on \"rehydrationToken\" is an invalid Uri", nameof(rehydrationToken));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// We are sure that the following properties(apart from nullable lastKnownLocation) are not null as they are required in the rehydrationToken
|
|
114
|
+
string nextRequestUri = lroDetails.GetProperty("nextRequestUri").GetString()!;
|
|
115
|
+
string requestMethodStr = lroDetails.GetProperty("requestMethod").GetString()!;
|
|
116
|
+
RequestMethod requestMethod = new RequestMethod(requestMethodStr)!;
|
|
117
|
+
string? lastKnownLocation = lroDetails.GetProperty("lastKnownLocation").GetString();
|
|
118
|
+
|
|
119
|
+
string finalStateViaStr = lroDetails.GetProperty("finalStateVia").GetString()!;
|
|
120
|
+
OperationFinalStateVia finalStateVia;
|
|
121
|
+
if (Enum.IsDefined(typeof(OperationFinalStateVia), finalStateViaStr))
|
|
122
|
+
{
|
|
123
|
+
finalStateVia = (OperationFinalStateVia)Enum.Parse(typeof(OperationFinalStateVia), finalStateViaStr);
|
|
124
|
+
}
|
|
125
|
+
else
|
|
126
|
+
{
|
|
127
|
+
finalStateVia = OperationFinalStateVia.Location;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
string headerSourceStr = lroDetails.GetProperty("headerSource").GetString()!;
|
|
131
|
+
HeaderSource headerSource;
|
|
132
|
+
if (Enum.IsDefined(typeof(HeaderSource), headerSourceStr))
|
|
133
|
+
{
|
|
134
|
+
headerSource = (HeaderSource)Enum.Parse(typeof(HeaderSource), headerSourceStr);
|
|
135
|
+
}
|
|
136
|
+
else
|
|
137
|
+
{
|
|
138
|
+
headerSource = HeaderSource.None;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return new NextLinkOperationImplementation(pipeline, requestMethod, startRequestUri, nextRequestUri, headerSource, lastKnownLocation, finalStateVia, null, rehydrationToken.Id);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
private NextLinkOperationImplementation(
|
|
145
|
+
HttpPipeline pipeline,
|
|
146
|
+
RequestMethod requestMethod,
|
|
147
|
+
Uri startRequestUri,
|
|
148
|
+
string nextRequestUri,
|
|
149
|
+
HeaderSource headerSource,
|
|
150
|
+
string? lastKnownLocation,
|
|
151
|
+
OperationFinalStateVia finalStateVia,
|
|
152
|
+
string? apiVersion,
|
|
153
|
+
string? operationId = null,
|
|
154
|
+
bool isNextRequestPolling = false)
|
|
155
|
+
{
|
|
156
|
+
AssertNotNull(pipeline, nameof(pipeline));
|
|
157
|
+
AssertNotNull(requestMethod, nameof(requestMethod));
|
|
158
|
+
AssertNotNull(startRequestUri, nameof(startRequestUri));
|
|
159
|
+
AssertNotNull(nextRequestUri, nameof(nextRequestUri));
|
|
160
|
+
AssertNotNull(headerSource, nameof(headerSource));
|
|
161
|
+
AssertNotNull(finalStateVia, nameof(finalStateVia));
|
|
162
|
+
|
|
163
|
+
RequestMethod = requestMethod;
|
|
164
|
+
_headerSource = headerSource;
|
|
165
|
+
_startRequestUri = startRequestUri;
|
|
166
|
+
_nextRequestUri = nextRequestUri;
|
|
167
|
+
_lastKnownLocation = lastKnownLocation;
|
|
168
|
+
_finalStateVia = finalStateVia;
|
|
169
|
+
_pipeline = pipeline;
|
|
170
|
+
_apiVersion = apiVersion;
|
|
171
|
+
if (operationId is not null)
|
|
172
|
+
{
|
|
173
|
+
OperationId = operationId;
|
|
174
|
+
}
|
|
175
|
+
else if (isNextRequestPolling)
|
|
176
|
+
{
|
|
177
|
+
OperationId = ParseOperationId(startRequestUri, nextRequestUri);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
private static string ParseOperationId(Uri startRequestUri, string nextRequestUri)
|
|
182
|
+
{
|
|
183
|
+
if (Uri.TryCreate(nextRequestUri, UriKind.Absolute, out var nextLink) && nextLink.Scheme != "file")
|
|
184
|
+
{
|
|
185
|
+
return nextLink.Segments.Last();
|
|
186
|
+
}
|
|
187
|
+
else
|
|
188
|
+
{
|
|
189
|
+
return new Uri(startRequestUri, nextRequestUri).Segments.Last();
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
public RehydrationToken GetRehydrationToken()
|
|
194
|
+
=> GetRehydrationToken(RequestMethod, _startRequestUri, _nextRequestUri, _headerSource.ToString(), _lastKnownLocation, _finalStateVia.ToString(), OperationId);
|
|
195
|
+
|
|
196
|
+
public static RehydrationToken GetRehydrationToken(
|
|
197
|
+
RequestMethod requestMethod,
|
|
198
|
+
Uri startRequestUri,
|
|
199
|
+
Response response,
|
|
200
|
+
OperationFinalStateVia finalStateVia)
|
|
201
|
+
{
|
|
202
|
+
AssertNotNull(requestMethod, nameof(requestMethod));
|
|
203
|
+
AssertNotNull(startRequestUri, nameof(startRequestUri));
|
|
204
|
+
AssertNotNull(response, nameof(response));
|
|
205
|
+
AssertNotNull(finalStateVia, nameof(finalStateVia));
|
|
206
|
+
|
|
207
|
+
var headerSource = GetHeaderSource(requestMethod, startRequestUri, response, null, out string nextRequestUri, out bool isNextRequestPolling);
|
|
208
|
+
string? lastKnownLocation;
|
|
209
|
+
if (!response.Headers.TryGetValue("Location", out lastKnownLocation))
|
|
210
|
+
{
|
|
211
|
+
lastKnownLocation = null;
|
|
212
|
+
}
|
|
213
|
+
return GetRehydrationToken(requestMethod, startRequestUri, nextRequestUri, headerSource.ToString(), lastKnownLocation, finalStateVia.ToString(), isNextRequestPolling ? ParseOperationId(startRequestUri, nextRequestUri) : null);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
public static RehydrationToken GetRehydrationToken(
|
|
217
|
+
RequestMethod requestMethod,
|
|
218
|
+
Uri startRequestUri,
|
|
219
|
+
string nextRequestUri,
|
|
220
|
+
string headerSource,
|
|
221
|
+
string? lastKnownLocation,
|
|
222
|
+
string finalStateVia,
|
|
223
|
+
string? operationId = null)
|
|
224
|
+
{
|
|
225
|
+
// TODO: Once we remove NextLinkOperationImplementation from internal shared and make it internal to Azure.Core only in https://github.com/Azure/azure-sdk-for-net/issues/43260
|
|
226
|
+
// We can access the internal members from RehydrationToken directly
|
|
227
|
+
var json = $$"""
|
|
228
|
+
{"version":"{{RehydrationTokenVersion}}","id":{{ConstructStringValue(operationId)}},"requestMethod":"{{requestMethod}}","initialUri":"{{startRequestUri.AbsoluteUri}}","nextRequestUri":"{{nextRequestUri}}","headerSource":"{{headerSource}}","finalStateVia":"{{finalStateVia}}","lastKnownLocation":{{ConstructStringValue(lastKnownLocation)}}}
|
|
229
|
+
""";
|
|
230
|
+
var data = new BinaryData(json);
|
|
231
|
+
return ModelReaderWriter.Read<RehydrationToken>(data);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
private static string? ConstructStringValue(string? value) => value is null ? "null" : $"\"{value}\"";
|
|
235
|
+
|
|
236
|
+
public async ValueTask<OperationState> UpdateStateAsync(bool async, CancellationToken cancellationToken)
|
|
237
|
+
{
|
|
238
|
+
Response response = async
|
|
239
|
+
? await GetResponseAsync(_nextRequestUri, cancellationToken).ConfigureAwait(false)
|
|
240
|
+
: GetResponse(_nextRequestUri, cancellationToken);
|
|
241
|
+
|
|
242
|
+
var hasCompleted = IsFinalState(response, _headerSource, out var failureState, out var resourceLocation);
|
|
243
|
+
if (failureState != null)
|
|
244
|
+
{
|
|
245
|
+
return failureState.Value;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (hasCompleted)
|
|
249
|
+
{
|
|
250
|
+
string? finalUri = GetFinalUri(resourceLocation);
|
|
251
|
+
Response finalResponse;
|
|
252
|
+
if (finalUri != null)
|
|
253
|
+
{
|
|
254
|
+
finalResponse = async
|
|
255
|
+
? await GetResponseAsync(finalUri, cancellationToken).ConfigureAwait(false)
|
|
256
|
+
: GetResponse(finalUri, cancellationToken);
|
|
257
|
+
}
|
|
258
|
+
else
|
|
259
|
+
{
|
|
260
|
+
finalResponse = response;
|
|
261
|
+
}
|
|
262
|
+
return GetOperationStateFromFinalResponse(RequestMethod, finalResponse);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
UpdateNextRequestUri(response.Headers);
|
|
266
|
+
return OperationState.Pending(response);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
private static OperationState GetOperationStateFromFinalResponse(RequestMethod requestMethod, Response response)
|
|
270
|
+
{
|
|
271
|
+
switch (response.Status)
|
|
272
|
+
{
|
|
273
|
+
case 200:
|
|
274
|
+
case 201 when requestMethod == RequestMethod.Put:
|
|
275
|
+
case 204 when requestMethod != RequestMethod.Put && requestMethod != RequestMethod.Patch:
|
|
276
|
+
return OperationState.Success(response);
|
|
277
|
+
default:
|
|
278
|
+
return OperationState.Failure(response);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
private void UpdateNextRequestUri(ResponseHeaders headers)
|
|
283
|
+
{
|
|
284
|
+
var hasLocation = headers.TryGetValue("Location", out string? location);
|
|
285
|
+
if (hasLocation)
|
|
286
|
+
{
|
|
287
|
+
_lastKnownLocation = location;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
switch (_headerSource)
|
|
291
|
+
{
|
|
292
|
+
case HeaderSource.OperationLocation when headers.TryGetValue("Operation-Location", out string? operationLocation):
|
|
293
|
+
_nextRequestUri = AppendOrReplaceApiVersion(operationLocation, _apiVersion);
|
|
294
|
+
OperationId = ParseOperationId(_startRequestUri, _nextRequestUri);
|
|
295
|
+
return;
|
|
296
|
+
case HeaderSource.AzureAsyncOperation when headers.TryGetValue("Azure-AsyncOperation", out string? azureAsyncOperation):
|
|
297
|
+
_nextRequestUri = AppendOrReplaceApiVersion(azureAsyncOperation, _apiVersion);
|
|
298
|
+
OperationId = ParseOperationId(_startRequestUri, _nextRequestUri);
|
|
299
|
+
return;
|
|
300
|
+
case HeaderSource.Location when hasLocation:
|
|
301
|
+
_nextRequestUri = AppendOrReplaceApiVersion(location!, _apiVersion);
|
|
302
|
+
OperationId = ParseOperationId(_startRequestUri, _nextRequestUri);
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
internal static string AppendOrReplaceApiVersion(string uri, string? apiVersion)
|
|
308
|
+
{
|
|
309
|
+
if (!string.IsNullOrEmpty(apiVersion))
|
|
310
|
+
{
|
|
311
|
+
var uriSpan = uri.AsSpan();
|
|
312
|
+
var apiVersionParamSpan = ApiVersionParam.AsSpan();
|
|
313
|
+
var apiVersionIndex = uriSpan.IndexOf(apiVersionParamSpan);
|
|
314
|
+
if (apiVersionIndex == -1)
|
|
315
|
+
{
|
|
316
|
+
var concatSymbol = uriSpan.IndexOf('?') > -1 ? "&" : "?";
|
|
317
|
+
return $"{uri}{concatSymbol}api-version={apiVersion}";
|
|
318
|
+
}
|
|
319
|
+
else
|
|
320
|
+
{
|
|
321
|
+
var lengthToEndOfApiVersionParam = apiVersionIndex + ApiVersionParam.Length;
|
|
322
|
+
ReadOnlySpan<char> remaining = uriSpan.Slice(lengthToEndOfApiVersionParam);
|
|
323
|
+
bool apiVersionHasEqualSign = false;
|
|
324
|
+
if (remaining.IndexOf('=') == 0)
|
|
325
|
+
{
|
|
326
|
+
remaining = remaining.Slice(1);
|
|
327
|
+
lengthToEndOfApiVersionParam += 1;
|
|
328
|
+
apiVersionHasEqualSign = true;
|
|
329
|
+
}
|
|
330
|
+
var indexOfFirstSignAfterApiVersion = remaining.IndexOf('&');
|
|
331
|
+
ReadOnlySpan<char> uriBeforeApiVersion = uriSpan.Slice(0, lengthToEndOfApiVersionParam);
|
|
332
|
+
if (indexOfFirstSignAfterApiVersion == -1)
|
|
333
|
+
{
|
|
334
|
+
return string.Concat(uriBeforeApiVersion.ToString(), apiVersionHasEqualSign ? string.Empty : "=", apiVersion);
|
|
335
|
+
}
|
|
336
|
+
else
|
|
337
|
+
{
|
|
338
|
+
ReadOnlySpan<char> uriAfterApiVersion = uriSpan.Slice(indexOfFirstSignAfterApiVersion + lengthToEndOfApiVersionParam);
|
|
339
|
+
return string.Concat(uriBeforeApiVersion.ToString(), apiVersionHasEqualSign ? string.Empty : "=", apiVersion, uriAfterApiVersion.ToString());
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
return uri;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
internal static bool TryGetApiVersion(Uri startRequestUri, out ReadOnlySpan<char> apiVersion)
|
|
347
|
+
{
|
|
348
|
+
apiVersion = default;
|
|
349
|
+
ReadOnlySpan<char> uriSpan = startRequestUri.Query.AsSpan();
|
|
350
|
+
int startIndex = uriSpan.IndexOf(ApiVersionParam.AsSpan());
|
|
351
|
+
if (startIndex == -1)
|
|
352
|
+
{
|
|
353
|
+
return false;
|
|
354
|
+
}
|
|
355
|
+
startIndex += ApiVersionParam.Length;
|
|
356
|
+
ReadOnlySpan<char> remaining = uriSpan.Slice(startIndex);
|
|
357
|
+
if (remaining.IndexOf('=') == 0)
|
|
358
|
+
{
|
|
359
|
+
remaining = remaining.Slice(1);
|
|
360
|
+
startIndex += 1;
|
|
361
|
+
}
|
|
362
|
+
else
|
|
363
|
+
{
|
|
364
|
+
return false;
|
|
365
|
+
}
|
|
366
|
+
int endIndex = remaining.IndexOf('&');
|
|
367
|
+
int length = endIndex == -1 ? uriSpan.Length - startIndex : endIndex;
|
|
368
|
+
apiVersion = uriSpan.Slice(startIndex, length);
|
|
369
|
+
return true;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/// <summary>
|
|
373
|
+
/// This function is used to get the final request uri after the lro has completed.
|
|
374
|
+
/// </summary>
|
|
375
|
+
private string? GetFinalUri(string? resourceLocation)
|
|
376
|
+
{
|
|
377
|
+
// Set final uri as null if the response for initial request doesn't contain header "Operation-Location" or "Azure-AsyncOperation".
|
|
378
|
+
if (_headerSource is not (HeaderSource.OperationLocation or HeaderSource.AzureAsyncOperation))
|
|
379
|
+
{
|
|
380
|
+
return null;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// Set final uri as null if initial request is a delete method.
|
|
384
|
+
if (RequestMethod == RequestMethod.Delete)
|
|
385
|
+
{
|
|
386
|
+
return null;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// Handle final-state-via options: https://github.com/Azure/autorest/blob/main/docs/extensions/readme.md#x-ms-long-running-operation-options
|
|
390
|
+
switch (_finalStateVia)
|
|
391
|
+
{
|
|
392
|
+
case OperationFinalStateVia.LocationOverride when !string.IsNullOrEmpty(_lastKnownLocation):
|
|
393
|
+
return _lastKnownLocation;
|
|
394
|
+
case OperationFinalStateVia.OperationLocation or OperationFinalStateVia.AzureAsyncOperation when RequestMethod == RequestMethod.Post:
|
|
395
|
+
return null;
|
|
396
|
+
case OperationFinalStateVia.OriginalUri:
|
|
397
|
+
return _startRequestUri.AbsoluteUri;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// If response body contains resourceLocation, use it: https://github.com/microsoft/api-guidelines/blob/vNext/Guidelines.md#target-resource-location
|
|
401
|
+
if (resourceLocation != null)
|
|
402
|
+
{
|
|
403
|
+
return resourceLocation;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// If initial request is PUT or PATCH, return initial request Uri
|
|
407
|
+
if (RequestMethod == RequestMethod.Put || RequestMethod == RequestMethod.Patch)
|
|
408
|
+
{
|
|
409
|
+
return _startRequestUri.AbsoluteUri;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// If response for initial request contains header "Location", return last known location
|
|
413
|
+
if (!string.IsNullOrEmpty(_lastKnownLocation))
|
|
414
|
+
{
|
|
415
|
+
return _lastKnownLocation;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
return null;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
private Response GetResponse(string uri, CancellationToken cancellationToken)
|
|
422
|
+
{
|
|
423
|
+
using HttpMessage message = CreateRequest(uri);
|
|
424
|
+
_pipeline.Send(message, cancellationToken);
|
|
425
|
+
|
|
426
|
+
// If we are doing final get for a delete LRO with 404, just return empty response with 204
|
|
427
|
+
if (message.Response.Status == 404 && RequestMethod == RequestMethod.Delete)
|
|
428
|
+
{
|
|
429
|
+
return new EmptyResponse(HttpStatusCode.NoContent, message.Response.ClientRequestId);
|
|
430
|
+
}
|
|
431
|
+
return message.Response;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
private async ValueTask<Response> GetResponseAsync(string uri, CancellationToken cancellationToken)
|
|
435
|
+
{
|
|
436
|
+
using HttpMessage message = CreateRequest(uri);
|
|
437
|
+
await _pipeline.SendAsync(message, cancellationToken).ConfigureAwait(false);
|
|
438
|
+
|
|
439
|
+
// If we are doing final get for a delete LRO with 404, just return empty response with 204
|
|
440
|
+
if (message.Response.Status == 404 && RequestMethod == RequestMethod.Delete)
|
|
441
|
+
{
|
|
442
|
+
return new EmptyResponse(HttpStatusCode.NoContent, message.Response.ClientRequestId);
|
|
443
|
+
}
|
|
444
|
+
return message.Response;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/// <summary>
|
|
448
|
+
/// This is only used for final get of the delete LRO, we just want to return an empty response with 204 to the user for this case.
|
|
449
|
+
/// </summary>
|
|
450
|
+
private sealed class EmptyResponse : Response
|
|
451
|
+
{
|
|
452
|
+
public EmptyResponse(HttpStatusCode status, string clientRequestId)
|
|
453
|
+
{
|
|
454
|
+
Status = (int)status;
|
|
455
|
+
ReasonPhrase = status.ToString();
|
|
456
|
+
ClientRequestId = clientRequestId;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
public override int Status { get; }
|
|
460
|
+
|
|
461
|
+
public override string ReasonPhrase { get; }
|
|
462
|
+
|
|
463
|
+
public override Stream? ContentStream { get => null; set => throw new InvalidOperationException("Should not set ContentStream for an empty response."); }
|
|
464
|
+
public override string ClientRequestId { get; set; }
|
|
465
|
+
|
|
466
|
+
public override void Dispose()
|
|
467
|
+
{
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/// <inheritdoc />
|
|
471
|
+
#if HAS_INTERNALS_VISIBLE_CORE
|
|
472
|
+
internal
|
|
473
|
+
#endif
|
|
474
|
+
protected override bool ContainsHeader(string name) => false;
|
|
475
|
+
|
|
476
|
+
/// <inheritdoc />
|
|
477
|
+
#if HAS_INTERNALS_VISIBLE_CORE
|
|
478
|
+
internal
|
|
479
|
+
#endif
|
|
480
|
+
protected override IEnumerable<HttpHeader> EnumerateHeaders() => Array.Empty<HttpHeader>();
|
|
481
|
+
|
|
482
|
+
/// <inheritdoc />
|
|
483
|
+
#if HAS_INTERNALS_VISIBLE_CORE
|
|
484
|
+
internal
|
|
485
|
+
#endif
|
|
486
|
+
protected override bool TryGetHeader(string name, out string value)
|
|
487
|
+
{
|
|
488
|
+
value = string.Empty;
|
|
489
|
+
return false;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/// <inheritdoc />
|
|
493
|
+
#if HAS_INTERNALS_VISIBLE_CORE
|
|
494
|
+
internal
|
|
495
|
+
#endif
|
|
496
|
+
protected override bool TryGetHeaderValues(string name, out IEnumerable<string> values)
|
|
497
|
+
{
|
|
498
|
+
values = Array.Empty<string>();
|
|
499
|
+
return false;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
private HttpMessage CreateRequest(string uri)
|
|
504
|
+
{
|
|
505
|
+
HttpMessage message = _pipeline.CreateMessage();
|
|
506
|
+
Request request = message.Request;
|
|
507
|
+
request.Method = RequestMethod.Get;
|
|
508
|
+
|
|
509
|
+
if (Uri.TryCreate(uri, UriKind.Absolute, out var nextLink) && nextLink.Scheme != "file")
|
|
510
|
+
{
|
|
511
|
+
request.Uri.Reset(nextLink);
|
|
512
|
+
}
|
|
513
|
+
else
|
|
514
|
+
{
|
|
515
|
+
request.Uri.Reset(new Uri(_startRequestUri, uri));
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
return message;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
private static bool IsFinalState(Response response, HeaderSource headerSource, out OperationState? failureState, out string? resourceLocation)
|
|
522
|
+
{
|
|
523
|
+
failureState = null;
|
|
524
|
+
resourceLocation = null;
|
|
525
|
+
|
|
526
|
+
if (headerSource == HeaderSource.Location)
|
|
527
|
+
{
|
|
528
|
+
return response.Status != 202;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
if (response.Status is >= 200 and <= 204)
|
|
532
|
+
{
|
|
533
|
+
if (response.ContentStream is { Length: > 0 })
|
|
534
|
+
{
|
|
535
|
+
try
|
|
536
|
+
{
|
|
537
|
+
using JsonDocument document = JsonDocument.Parse(response.ContentStream);
|
|
538
|
+
var root = document.RootElement;
|
|
539
|
+
switch (headerSource)
|
|
540
|
+
{
|
|
541
|
+
case HeaderSource.None when root.TryGetProperty("properties", out var properties) && properties.TryGetProperty("provisioningState", out JsonElement property):
|
|
542
|
+
case HeaderSource.OperationLocation when root.TryGetProperty("status", out property):
|
|
543
|
+
case HeaderSource.AzureAsyncOperation when root.TryGetProperty("status", out property):
|
|
544
|
+
var state = GetRequiredString(property).ToLowerInvariant();
|
|
545
|
+
if (FailureStates.Contains(state))
|
|
546
|
+
{
|
|
547
|
+
failureState = OperationState.Failure(response);
|
|
548
|
+
return true;
|
|
549
|
+
}
|
|
550
|
+
else if (!SuccessStates.Contains(state))
|
|
551
|
+
{
|
|
552
|
+
return false;
|
|
553
|
+
}
|
|
554
|
+
else
|
|
555
|
+
{
|
|
556
|
+
if (headerSource is HeaderSource.OperationLocation or HeaderSource.AzureAsyncOperation && root.TryGetProperty("resourceLocation", out var resourceLocationProperty))
|
|
557
|
+
{
|
|
558
|
+
resourceLocation = resourceLocationProperty.GetString();
|
|
559
|
+
}
|
|
560
|
+
return true;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
finally
|
|
565
|
+
{
|
|
566
|
+
// It is required to reset the position of the content after reading as this response may be used for deserialization.
|
|
567
|
+
response.ContentStream.Position = 0;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// If headerSource is None and provisioningState was not found, it defaults to Succeeded.
|
|
572
|
+
if (headerSource == HeaderSource.None)
|
|
573
|
+
{
|
|
574
|
+
return true;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
failureState = OperationState.Failure(response);
|
|
579
|
+
return true;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
private static string GetRequiredString(in JsonElement element)
|
|
583
|
+
{
|
|
584
|
+
var value = element.GetString();
|
|
585
|
+
if (value == null)
|
|
586
|
+
throw new InvalidOperationException($"The requested operation requires an element of type 'String', but the target element has type '{element.ValueKind}'.");
|
|
587
|
+
|
|
588
|
+
return value;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
private static bool ShouldIgnoreHeader(RequestMethod method, Response response)
|
|
592
|
+
=> method.Method == RequestMethod.Patch.Method && response.Status == 200;
|
|
593
|
+
|
|
594
|
+
// Since this method is static, we can't manipulate the instance property OperationId of the class. We need to return isRequestPolling to update the OperationId after creaing the instance.
|
|
595
|
+
private static HeaderSource GetHeaderSource(RequestMethod requestMethod, Uri requestUri, Response response, string? apiVersion, out string nextRequestUri, out bool isNextRequestPolling)
|
|
596
|
+
{
|
|
597
|
+
isNextRequestPolling = false;
|
|
598
|
+
if (ShouldIgnoreHeader(requestMethod, response))
|
|
599
|
+
{
|
|
600
|
+
nextRequestUri = requestUri.AbsoluteUri;
|
|
601
|
+
return HeaderSource.None;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
var headers = response.Headers;
|
|
605
|
+
if (headers.TryGetValue("Operation-Location", out var operationLocationUri))
|
|
606
|
+
{
|
|
607
|
+
nextRequestUri = AppendOrReplaceApiVersion(operationLocationUri, apiVersion);
|
|
608
|
+
isNextRequestPolling = true;
|
|
609
|
+
return HeaderSource.OperationLocation;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
if (headers.TryGetValue("Azure-AsyncOperation", out var azureAsyncOperationUri))
|
|
613
|
+
{
|
|
614
|
+
nextRequestUri = AppendOrReplaceApiVersion(azureAsyncOperationUri, apiVersion);
|
|
615
|
+
isNextRequestPolling = true;
|
|
616
|
+
return HeaderSource.AzureAsyncOperation;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
if (headers.TryGetValue("Location", out var locationUri))
|
|
620
|
+
{
|
|
621
|
+
nextRequestUri = AppendOrReplaceApiVersion(locationUri, apiVersion);
|
|
622
|
+
isNextRequestPolling = true;
|
|
623
|
+
return HeaderSource.Location;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
nextRequestUri = requestUri.AbsoluteUri;
|
|
627
|
+
return HeaderSource.None;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
private static void AssertNotNull<T>(T value, string name)
|
|
631
|
+
{
|
|
632
|
+
if (value is null)
|
|
633
|
+
{
|
|
634
|
+
throw new ArgumentNullException(name);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
private enum HeaderSource
|
|
639
|
+
{
|
|
640
|
+
None,
|
|
641
|
+
OperationLocation,
|
|
642
|
+
AzureAsyncOperation,
|
|
643
|
+
Location
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
private class CompletedOperation : IOperation
|
|
647
|
+
{
|
|
648
|
+
private readonly OperationState _operationState;
|
|
649
|
+
|
|
650
|
+
public CompletedOperation(OperationState operationState)
|
|
651
|
+
{
|
|
652
|
+
_operationState = operationState;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
public ValueTask<OperationState> UpdateStateAsync(bool async, CancellationToken cancellationToken) => new(_operationState);
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
private sealed class OperationToOperationOfT<T> : IOperation<T>
|
|
659
|
+
{
|
|
660
|
+
private readonly IOperationSource<T> _operationSource;
|
|
661
|
+
private readonly IOperation _operation;
|
|
662
|
+
|
|
663
|
+
public OperationToOperationOfT(IOperationSource<T> operationSource, IOperation operation)
|
|
664
|
+
{
|
|
665
|
+
_operationSource = operationSource;
|
|
666
|
+
_operation = operation;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
public async ValueTask<OperationState<T>> UpdateStateAsync(bool async, CancellationToken cancellationToken)
|
|
670
|
+
{
|
|
671
|
+
var state = await _operation.UpdateStateAsync(async, cancellationToken).ConfigureAwait(false);
|
|
672
|
+
if (state.HasSucceeded)
|
|
673
|
+
{
|
|
674
|
+
var result = async
|
|
675
|
+
? await _operationSource.CreateResultAsync(state.RawResponse, cancellationToken).ConfigureAwait(false)
|
|
676
|
+
: _operationSource.CreateResult(state.RawResponse, cancellationToken);
|
|
677
|
+
|
|
678
|
+
return OperationState<T>.Success(state.RawResponse, result);
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
if (state.HasCompleted)
|
|
682
|
+
{
|
|
683
|
+
return OperationState<T>.Failure(state.RawResponse, state.OperationFailedException);
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
return OperationState<T>.Pending(state.RawResponse);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
}
|