diff --git a/akka-http-core/src/main/scala/akka/http/impl/model/parser/CharacterClasses.scala b/akka-http-core/src/main/scala/akka/http/impl/model/parser/CharacterClasses.scala index 37ee2a724f..10df68e7a3 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/model/parser/CharacterClasses.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/model/parser/CharacterClasses.scala @@ -75,6 +75,7 @@ private[http] object CharacterClasses { val DIGIT05 = CharPredicate('0' to '5') def DIGIT19 = CharPredicate.Digit19 val colonSlashEOI = CharPredicate(':', '/', akka.parboiled2.EOI) + val `date-sep` = CharPredicate("""- """) require(`qdtext-base`.isMaskBased) // make sure we didn't introduce any non-7bit-chars by accident which require(`ctext-base`.isMaskBased) // would make the CharPredicate fall back to the much slower diff --git a/akka-http-core/src/main/scala/akka/http/impl/model/parser/CommonRules.scala b/akka-http-core/src/main/scala/akka/http/impl/model/parser/CommonRules.scala index e133beaecb..890a1ca03a 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/model/parser/CommonRules.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/model/parser/CommonRules.scala @@ -78,7 +78,7 @@ private[parser] trait CommonRules { this: Parser with StringBuilding ⇒ def `day-name` = rule( "Sun" ~ push(0) | "Mon" ~ push(1) | "Tue" ~ push(2) | "Wed" ~ push(3) | "Thu" ~ push(4) | "Fri" ~ push(5) | "Sat" ~ push(6)) - def date1 = rule { day ~ ' ' ~ month ~ ' ' ~ year } + def date1 = rule { day ~ `date-sep` ~ month ~ `date-sep` ~ year } def day = rule { digit2 } @@ -97,7 +97,8 @@ private[parser] trait CommonRules { this: Parser with StringBuilding ⇒ // def `rfc850-date` = rule { `day-name-l` ~ ", " ~ date2 ~ ' ' ~ `time-of-day` ~ " GMT" } - def date2 = rule { day ~ '-' ~ month ~ '-' ~ digit2 } + // per #17714, parse two digit year to https://tools.ietf.org/html/rfc6265#section-5.1.1 + def date2 = rule { day ~ '-' ~ month ~ '-' ~ digit2 ~> (y ⇒ if (y <= 69) y + 2000 else y + 1900) } def `day-name-l` = rule( "Sunday" ~ push(0) | "Monday" ~ push(1) | "Tuesday" ~ push(2) | "Wednesday" ~ push(3) | "Thursday" ~ push(4) | @@ -246,7 +247,7 @@ private[parser] trait CommonRules { this: Parser with StringBuilding ⇒ // https://tools.ietf.org/html/rfc1034#section-3.5 relaxed by https://tools.ietf.org/html/rfc1123#section-2 // to also allow digits at the start of a label def `domain-value` = rule { - capture(oneOrMore(oneOrMore(oneOrMore(ALPHANUM)).separatedBy('-')).separatedBy('.')) ~ OWS + optional('.') ~ capture(oneOrMore(oneOrMore(oneOrMore(ALPHANUM)).separatedBy('-')).separatedBy('.')) ~ OWS } def `path-av` = rule { diff --git a/akka-http-core/src/test/scala/akka/http/impl/model/parser/HttpHeaderSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/model/parser/HttpHeaderSpec.scala index 3f3e9dd77c..8d67fb7132 100644 --- a/akka-http-core/src/test/scala/akka/http/impl/model/parser/HttpHeaderSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/model/parser/HttpHeaderSpec.scala @@ -228,6 +228,12 @@ class HttpHeaderSpec extends FreeSpec with Matchers { "Date" in { "Date: Wed, 13 Jul 2011 08:12:31 GMT" =!= Date(DateTime(2011, 7, 13, 8, 12, 31)) + "Date: Wed, 13-Jul-2011 08:12:31 GMT" =!= Date(DateTime(2011, 7, 13, 8, 12, 31)).renderedTo( + "Wed, 13 Jul 2011 08:12:31 GMT") + "Date: Wed, 13-Jul-11 08:12:31 GMT" =!= Date(DateTime(2011, 7, 13, 8, 12, 31)).renderedTo( + "Wed, 13 Jul 2011 08:12:31 GMT") + "Date: Mon, 13-Jul-70 08:12:31 GMT" =!= Date(DateTime(1970, 7, 13, 8, 12, 31)).renderedTo( + "Mon, 13 Jul 1970 08:12:31 GMT") "Date: Fri, 23 Mar 1804 12:11:10 UTC" =!= Date(DateTime(1804, 3, 23, 12, 11, 10)).renderedTo( "Fri, 23 Mar 1804 12:11:10 GMT") } @@ -612,4 +618,4 @@ class HttpHeaderSpec extends FreeSpec with Matchers { val info = result.errors.head fail(s"Input `${header.header}` failed to parse:\n${info.summary}\n${info.detail}") } -} \ No newline at end of file +}