All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.jetty.http.HttpURI Maven / Gradle / Ivy

There is a newer version: 11.0.0.beta1
Show newest version
//
//  ========================================================================
//  Copyright (c) 1995-2018 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.http;

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

import org.eclipse.jetty.util.MultiMap;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.UrlEncoded;
import org.eclipse.jetty.util.Utf8StringBuilder;


/* ------------------------------------------------------------ */
/** Http URI.
 * Parse a HTTP URI from a string or byte array.  Given a URI
 * http://user@host:port/path/info;param?query#fragment
 * this class will split it into the following undecoded optional elements:
    *
  • {@link #getScheme()} - http:
  • *
  • {@link #getAuthority()} - //name@host:port
  • *
  • {@link #getHost()} - host
  • *
  • {@link #getPort()} - port
  • *
  • {@link #getPath()} - /path/info
  • *
  • {@link #getParam()} - param
  • *
  • {@link #getQuery()} - query
  • *
  • {@link #getFragment()} - fragment
  • *
* */ public class HttpURI { private static final byte[] __empty={}; private final static int START=0, AUTH_OR_PATH=1, SCHEME_OR_PATH=2, AUTH=4, IPV6=5, PORT=6, PATH=7, PARAM=8, QUERY=9, ASTERISK=10; final Charset _charset; boolean _partial=false; byte[] _raw=__empty; String _rawString; int _scheme; int _authority; int _host; int _port; int _portValue; int _path; int _param; int _query; int _fragment; int _end; boolean _encoded=false; public HttpURI() { _charset = URIUtil.__CHARSET; } public HttpURI(Charset charset) { _charset = charset; } /* ------------------------------------------------------------ */ /** * @param parsePartialAuth If True, parse auth without prior scheme, else treat all URIs starting with / as paths */ public HttpURI(boolean parsePartialAuth) { _partial=parsePartialAuth; _charset = URIUtil.__CHARSET; } public HttpURI(String raw) { _rawString=raw; byte[] b = raw.getBytes(StandardCharsets.UTF_8); parse(b,0,b.length); _charset = URIUtil.__CHARSET; } public HttpURI(byte[] raw,int offset, int length) { parse2(raw,offset,length); _charset = URIUtil.__CHARSET; } public HttpURI(URI uri) { parse(uri.toASCIIString()); _charset = URIUtil.__CHARSET; } public void parse(String raw) { byte[] b = StringUtil.getUtf8Bytes(raw); parse2(b,0,b.length); _rawString=raw; } public void parseConnect(String raw) { byte[] b = StringUtil.getBytes(raw); parseConnect(b,0,b.length); _rawString=raw; } public void parse(byte[] raw,int offset, int length) { _rawString=null; parse2(raw,offset,length); } public void parseConnect(byte[] raw,int offset, int length) { _rawString=null; _encoded=false; _raw=raw; int i=offset; int e=offset+length; int state=AUTH; _end=offset+length; _scheme=offset; _authority=offset; _host=offset; _port=_end; _portValue=-1; _path=_end; _param=_end; _query=_end; _fragment=_end; loop: while (i6 && c=='t') { if (_raw[offset+3]==':') { s=offset+3; i=offset+4; c=':'; } else if (_raw[offset+4]==':') { s=offset+4; i=offset+5; c=':'; } else if (_raw[offset+5]==':') { s=offset+5; i=offset+6; c=':'; } } switch (c) { case ':': { m = i++; _authority = m; _path = m; c = (char)(0xff & _raw[i]); if (c == '/') state = AUTH_OR_PATH; else { _host = m; _port = m; state = PATH; } break; } case '/': { state = PATH; break; } case ';': { _param = s; state = PARAM; break; } case '?': { _param = s; _query = s; state = QUERY; break; } case '#': { _param = s; _query = s; _fragment = s; break; } } continue; } case AUTH: { switch (c) { case '/': { m = s; _path = m; _port = _path; state = PATH; break; } case '@': { _host = i; break; } case ':': { _port = s; state = PORT; break; } case '[': { state = IPV6; break; } } continue; } case IPV6: { switch (c) { case '/': { throw new IllegalArgumentException("No closing ']' for " + new String(_raw,offset,length,_charset)); } case ']': { state = AUTH; break; } } continue; } case PORT: { if (c=='/') { m=s; _path=m; if (_port<=_authority) _port=_path; state=PATH; } continue; } case PATH: { switch (c) { case ';': { _param = s; state = PARAM; break; } case '?': { _param = s; _query = s; state = QUERY; break; } case '#': { _param = s; _query = s; _fragment = s; break state; } case '%': { _encoded=true; } } continue; } case PARAM: { switch (c) { case '?': { _query = s; state = QUERY; break; } case '#': { _query = s; _fragment = s; break state; } } continue; } case QUERY: { if (c=='#') { _fragment=s; break state; } continue; } case ASTERISK: { throw new IllegalArgumentException("only '*'"); } } } if (_port<_path) _portValue=TypeUtil.parseInt(_raw, _port+1, _path-_port-1,10); } public String getScheme() { if (_scheme==_authority) return null; int l=_authority-_scheme; if (l==5 && _raw[_scheme]=='h' && _raw[_scheme+1]=='t' && _raw[_scheme+2]=='t' && _raw[_scheme+3]=='p' ) return HttpScheme.HTTP.asString(); if (l==6 && _raw[_scheme]=='h' && _raw[_scheme+1]=='t' && _raw[_scheme+2]=='t' && _raw[_scheme+3]=='p' && _raw[_scheme+4]=='s' ) return HttpScheme.HTTPS.asString(); return new String(_raw,_scheme,_authority-_scheme-1,_charset); } public String getAuthority() { if (_authority==_path) return null; return new String(_raw,_authority,_path-_authority,_charset); } public String getHost() { if (_host==_port) return null; return new String(_raw,_host,_port-_host,_charset); } public int getPort() { return _portValue; } public String getPath() { if (_path==_param) return null; return new String(_raw,_path,_param-_path,_charset); } public String getDecodedPath() { if (_path==_param) return null; Utf8StringBuilder utf8b=null; for (int i=_path;i<_param;i++) { byte b = _raw[i]; if (b=='%') { if (utf8b==null) { utf8b=new Utf8StringBuilder(); utf8b.append(_raw,_path,i-_path); } if ((i+2)>=_param) throw new IllegalArgumentException("Bad % encoding: "+this); if (_raw[i+1]=='u') { if ((i+5)>=_param) throw new IllegalArgumentException("Bad %u encoding: "+this); try { String unicode = new String(Character.toChars(TypeUtil.parseInt(_raw,i+2,4,16))); utf8b.getStringBuilder().append(unicode); i+=5; } catch(Exception e) { throw new RuntimeException(e); } } else { b=(byte)(0xff&TypeUtil.parseInt(_raw,i+1,2,16)); utf8b.append(b); i+=2; } continue; } else if (utf8b!=null) { utf8b.append(b); } } if (utf8b==null) return StringUtil.toUTF8String(_raw, _path, _param-_path); return utf8b.toString(); } public String getDecodedPath(String encoding) { return getDecodedPath(Charset.forName(encoding)); } public String getDecodedPath(Charset encoding) { if (_path==_param) return null; int length = _param-_path; byte[] bytes=null; int n=0; for (int i=_path;i<_param;i++) { byte b = _raw[i]; if (b=='%') { if (bytes==null) { bytes=new byte[length]; System.arraycopy(_raw,_path,bytes,0,n); } if ((i+2)>=_param) throw new IllegalArgumentException("Bad % encoding: "+this); if (_raw[i+1]=='u') { if ((i+5)>=_param) throw new IllegalArgumentException("Bad %u encoding: "+this); try { String unicode = new String(Character.toChars(TypeUtil.parseInt(_raw,i+2,4,16))); byte[] encoded = unicode.getBytes(encoding); System.arraycopy(encoded,0,bytes,n,encoded.length); n+=encoded.length; i+=5; } catch(Exception e) { throw new RuntimeException(e); } } else { b=(byte)(0xff&TypeUtil.parseInt(_raw,i+1,2,16)); bytes[n++]=b; i+=2; } continue; } else if (bytes==null) { n++; continue; } bytes[n++]=b; } if (bytes==null) return new String(_raw,_path,_param-_path,encoding); return new String(bytes,0,n,encoding); } public String getPathAndParam() { if (_path==_query) return null; return new String(_raw,_path,_query-_path,_charset); } public String getCompletePath() { if (_path==_end) return null; return new String(_raw,_path,_end-_path,_charset); } public String getParam() { if (_param==_query) return null; return new String(_raw,_param+1,_query-_param-1,_charset); } public String getQuery() { if (_query==_fragment) return null; return new String(_raw,_query+1,_fragment-_query-1,_charset); } public String getQuery(String encoding) { if (_query==_fragment) return null; return StringUtil.toString(_raw,_query+1,_fragment-_query-1,encoding); } public boolean hasQuery() { return (_fragment>_query); } public String getFragment() { if (_fragment==_end) return null; return new String(_raw,_fragment+1,_end-_fragment-1,_charset); } public void decodeQueryTo(MultiMap parameters) { if (_query==_fragment) return; if (_charset.equals(StandardCharsets.UTF_8)) UrlEncoded.decodeUtf8To(_raw,_query+1,_fragment-_query-1,parameters); else UrlEncoded.decodeTo(new String(_raw,_query+1,_fragment-_query-1,_charset),parameters,_charset,-1); } public void decodeQueryTo(MultiMap parameters, String encoding) throws UnsupportedEncodingException { if (_query==_fragment) return; if (encoding==null || StringUtil.isUTF8(encoding)) UrlEncoded.decodeUtf8To(_raw,_query+1,_fragment-_query-1,parameters); else UrlEncoded.decodeTo(StringUtil.toString(_raw,_query+1,_fragment-_query-1,encoding),parameters,encoding,-1); } public void decodeQueryTo(MultiMap parameters, Charset encoding) throws UnsupportedEncodingException { if (_query==_fragment) return; if (encoding==null || StandardCharsets.UTF_8.equals(encoding)) UrlEncoded.decodeUtf8To(_raw,_query+1,_fragment-_query-1,parameters); else UrlEncoded.decodeTo(new String(_raw,_query+1,_fragment-_query-1,encoding),parameters,encoding,-1); } public void clear() { _scheme=_authority=_host=_port=_path=_param=_query=_fragment=_end=0; _raw=__empty; _rawString=""; _encoded=false; } @Override public String toString() { if (_rawString==null) _rawString=new String(_raw,_scheme,_end-_scheme,_charset); return _rawString; } public void writeTo(Utf8StringBuilder buf) { buf.append(_raw,_scheme,_end-_scheme); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy