Created
February 23, 2017 00:56
-
-
Save thomaslevesque/d8ee28be1cf383a3f8aaf39cee776f92 to your computer and use it in GitHub Desktop.
Parsing HTTP authentication challenge with Sprache
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void Main() | |
{ | |
ParseAndPrintChallenge(@"Bearer realm=""FooCorp"", error=invalid_token, error_description=""The access token has expired"""); | |
} | |
void ParseAndPrintChallenge(string input) | |
{ | |
var challenge = Grammar.Challenge.Parse(input); | |
Console.WriteLine($"Scheme: {challenge.Scheme}"); | |
Console.WriteLine($"Parameters:"); | |
foreach (var p in challenge.Parameters) | |
{ | |
Console.WriteLine($"- {p.Name} = {p.Value}"); | |
} | |
} | |
static class Grammar | |
{ | |
private static readonly Parser<char> DoubleQuote = Parse.Char('"'); | |
private static readonly Parser<char> EqualSign = Parse.Char('='); | |
private static readonly Parser<char> Backslash = Parse.Char('\\'); | |
private static readonly Parser<char> Comma = Parse.Char(','); | |
private static readonly Parser<char> SeparatorChar = | |
Parse.Chars("()<>@,;:\\\"/[]?={} \t"); | |
private static readonly Parser<char> ControlChar = | |
Parse.Char(Char.IsControl, "Control character"); | |
private static readonly Parser<char> TokenChar = | |
Parse.AnyChar | |
.Except(SeparatorChar) | |
.Except(ControlChar); | |
private static readonly Parser<string> Token = | |
TokenChar.AtLeastOnce().Text(); | |
private static readonly Parser<char> QdText = | |
Parse.AnyChar.Except(DoubleQuote); | |
private static readonly Parser<char> QuotedPair = | |
from _ in Backslash | |
from c in Parse.AnyChar | |
select c; | |
private static readonly Parser<string> QuotedString = | |
from open in DoubleQuote | |
from text in QuotedPair.Or(QdText).Many().Text() | |
from close in DoubleQuote | |
select text; | |
private static readonly Parser<string> ParameterValue = | |
Token.Or(QuotedString); | |
private static readonly Parser<Parameter> Parameter = | |
from name in Token | |
from _ in EqualSign | |
from value in ParameterValue | |
select new Parameter(name, value); | |
private static readonly Parser<char> ListDelimiter = | |
from leading in Parse.WhiteSpace.Many() | |
from c in Comma | |
from trailing in Parse.WhiteSpace.Or(Comma).Many() | |
select c; | |
private static readonly Parser<Parameter[]> Parameters = | |
from p in Parameter.DelimitedBy(ListDelimiter) | |
select p.ToArray(); | |
public static readonly Parser<Challenge> Challenge = | |
from scheme in Token | |
from _ in Parse.WhiteSpace.AtLeastOnce() | |
from parameters in Parameters | |
select new Challenge(scheme, parameters); | |
} | |
class Parameter | |
{ | |
public Parameter(string name, string value) | |
{ | |
Name = name; | |
Value = value; | |
} | |
public string Name { get; } | |
public string Value { get; } | |
} | |
class Challenge | |
{ | |
public Challenge(string scheme, Parameter[] parameters) | |
{ | |
Scheme = scheme; | |
Parameters = parameters; | |
} | |
public string Scheme { get; } | |
public Parameter[] Parameters { get; } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment