diff src/luan/webserver/RequestHeadParser.java @ 1143:3bf5190b3c77

webserver - handle GET params
author Franklin Schmidt <fschmidt@gmail.com>
date Tue, 30 Jan 2018 23:53:28 -0700
parents c123ee15f99b
children
line wrap: on
line diff
--- a/src/luan/webserver/RequestHeadParser.java	Tue Jan 30 18:02:47 2018 -0700
+++ b/src/luan/webserver/RequestHeadParser.java	Tue Jan 30 23:53:28 2018 -0700
@@ -1,5 +1,9 @@
 package luan.webserver;
 
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.util.List;
+import java.util.ArrayList;
 import luan.lib.parser.Parser;
 import luan.lib.parser.ParseException;
 
@@ -31,7 +35,7 @@
 	private void parseRequestLine() throws ParseException {
 		parseMethod();
 		require( parser.match(' ') );
-		parsePath();
+		parseRawPath();
 		require( parser.match(' ') );
 		parseProtocol();
 		require( parser.match("\r\n") );
@@ -49,17 +53,64 @@
 		return parser.inCharRange('A','Z');
 	}
 
+	private void parseRawPath() throws ParseException {
+		int start = parser.currentIndex();
+		parsePath();
+		if( parser.match('?') )
+			parseQuery();
+		request.rawPath = parser.textFrom(start);
+	}
+
 	private void parsePath() throws ParseException {
 		int start = parser.currentIndex();
 		if( !parser.match('/') )
 			throw new ParseException(parser,"bad path");
-		while(
-			parser.inCharRange('A','Z')
+		while( safePathChar() || parser.anyOf("&=") );
+		request.path = decode( parser.textFrom(start) );
+	}
+
+	private void parseQuery() throws ParseException {
+		while(true) {
+			while( parser.match('&') );
+			int start = parser.currentIndex();
+			if( !queryChar() )
+				return;
+			while( queryChar() );
+			String name = decode( parser.textFrom(start) );
+			String value;
+			if( parser.match('=') ) {
+				start = parser.currentIndex();
+				while( queryChar() );
+				value = decode( parser.textFrom(start) );
+			} else {
+				value = "";
+			}
+			Object current = request.parameters.get(name);
+			if( current == null ) {
+				request.parameters.put(name,value);
+			} else if( current instanceof List ) {
+				List list = (List)current;
+				list.add(value);
+			} else {
+				List list = new ArrayList();
+				list.add(current);
+				list.add(value);
+				request.parameters.put(name,list);
+			}
+		}
+	}
+
+	private boolean queryChar() {
+		return safePathChar() || parser.anyOf("?");
+	}
+
+	// where did I get this?
+	private boolean safePathChar() {
+		return parser.inCharRange('A','Z')
 			|| parser.inCharRange('a','z')
 			|| parser.inCharRange('0','9')
-			|| parser.anyOf("-._~:/?#[]@!$&'()*+,;=`.")
-		);
-		request.path = parser.textFrom(start);
+			|| parser.anyOf("-._~:/[]@!$'()*+,;`.%")
+		;
 	}
 
 	private void parseProtocol() throws ParseException {
@@ -135,4 +186,12 @@
 			return false;
 		}
 	}
+
+	private static String decode(String s) {
+		try {
+			return URLDecoder.decode(s,"UTF-8");
+		} catch(UnsupportedEncodingException e) {
+			throw new RuntimeException(e);
+		}
+	}
 }