Mercurial Hosting > luan
view src/luan/webserver/RequestHeadParser.java @ 1137:c123ee15f99b
add webserver
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Mon, 29 Jan 2018 18:49:59 -0700 |
parents | |
children | 3bf5190b3c77 |
line wrap: on
line source
package luan.webserver; import luan.lib.parser.Parser; import luan.lib.parser.ParseException; final class RequestHeadParser { static Request parse(String text) throws ParseException { RequestHeadParser rhp = new RequestHeadParser(text); rhp.parse(); return rhp.request; } private final Request request = new Request(); private final Parser parser; private RequestHeadParser(String text) { this.parser = new Parser(text); request.rawHead = text; } private void parse() throws ParseException { parseRequestLine(); while( !parser.match("\r\n") ) { parserHeaderField(); } } private void parseRequestLine() throws ParseException { parseMethod(); require( parser.match(' ') ); parsePath(); require( parser.match(' ') ); parseProtocol(); require( parser.match("\r\n") ); } private void parseMethod() throws ParseException { int start = parser.currentIndex(); if( !methodChar() ) throw new ParseException(parser,"no method"); while( methodChar() ); request.method = parser.textFrom(start); } private boolean methodChar() { return parser.inCharRange('A','Z'); } private void parsePath() throws ParseException { int start = parser.currentIndex(); if( !parser.match('/') ) throw new ParseException(parser,"bad path"); while( parser.inCharRange('A','Z') || parser.inCharRange('a','z') || parser.inCharRange('0','9') || parser.anyOf("-._~:/?#[]@!$&'()*+,;=`.") ); request.path = parser.textFrom(start); } private void parseProtocol() throws ParseException { int start = parser.currentIndex(); if( !( parser.match("HTTP/") && parser.inCharRange('0','9') && parser.match('.') && parser.inCharRange('0','9') ) ) throw new ParseException(parser,"bad protocol"); request.protocol = parser.textFrom(start); } private void parserHeaderField() throws ParseException { String name = parseName(); require( parser.match(':') ); while( parser.anyOf(" \t") ); String value = parseValue(); while( parser.anyOf(" \t") ); require( parser.match("\r\n") ); request.headers.put(name,value); } private String parseName() throws ParseException { StringBuilder buf = new StringBuilder(); boolean cap = true; require( tokenChar() ); do { char c = parser.lastChar(); if( c == '-' ) { cap = true; } else if( cap ) { c = Character.toUpperCase(c); cap = false; } else { c = Character.toLowerCase(c); } buf.append(c); } while( tokenChar() ); return buf.toString(); } private String parseValue() { int start = parser.currentIndex(); while( !testEndOfValue() ) parser.anyChar(); return parser.textFrom(start); } private boolean testEndOfValue() { parser.begin(); while( parser.anyOf(" \t") ); boolean b = parser.endOfInput() || parser.anyOf("\r\n"); parser.failure(); // rollback return b; } private void require(boolean b) throws ParseException { if( !b ) throw new ParseException(parser,"failed"); } boolean tokenChar() { if( parser.endOfInput() ) return false; char c = parser.currentChar(); if( 32 <= c && c <= 126 && "()<>@,;:\\\"/[]?={} \t\r\n".indexOf(c) == -1 ) { parser.anyChar(); return true; } else { return false; } } }