Merge remote-tracking branch 'origin/jetty-9.3.x' into jetty-9.4.x
This commit is contained in:
commit
c6e910cf12
|
@ -41,11 +41,18 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
/** MIME Type enum and utilities
|
||||
*
|
||||
*/
|
||||
public class MimeTypes
|
||||
{
|
||||
/* ------------------------------------------------------------ */
|
||||
private static final Logger LOG = Log.getLogger(MimeTypes.class);
|
||||
private static final Trie<ByteBuffer> TYPES= new ArrayTrie<ByteBuffer>(512);
|
||||
private static final Map<String,String> __dftMimeMap = new HashMap<String,String>();
|
||||
private static final Map<String,String> __inferredEncodings = new HashMap<String,String>();
|
||||
private static final Map<String,String> __assumedEncodings = new HashMap<String,String>();
|
||||
|
||||
public enum Type
|
||||
{
|
||||
FORM_ENCODED("application/x-www-form-urlencoded"),
|
||||
|
@ -70,8 +77,8 @@ public class MimeTypes
|
|||
TEXT_JSON_8859_1("text/json;charset=iso-8859-1",TEXT_JSON),
|
||||
TEXT_JSON_UTF_8("text/json;charset=utf-8",TEXT_JSON),
|
||||
|
||||
APPLICATION_JSON_8859_1("text/json;charset=iso-8859-1",APPLICATION_JSON),
|
||||
APPLICATION_JSON_UTF_8("text/json;charset=utf-8",APPLICATION_JSON);
|
||||
APPLICATION_JSON_8859_1("application/json;charset=iso-8859-1",APPLICATION_JSON),
|
||||
APPLICATION_JSON_UTF_8("application/json;charset=utf-8",APPLICATION_JSON);
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -177,12 +184,7 @@ public class MimeTypes
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private static final Logger LOG = Log.getLogger(MimeTypes.class);
|
||||
public final static Trie<MimeTypes.Type> CACHE= new ArrayTrie<>(512);
|
||||
private final static Trie<ByteBuffer> TYPES= new ArrayTrie<ByteBuffer>(512);
|
||||
private final static Map<String,String> __dftMimeMap = new HashMap<String,String>();
|
||||
private final static Map<String,String> __encodings = new HashMap<String,String>();
|
||||
|
||||
public static final Trie<MimeTypes.Type> CACHE= new ArrayTrie<>(512);
|
||||
static
|
||||
{
|
||||
for (MimeTypes.Type type : MimeTypes.Type.values())
|
||||
|
@ -197,6 +199,9 @@ public class MimeTypes
|
|||
CACHE.put(alt,type);
|
||||
TYPES.put(alt,type.asBuffer());
|
||||
}
|
||||
|
||||
if (type.isCharsetAssumed())
|
||||
__assumedEncodings.put(type.asString(),type.getCharsetString());
|
||||
}
|
||||
|
||||
String resourceName = "org/eclipse/jetty/http/mime.properties";
|
||||
|
@ -240,7 +245,6 @@ public class MimeTypes
|
|||
LOG.debug(e);
|
||||
}
|
||||
|
||||
|
||||
resourceName = "org/eclipse/jetty/http/encoding.properties";
|
||||
try (InputStream stream = MimeTypes.class.getClassLoader().getResourceAsStream(resourceName))
|
||||
{
|
||||
|
@ -254,13 +258,20 @@ public class MimeTypes
|
|||
props.load(reader);
|
||||
props.stringPropertyNames().stream()
|
||||
.filter(t->t!=null)
|
||||
.forEach(t->__encodings.put(t, props.getProperty(t)));
|
||||
.forEach(t->
|
||||
{
|
||||
String charset = props.getProperty(t);
|
||||
if (charset.startsWith("-"))
|
||||
__assumedEncodings.put(t, charset.substring(1));
|
||||
else
|
||||
__inferredEncodings.put(t, props.getProperty(t));
|
||||
});
|
||||
|
||||
if (__encodings.size()==0)
|
||||
if (__inferredEncodings.size()==0)
|
||||
{
|
||||
LOG.warn("Empty encodings at {}", resourceName);
|
||||
}
|
||||
else if (__encodings.size()<props.keySet().size())
|
||||
else if ((__inferredEncodings.size()+__assumedEncodings.size())<props.keySet().size())
|
||||
{
|
||||
LOG.warn("Null or duplicate encodings in resource: {}", resourceName);
|
||||
}
|
||||
|
@ -312,6 +323,43 @@ public class MimeTypes
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the MIME type by filename extension.
|
||||
* Lookup only the static default mime map.
|
||||
* @param filename A file name
|
||||
* @return MIME type matching the longest dot extension of the
|
||||
* file name.
|
||||
*/
|
||||
public static String getDefaultMimeByExtension(String filename)
|
||||
{
|
||||
String type=null;
|
||||
|
||||
if (filename!=null)
|
||||
{
|
||||
int i=-1;
|
||||
while(type==null)
|
||||
{
|
||||
i=filename.indexOf(".",i+1);
|
||||
|
||||
if (i<0 || i>=filename.length())
|
||||
break;
|
||||
|
||||
String ext=StringUtil.asciiToLowerCase(filename.substring(i+1));
|
||||
if (type==null)
|
||||
type=__dftMimeMap.get(ext);
|
||||
}
|
||||
}
|
||||
|
||||
if (type==null)
|
||||
{
|
||||
if (type==null)
|
||||
type=__dftMimeMap.get("*");
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the MIME type by filename extension.
|
||||
* Lookup the content and static default mime maps.
|
||||
* @param filename A file name
|
||||
* @return MIME type matching the longest dot extension of the
|
||||
* file name.
|
||||
|
@ -449,11 +497,44 @@ public class MimeTypes
|
|||
return null;
|
||||
}
|
||||
|
||||
public static String inferCharsetFromContentType(String value)
|
||||
/**
|
||||
* Access a mutable map of mime type to the charset inferred from that content type.
|
||||
* An inferred encoding is used by when encoding/decoding a stream and is
|
||||
* explicitly set in any metadata (eg Content-Type).
|
||||
* @return Map of mime type to charset
|
||||
*/
|
||||
public static Map<String,String> getInferredEncodings()
|
||||
{
|
||||
return __encodings.get(value);
|
||||
return __inferredEncodings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access a mutable map of mime type to the charset assumed for that content type.
|
||||
* An assumed encoding is used by when encoding/decoding a stream, but is not
|
||||
* explicitly set in any metadata (eg Content-Type).
|
||||
* @return Map of mime type to charset
|
||||
*/
|
||||
public static Map<String,String> getAssumedEncodings()
|
||||
{
|
||||
return __inferredEncodings;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static String inferCharsetFromContentType(String contentType)
|
||||
{
|
||||
return getCharsetAssumedFromContentType(contentType);
|
||||
}
|
||||
|
||||
public static String getCharsetInferredFromContentType(String contentType)
|
||||
{
|
||||
return __inferredEncodings.get(contentType);
|
||||
}
|
||||
|
||||
public static String getCharsetAssumedFromContentType(String contentType)
|
||||
{
|
||||
return __assumedEncodings.get(contentType);
|
||||
}
|
||||
|
||||
public static String getContentTypeWithoutCharset(String value)
|
||||
{
|
||||
int end=value.length();
|
||||
|
@ -545,4 +626,5 @@ public class MimeTypes
|
|||
return builder.toString();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
# Mapping of mime type to inferred or assumed charset
|
||||
# inferred charsets are used for encoding/decoding and explicitly set in associated metadata
|
||||
# assumed charsets are used for encoding/decoding, but are not set in associated metadata
|
||||
# In this file, assumed charsets are indicatd with a leading '-'
|
||||
|
||||
text/html=utf-8
|
||||
text/plain=iso-8859-1
|
||||
text/xml=utf-8
|
||||
text/json=utf-8
|
||||
application/xhtml+xml=utf-8
|
||||
application/xhtml+xml=utf-8
|
||||
text/json=-utf-8
|
||||
application/vnd.api+json=-utf-8
|
|
@ -797,7 +797,12 @@ public class Response implements HttpServletResponse
|
|||
public String getCharacterEncoding()
|
||||
{
|
||||
if (_characterEncoding == null)
|
||||
{
|
||||
String encoding = MimeTypes.getCharsetAssumedFromContentType(_contentType);
|
||||
if (encoding!=null)
|
||||
return encoding;
|
||||
_characterEncoding = StringUtil.__ISO_8859_1;
|
||||
}
|
||||
return _characterEncoding;
|
||||
}
|
||||
|
||||
|
@ -837,10 +842,14 @@ public class Response implements HttpServletResponse
|
|||
encoding=_mimeType.getCharsetString();
|
||||
else
|
||||
{
|
||||
encoding = MimeTypes.inferCharsetFromContentType(_contentType);
|
||||
encoding = MimeTypes.getCharsetAssumedFromContentType(_contentType);
|
||||
if (encoding == null)
|
||||
encoding = StringUtil.__ISO_8859_1;
|
||||
setCharacterEncoding(encoding,EncodingFrom.INFERRED);
|
||||
{
|
||||
encoding = MimeTypes.getCharsetInferredFromContentType(_contentType);
|
||||
if (encoding == null)
|
||||
encoding = StringUtil.__ISO_8859_1;
|
||||
setCharacterEncoding(encoding,EncodingFrom.INFERRED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -150,7 +150,7 @@ public class BufferedResponseHandler extends HandlerWrapper
|
|||
}
|
||||
|
||||
// If the mime type is known from the path, then apply mime type filtering
|
||||
String mimeType = context==null?null:context.getMimeType(path);
|
||||
String mimeType = context==null?MimeTypes.getDefaultMimeByExtension(path):context.getMimeType(path);
|
||||
if (mimeType!=null)
|
||||
{
|
||||
mimeType = MimeTypes.getContentTypeWithoutCharset(mimeType);
|
||||
|
|
|
@ -20,9 +20,12 @@ package org.eclipse.jetty.server.handler.gzip;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
import java.util.zip.Deflater;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -66,6 +69,7 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
|
|||
private boolean _checkGzExists = true;
|
||||
private boolean _syncFlush = false;
|
||||
private int _inflateBufferSize = -1;
|
||||
private EnumSet<DispatcherType> _dispatchers = EnumSet.of(DispatcherType.REQUEST);
|
||||
|
||||
// non-static, as other GzipHandler instances may have different configurations
|
||||
private final ThreadLocal<Deflater> _deflater = new ThreadLocal<>();
|
||||
|
@ -130,6 +134,25 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
|
|||
_methods.exclude(m);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public EnumSet<DispatcherType> getDispatcherTypes()
|
||||
{
|
||||
return _dispatchers;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setDispatcherTypes(EnumSet<DispatcherType> dispatchers)
|
||||
{
|
||||
_dispatchers = dispatchers;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setDispatcherTypes(DispatcherType... dispatchers)
|
||||
{
|
||||
_dispatchers = EnumSet.copyOf(Arrays.asList(dispatchers));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Set the mime types.
|
||||
|
@ -395,6 +418,7 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
|
|||
return _minGzipSize;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected HttpField getVaryField()
|
||||
{
|
||||
return _vary;
|
||||
|
@ -429,6 +453,13 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
|
|||
String path = context==null?baseRequest.getRequestURI():URIUtil.addPaths(baseRequest.getServletPath(),baseRequest.getPathInfo());
|
||||
LOG.debug("{} handle {} in {}",this,baseRequest,context);
|
||||
|
||||
if (!_dispatchers.contains(baseRequest.getDispatcherType()))
|
||||
{
|
||||
LOG.debug("{} excluded by dispatcherType {}",this,baseRequest.getDispatcherType());
|
||||
_handler.handle(target,baseRequest, request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle request inflation
|
||||
if (_inflateBufferSize>0)
|
||||
{
|
||||
|
@ -442,8 +473,8 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
|
|||
}
|
||||
}
|
||||
|
||||
HttpOutput out = baseRequest.getResponse().getHttpOutput();
|
||||
// Are we already being gzipped?
|
||||
HttpOutput out = baseRequest.getResponse().getHttpOutput();
|
||||
HttpOutput.Interceptor interceptor = out.getInterceptor();
|
||||
while (interceptor!=null)
|
||||
{
|
||||
|
@ -474,7 +505,7 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
|
|||
}
|
||||
|
||||
// Exclude non compressible mime-types known from URI extension. - no Vary because no matter what client, this URI is always excluded
|
||||
String mimeType = context==null?null:context.getMimeType(path);
|
||||
String mimeType = context==null?MimeTypes.getDefaultMimeByExtension(path):context.getMimeType(path);
|
||||
if (mimeType!=null)
|
||||
{
|
||||
mimeType = MimeTypes.getContentTypeWithoutCharset(mimeType);
|
||||
|
|
|
@ -278,6 +278,45 @@ public class ResponseTest
|
|||
response.getWriter();
|
||||
assertEquals("application/json",response.getContentType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInferredCharset() throws Exception
|
||||
{
|
||||
// Inferred from encoding.properties
|
||||
Response response = getResponse();
|
||||
|
||||
assertEquals(null, response.getContentType());
|
||||
|
||||
response.setHeader("Content-Type", "application/xhtml+xml");
|
||||
assertEquals("application/xhtml+xml", response.getContentType());
|
||||
response.getWriter();
|
||||
assertEquals("application/xhtml+xml;charset=utf-8", response.getContentType());
|
||||
assertEquals("utf-8", response.getCharacterEncoding());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAssumedCharset() throws Exception
|
||||
{
|
||||
Response response = getResponse();
|
||||
|
||||
// Assumed from known types
|
||||
assertEquals(null, response.getContentType());
|
||||
response.setHeader("Content-Type", "text/json");
|
||||
assertEquals("text/json", response.getContentType());
|
||||
response.getWriter();
|
||||
assertEquals("text/json", response.getContentType());
|
||||
assertEquals("utf-8", response.getCharacterEncoding());
|
||||
|
||||
response.recycle();
|
||||
|
||||
// Assumed from encoding.properties
|
||||
assertEquals(null, response.getContentType());
|
||||
response.setHeader("Content-Type", "application/vnd.api+json");
|
||||
assertEquals("application/vnd.api+json", response.getContentType());
|
||||
response.getWriter();
|
||||
assertEquals("application/vnd.api+json", response.getContentType());
|
||||
assertEquals("utf-8", response.getCharacterEncoding());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStrangeContentType() throws Exception
|
||||
|
|
Loading…
Reference in New Issue