Mercurial Hosting > luan
annotate src/luan/webserver/RequestParser.java @ 1146:2dda3c92a473
webserver - implement cookies
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Thu, 01 Feb 2018 03:08:21 -0700 |
parents | 12ececf30597 |
children | 30d87b7d1d62 |
rev | line source |
---|---|
1137 | 1 package luan.webserver; |
2 | |
1143
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
3 import java.util.List; |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
4 import java.util.ArrayList; |
1137 | 5 import luan.lib.parser.Parser; |
6 import luan.lib.parser.ParseException; | |
7 | |
8 | |
1144
ae0a048f3bc7
webserver - handle POST params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1143
diff
changeset
|
9 final class RequestParser { |
ae0a048f3bc7
webserver - handle POST params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1143
diff
changeset
|
10 private final Request request; |
ae0a048f3bc7
webserver - handle POST params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1143
diff
changeset
|
11 private Parser parser; |
1137 | 12 |
1144
ae0a048f3bc7
webserver - handle POST params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1143
diff
changeset
|
13 RequestParser(Request request) { |
ae0a048f3bc7
webserver - handle POST params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1143
diff
changeset
|
14 this.request = request; |
1137 | 15 } |
16 | |
1145 | 17 void parseUrlencoded() throws ParseException { |
1144
ae0a048f3bc7
webserver - handle POST params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1143
diff
changeset
|
18 this.parser = new Parser(request.body); |
ae0a048f3bc7
webserver - handle POST params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1143
diff
changeset
|
19 parseQuery(); |
ae0a048f3bc7
webserver - handle POST params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1143
diff
changeset
|
20 require( parser.endOfInput() ); |
1137 | 21 } |
22 | |
1144
ae0a048f3bc7
webserver - handle POST params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1143
diff
changeset
|
23 void parseHead() throws ParseException { |
ae0a048f3bc7
webserver - handle POST params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1143
diff
changeset
|
24 this.parser = new Parser(request.rawHead); |
1137 | 25 parseRequestLine(); |
26 while( !parser.match("\r\n") ) { | |
27 parserHeaderField(); | |
28 } | |
1146
2dda3c92a473
webserver - implement cookies
Franklin Schmidt <fschmidt@gmail.com>
parents:
1145
diff
changeset
|
29 parseCookies(); |
1137 | 30 } |
31 | |
32 private void parseRequestLine() throws ParseException { | |
33 parseMethod(); | |
34 require( parser.match(' ') ); | |
1143
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
35 parseRawPath(); |
1137 | 36 require( parser.match(' ') ); |
37 parseProtocol(); | |
38 require( parser.match("\r\n") ); | |
39 } | |
40 | |
41 private void parseMethod() throws ParseException { | |
42 int start = parser.currentIndex(); | |
43 if( !methodChar() ) | |
44 throw new ParseException(parser,"no method"); | |
45 while( methodChar() ); | |
46 request.method = parser.textFrom(start); | |
47 } | |
48 | |
49 private boolean methodChar() { | |
50 return parser.inCharRange('A','Z'); | |
51 } | |
52 | |
1143
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
53 private void parseRawPath() throws ParseException { |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
54 int start = parser.currentIndex(); |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
55 parsePath(); |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
56 if( parser.match('?') ) |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
57 parseQuery(); |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
58 request.rawPath = parser.textFrom(start); |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
59 } |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
60 |
1137 | 61 private void parsePath() throws ParseException { |
62 int start = parser.currentIndex(); | |
63 if( !parser.match('/') ) | |
64 throw new ParseException(parser,"bad path"); | |
1143
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
65 while( safePathChar() || parser.anyOf("&=") ); |
1146
2dda3c92a473
webserver - implement cookies
Franklin Schmidt <fschmidt@gmail.com>
parents:
1145
diff
changeset
|
66 request.path = Util.urlDecode( parser.textFrom(start) ); |
1143
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
67 } |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
68 |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
69 private void parseQuery() throws ParseException { |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
70 while(true) { |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
71 while( parser.match('&') ); |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
72 int start = parser.currentIndex(); |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
73 if( !queryChar() ) |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
74 return; |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
75 while( queryChar() ); |
1146
2dda3c92a473
webserver - implement cookies
Franklin Schmidt <fschmidt@gmail.com>
parents:
1145
diff
changeset
|
76 String name = Util.urlDecode( parser.textFrom(start) ); |
1143
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
77 String value; |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
78 if( parser.match('=') ) { |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
79 start = parser.currentIndex(); |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
80 while( queryChar() ); |
1146
2dda3c92a473
webserver - implement cookies
Franklin Schmidt <fschmidt@gmail.com>
parents:
1145
diff
changeset
|
81 value = Util.urlDecode( parser.textFrom(start) ); |
1143
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
82 } else { |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
83 value = ""; |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
84 } |
1146
2dda3c92a473
webserver - implement cookies
Franklin Schmidt <fschmidt@gmail.com>
parents:
1145
diff
changeset
|
85 Util.add(request.parameters,name,value); |
1143
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
86 } |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
87 } |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
88 |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
89 private boolean queryChar() { |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
90 return safePathChar() || parser.anyOf("?"); |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
91 } |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
92 |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
93 // where did I get this? |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
94 private boolean safePathChar() { |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
95 return parser.inCharRange('A','Z') |
1137 | 96 || parser.inCharRange('a','z') |
97 || parser.inCharRange('0','9') | |
1143
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
98 || parser.anyOf("-._~:/[]@!$'()*+,;`.%") |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
99 ; |
1137 | 100 } |
101 | |
102 private void parseProtocol() throws ParseException { | |
103 int start = parser.currentIndex(); | |
104 if( !( | |
105 parser.match("HTTP/") | |
106 && parser.inCharRange('0','9') | |
107 && parser.match('.') | |
108 && parser.inCharRange('0','9') | |
109 ) ) | |
110 throw new ParseException(parser,"bad protocol"); | |
111 request.protocol = parser.textFrom(start); | |
112 } | |
113 | |
114 | |
115 private void parserHeaderField() throws ParseException { | |
116 String name = parseName(); | |
117 require( parser.match(':') ); | |
118 while( parser.anyOf(" \t") ); | |
119 String value = parseValue(); | |
120 while( parser.anyOf(" \t") ); | |
121 require( parser.match("\r\n") ); | |
1146
2dda3c92a473
webserver - implement cookies
Franklin Schmidt <fschmidt@gmail.com>
parents:
1145
diff
changeset
|
122 Util.add(request.headers,name,value); |
1137 | 123 } |
124 | |
125 private String parseName() throws ParseException { | |
126 StringBuilder buf = new StringBuilder(); | |
127 boolean cap = true; | |
128 require( tokenChar() ); | |
129 do { | |
130 char c = parser.lastChar(); | |
131 if( c == '-' ) { | |
132 cap = true; | |
133 } else if( cap ) { | |
134 c = Character.toUpperCase(c); | |
135 cap = false; | |
136 } else { | |
137 c = Character.toLowerCase(c); | |
138 } | |
139 buf.append(c); | |
140 } while( tokenChar() ); | |
141 return buf.toString(); | |
142 } | |
143 | |
144 private String parseValue() { | |
145 int start = parser.currentIndex(); | |
146 while( !testEndOfValue() ) | |
147 parser.anyChar(); | |
148 return parser.textFrom(start); | |
149 } | |
150 | |
151 private boolean testEndOfValue() { | |
152 parser.begin(); | |
153 while( parser.anyOf(" \t") ); | |
154 boolean b = parser.endOfInput() || parser.anyOf("\r\n"); | |
155 parser.failure(); // rollback | |
156 return b; | |
157 } | |
158 | |
159 private void require(boolean b) throws ParseException { | |
160 if( !b ) | |
161 throw new ParseException(parser,"failed"); | |
162 } | |
163 | |
164 boolean tokenChar() { | |
165 if( parser.endOfInput() ) | |
166 return false; | |
167 char c = parser.currentChar(); | |
168 if( 32 <= c && c <= 126 && "()<>@,;:\\\"/[]?={} \t\r\n".indexOf(c) == -1 ) { | |
169 parser.anyChar(); | |
170 return true; | |
171 } else { | |
172 return false; | |
173 } | |
174 } | |
1143
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
175 |
1146
2dda3c92a473
webserver - implement cookies
Franklin Schmidt <fschmidt@gmail.com>
parents:
1145
diff
changeset
|
176 |
2dda3c92a473
webserver - implement cookies
Franklin Schmidt <fschmidt@gmail.com>
parents:
1145
diff
changeset
|
177 private void parseCookies() throws ParseException { |
2dda3c92a473
webserver - implement cookies
Franklin Schmidt <fschmidt@gmail.com>
parents:
1145
diff
changeset
|
178 String text = (String)request.headers.get("Cookie"); |
2dda3c92a473
webserver - implement cookies
Franklin Schmidt <fschmidt@gmail.com>
parents:
1145
diff
changeset
|
179 if( text == null ) |
2dda3c92a473
webserver - implement cookies
Franklin Schmidt <fschmidt@gmail.com>
parents:
1145
diff
changeset
|
180 return; |
2dda3c92a473
webserver - implement cookies
Franklin Schmidt <fschmidt@gmail.com>
parents:
1145
diff
changeset
|
181 this.parser = new Parser(text); |
2dda3c92a473
webserver - implement cookies
Franklin Schmidt <fschmidt@gmail.com>
parents:
1145
diff
changeset
|
182 while(true) { |
2dda3c92a473
webserver - implement cookies
Franklin Schmidt <fschmidt@gmail.com>
parents:
1145
diff
changeset
|
183 int start = parser.currentIndex(); |
2dda3c92a473
webserver - implement cookies
Franklin Schmidt <fschmidt@gmail.com>
parents:
1145
diff
changeset
|
184 while( parser.noneOf("=;") ); |
2dda3c92a473
webserver - implement cookies
Franklin Schmidt <fschmidt@gmail.com>
parents:
1145
diff
changeset
|
185 String name = Util.urlDecode( parser.textFrom(start) ); |
2dda3c92a473
webserver - implement cookies
Franklin Schmidt <fschmidt@gmail.com>
parents:
1145
diff
changeset
|
186 if( parser.match('=') ) { |
2dda3c92a473
webserver - implement cookies
Franklin Schmidt <fschmidt@gmail.com>
parents:
1145
diff
changeset
|
187 start = parser.currentIndex(); |
2dda3c92a473
webserver - implement cookies
Franklin Schmidt <fschmidt@gmail.com>
parents:
1145
diff
changeset
|
188 while( parser.noneOf(";") ); |
2dda3c92a473
webserver - implement cookies
Franklin Schmidt <fschmidt@gmail.com>
parents:
1145
diff
changeset
|
189 String value = Util.urlDecode( parser.textFrom(start) ); |
2dda3c92a473
webserver - implement cookies
Franklin Schmidt <fschmidt@gmail.com>
parents:
1145
diff
changeset
|
190 request.cookies.put(name,value); |
2dda3c92a473
webserver - implement cookies
Franklin Schmidt <fschmidt@gmail.com>
parents:
1145
diff
changeset
|
191 } |
2dda3c92a473
webserver - implement cookies
Franklin Schmidt <fschmidt@gmail.com>
parents:
1145
diff
changeset
|
192 if( parser.endOfInput() ) |
2dda3c92a473
webserver - implement cookies
Franklin Schmidt <fschmidt@gmail.com>
parents:
1145
diff
changeset
|
193 return; |
2dda3c92a473
webserver - implement cookies
Franklin Schmidt <fschmidt@gmail.com>
parents:
1145
diff
changeset
|
194 require( parser.match("; ") ); |
1143
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
195 } |
3bf5190b3c77
webserver - handle GET params
Franklin Schmidt <fschmidt@gmail.com>
parents:
1137
diff
changeset
|
196 } |
1146
2dda3c92a473
webserver - implement cookies
Franklin Schmidt <fschmidt@gmail.com>
parents:
1145
diff
changeset
|
197 |
1137 | 198 } |