Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(417)

Side by Side Diff: pkg/http_parser/lib/http_parser.dart

Issue 276823002: pkg/http_parser: created mini lib for http_date (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: changelog and pubspec tweaks Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/http_parser/CHANGELOG.md ('k') | pkg/http_parser/lib/src/http_date.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library http_parser; 5 library http_parser;
6 6
7 import 'package:string_scanner/string_scanner.dart'; 7 export 'src/http_date.dart';
8
9 export 'src/media_type.dart'; 8 export 'src/media_type.dart';
10 export 'src/web_socket.dart'; 9 export 'src/web_socket.dart';
11
12 const _WEEKDAYS = const ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
13 const _MONTHS = const ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
14 "Sep", "Oct", "Nov", "Dec"];
15
16 final _shortWeekdayRegExp = new RegExp(r"Mon|Tue|Wed|Thu|Fri|Sat|Sun");
17 final _longWeekdayRegExp =
18 new RegExp(r"Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday");
19 final _monthRegExp =
20 new RegExp(r"Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec");
21 final _digitRegExp = new RegExp(r"\d+");
22
23 // TODO(nweiz): Move this into an http_parser package.
24 /// Return a HTTP-formatted string representation of [date].
25 ///
26 /// This follows [RFC 822](http://tools.ietf.org/html/rfc822) as updated by [RFC
27 /// 1123](http://tools.ietf.org/html/rfc1123).
28 String formatHttpDate(DateTime date) {
29 date = date.toUtc();
30 var buffer = new StringBuffer()
31 ..write(_WEEKDAYS[date.weekday - 1])
32 ..write(", ")
33 ..write(date.day.toString())
34 ..write(" ")
35 ..write(_MONTHS[date.month - 1])
36 ..write(" ")
37 ..write(date.year.toString())
38 ..write(date.hour < 9 ? " 0" : " ")
39 ..write(date.hour.toString())
40 ..write(date.minute < 9 ? ":0" : ":")
41 ..write(date.minute.toString())
42 ..write(date.second < 9 ? ":0" : ":")
43 ..write(date.second.toString())
44 ..write(" GMT");
45 return buffer.toString();
46 }
47
48 // TODO(nweiz): Move this into an http_parser package.
49 /// Parses an HTTP-formatted date into a UTC [DateTime].
50 ///
51 /// This follows [RFC
52 /// 2616](http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3). It will
53 /// throw a [FormatException] if [date] is invalid.
54 DateTime parseHttpDate(String date) {
55 try {
56 var scanner = new StringScanner(date);
57
58 if (scanner.scan(_longWeekdayRegExp)) {
59 // RFC 850 starts with a long weekday.
60 scanner.expect(", ");
61 var day = _parseInt(scanner, 2);
62 scanner.expect("-");
63 var month = _parseMonth(scanner);
64 scanner.expect("-");
65 var year = 1900 + _parseInt(scanner, 2);
66 scanner.expect(" ");
67 var time = _parseTime(scanner);
68 scanner.expect(" GMT");
69 scanner.expectDone();
70
71 return _makeDateTime(year, month, day, time);
72 }
73
74 // RFC 1123 and asctime both start with a short weekday.
75 scanner.expect(_shortWeekdayRegExp);
76 if (scanner.scan(", ")) {
77 // RFC 1123 follows the weekday with a comma.
78 var day = _parseInt(scanner, 2);
79 scanner.expect(" ");
80 var month = _parseMonth(scanner);
81 scanner.expect(" ");
82 var year = _parseInt(scanner, 4);
83 scanner.expect(" ");
84 var time = _parseTime(scanner);
85 scanner.expect(" GMT");
86 scanner.expectDone();
87
88 return _makeDateTime(year, month, day, time);
89 }
90
91 // asctime follows the weekday with a space.
92 scanner.expect(" ");
93 var month = _parseMonth(scanner);
94 scanner.expect(" ");
95 var day = scanner.scan(" ") ?
96 _parseInt(scanner, 1) :
97 _parseInt(scanner, 2);
98 scanner.expect(" ");
99 var time = _parseTime(scanner);
100 scanner.expect(" ");
101 var year = _parseInt(scanner, 4);
102 scanner.expectDone();
103
104 return _makeDateTime(year, month, day, time);
105 } on FormatException catch (error) {
106 throw new FormatException('Invalid HTTP date "$date": ${error.message}');
107 }
108 }
109
110 /// Parses a short-form month name to a form accepted by [DateTime].
111 int _parseMonth(StringScanner scanner) {
112 scanner.expect(_monthRegExp);
113 // DateTime uses 1-indexed months.
114 return _MONTHS.indexOf(scanner.lastMatch[0]) + 1;
115 }
116
117 /// Parses an int an enforces that it has exactly [digits] digits.
118 int _parseInt(StringScanner scanner, int digits) {
119 scanner.expect(_digitRegExp);
120 if (scanner.lastMatch[0].length != digits) {
121 scanner.error("expected a $digits-digit number.");
122 }
123
124 return int.parse(scanner.lastMatch[0]);
125 }
126
127 /// Parses an timestamp of the form "HH:MM:SS" on a 24-hour clock.
128 DateTime _parseTime(StringScanner scanner) {
129 var hours = _parseInt(scanner, 2);
130 if (hours >= 24) scanner.error("hours may not be greater than 24.");
131 scanner.expect(':');
132
133 var minutes = _parseInt(scanner, 2);
134 if (minutes >= 60) scanner.error("minutes may not be greater than 60.");
135 scanner.expect(':');
136
137 var seconds = _parseInt(scanner, 2);
138 if (seconds >= 60) scanner.error("seconds may not be greater than 60.");
139
140 return new DateTime(1, 1, 1, hours, minutes, seconds);
141 }
142
143 /// Returns a UTC [DateTime] from the given components.
144 ///
145 /// Validates that [day] is a valid day for [month]. If it's not, throws a
146 /// [FormatException].
147 DateTime _makeDateTime(int year, int month, int day, DateTime time) {
148 var dateTime = new DateTime.utc(
149 year, month, day, time.hour, time.minute, time.second);
150
151 // If [day] was too large, it will cause [month] to overflow.
152 if (dateTime.month != month) {
153 throw new FormatException("invalid day '$day' for month '$month'.");
154 }
155 return dateTime;
156 }
OLDNEW
« no previous file with comments | « pkg/http_parser/CHANGELOG.md ('k') | pkg/http_parser/lib/src/http_date.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698