Skip to content

Commit d6f887f

Browse files
committed
Improve HttpStatusCodeParser efficiency, basic validation of non-standard regular expressions, provide a default implementation (HttpStatusCodeParser.Default)
1 parent 290d868 commit d6f887f

2 files changed

Lines changed: 73 additions & 6 deletions

File tree

src/corelib/Core/HttpStatusCodeParser.cs

Lines changed: 72 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,83 @@
1-
using System.Text.RegularExpressions;
1+
using System;
2+
using System.Linq;
3+
using System.Text.RegularExpressions;
24
using net.openstack.Core.Domain;
35

46
namespace net.openstack.Core
57
{
8+
/// <summary>
9+
/// A status parser for HTTP status codes.
10+
/// </summary>
611
public class HttpStatusCodeParser : IStatusParser
712
{
8-
private const string RegEx = @"(?<StatusCode>\d*)\s*(?<Status>\w*)";
9-
public Status Parse(string value)
13+
/// <summary>
14+
/// The default regular expression to use for matching HTTP status codes.
15+
/// </summary>
16+
protected static readonly string DefaultPattern = @"(?<StatusCode>\d*)\s*(?<Status>\w*)";
17+
18+
/// <summary>
19+
/// A singleton instance of the default <see cref="HttpStatusCodeParser"/>.
20+
/// </summary>
21+
private static readonly HttpStatusCodeParser _default = new HttpStatusCodeParser(DefaultPattern);
22+
23+
/// <summary>
24+
/// The compiled regular expression to use for matching HTTP status codes.
25+
/// </summary>
26+
private readonly Regex _expression;
27+
28+
/// <summary>
29+
/// Constructs a new instance of <see cref="HttpStatusCodeParser"/> for the default regular
30+
/// expression.
31+
/// </summary>
32+
[Obsolete("Use HttpStatusCodeParser.Default instead.")]
33+
public HttpStatusCodeParser()
34+
: this(DefaultPattern)
1035
{
11-
var regex = new Regex(RegEx);
36+
}
37+
38+
/// <summary>
39+
/// Constructs a new instance of <see cref="HttpStatusCodeParser"/> for the specified regular
40+
/// expression.
41+
/// </summary>
42+
/// <param name="pattern">
43+
/// The regular expression pattern to use.
44+
///
45+
/// <para><paramref name="pattern"/> should contain the named capturing grounds <c>StatusCode</c> and <c>status</c>.</para>
46+
/// </param>
47+
/// <exception cref="ArgumentNullException"><paramref name="pattern"/> is <c>null</c>.</exception>
48+
/// <exception cref="ArgumentException">
49+
/// <paramref name="pattern"/> does not contain a capturing group named <c>StatusCode</c>.
50+
/// <para>-or-</para>
51+
/// <para><paramref name="pattern"/> does not contain a capturing group named <c>Status</c>.</para>
52+
/// </exception>
53+
protected HttpStatusCodeParser(string pattern)
54+
{
55+
if (pattern == null)
56+
throw new ArgumentNullException("pattern");
57+
58+
_expression = new Regex(pattern, RegexOptions.Compiled);
1259

13-
var match = regex.Match(value);
60+
string[] groupNames = _expression.GetGroupNames();
61+
if (!groupNames.Contains("StatusCode", StringComparer.Ordinal))
62+
throw new ArgumentException("The pattern does not contain a StatusCode named capturing group.", "pattern");
63+
if (!groupNames.Contains("Status", StringComparer.Ordinal))
64+
throw new ArgumentException("The pattern does not contain a Status named capturing group.", "pattern");
65+
}
66+
67+
/// <summary>
68+
/// Gets a default <see cref="HttpStatusCodeParser"/>.
69+
/// </summary>
70+
public static HttpStatusCodeParser Default
71+
{
72+
get
73+
{
74+
return _default;
75+
}
76+
}
77+
78+
public Status Parse(string value)
79+
{
80+
var match = _expression.Match(value);
1481
if (!match.Success)
1582
return null;
1683

src/corelib/Providers/Rackspace/CloudFilesProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ public CloudFilesProvider(CloudIdentity identity, IRestService restService)
9999
/// <param name="identityProvider">An instance of an <see cref="IIdentityProvider"/> to override the default <see cref="CloudIdentity"/></param>
100100
/// <param name="restService">An instance of an <see cref="IRestService"/> to override the default <see cref="JsonRestServices"/></param>
101101
public CloudFilesProvider(CloudIdentity identity, IIdentityProvider identityProvider, IRestService restService)
102-
: this(identity, identityProvider, restService, CloudFilesValidator.Default, CloudFilesMetadataProcessor.Default, EncodeDecodeProvider.Default, new HttpStatusCodeParser(), new BulkDeletionResultMapper(new HttpStatusCodeParser())) { }
102+
: this(identity, identityProvider, restService, CloudFilesValidator.Default, CloudFilesMetadataProcessor.Default, EncodeDecodeProvider.Default, HttpStatusCodeParser.Default, new BulkDeletionResultMapper(HttpStatusCodeParser.Default)) { }
103103

104104
internal CloudFilesProvider(IIdentityProvider cloudIdentityProvider, IRestService restService, IObjectStorageValidator cloudFilesValidator, IObjectStorageMetadataProcessor cloudFilesMetadataProcessor, IEncodeDecodeProvider encodeDecodeProvider, IStatusParser statusParser, IObjectMapper<BulkDeleteResponse, BulkDeletionResults> mapper)
105105
: this(null, cloudIdentityProvider, restService, cloudFilesValidator, cloudFilesMetadataProcessor, encodeDecodeProvider, statusParser, mapper) { }

0 commit comments

Comments
 (0)