-
Notifications
You must be signed in to change notification settings - Fork 697
/
ApiVersioningFeature.cs
125 lines (107 loc) · 3.62 KB
/
ApiVersioningFeature.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// Copyright (c) .NET Foundation and contributors. All rights reserved.
namespace Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using System.Globalization;
using System.Runtime.CompilerServices;
/// <summary>
/// Represents the API versioning feature.
/// </summary>
[CLSCompliant( false )]
public sealed class ApiVersioningFeature : IApiVersioningFeature
{
private readonly HttpContext context;
private IReadOnlyList<string>? rawApiVersions;
private ApiVersion? apiVersion;
/// <summary>
/// Initializes a new instance of the <see cref="ApiVersioningFeature"/> class.
/// </summary>
/// <param name="context">The current <see cref="HttpContext">HTTP context</see>.</param>
[CLSCompliant( false )]
public ApiVersioningFeature( HttpContext context ) => this.context = context;
/// <inheritdoc />
public string? RouteParameter { get; set; }
/// <inheritdoc />
public IReadOnlyList<string> RawRequestedApiVersions
{
get
{
if ( rawApiVersions is null )
{
var reader = context.RequestServices.GetService<IApiVersionReader>()
?? ApiVersionReader.Combine(
new QueryStringApiVersionReader(),
new UrlSegmentApiVersionReader() );
rawApiVersions = reader.Read( context.Request );
}
return rawApiVersions;
}
set => rawApiVersions = value;
}
/// <inheritdoc />
public string? RawRequestedApiVersion
{
get
{
var values = RawRequestedApiVersions;
return values.Count switch
{
0 => default,
1 => values[0],
#pragma warning disable IDE0079
#pragma warning disable CA1065 // Do not raise exceptions in unexpected locations
_ => throw NewAmbiguousApiVersionException( values ),
#pragma warning restore CA1065 // Do not raise exceptions in unexpected locations
#pragma warning restore IDE0079
};
}
set
{
rawApiVersions = string.IsNullOrEmpty( value ) ? default : new[] { value };
}
}
/// <inheritdoc />
public ApiVersion? RequestedApiVersion
{
get
{
if ( apiVersion is not null )
{
return apiVersion;
}
var value = RawRequestedApiVersion;
if ( string.IsNullOrEmpty( value ) )
{
return apiVersion;
}
var parser = context.RequestServices.GetService<IApiVersionParser>()
?? ApiVersionParser.Default;
try
{
apiVersion = parser.Parse( value );
}
catch ( FormatException )
{
apiVersion = default;
}
return apiVersion;
}
set
{
apiVersion = value;
if ( apiVersion is not null &&
( rawApiVersions is null || rawApiVersions.Count == 0 ) )
{
rawApiVersions = new[] { apiVersion.ToString() };
}
}
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
private static AmbiguousApiVersionException NewAmbiguousApiVersionException( IReadOnlyList<string> values ) =>
new(
string.Format(
CultureInfo.CurrentCulture,
CommonSR.MultipleDifferentApiVersionsRequested,
string.Join( ", ", values.ToArray(), 0, values.Count ) ),
values );
}