Jetty 12 mimetype cleanup (#8919)
MimeTypes now available via context. Signed-off-by: Greg Wilkins <gregw@webtide.com>
This commit is contained in:
parent
84208f9955
commit
a44af984b5
|
@ -16,19 +16,16 @@ package org.eclipse.jetty.http;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.util.BufferUtil;
|
import org.eclipse.jetty.util.FileID;
|
||||||
import org.eclipse.jetty.util.Index;
|
import org.eclipse.jetty.util.Index;
|
||||||
import org.eclipse.jetty.util.StringUtil;
|
import org.eclipse.jetty.util.StringUtil;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -39,12 +36,9 @@ import org.slf4j.LoggerFactory;
|
||||||
*/
|
*/
|
||||||
public class MimeTypes
|
public class MimeTypes
|
||||||
{
|
{
|
||||||
|
static final Logger LOG = LoggerFactory.getLogger(MimeTypes.class);
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(MimeTypes.class);
|
/** Enumeration of predefined MimeTypes. This is not exhaustive */
|
||||||
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
|
public enum Type
|
||||||
{
|
{
|
||||||
FORM_ENCODED("application/x-www-form-urlencoded"),
|
FORM_ENCODED("application/x-www-form-urlencoded"),
|
||||||
|
@ -108,7 +102,6 @@ public class MimeTypes
|
||||||
|
|
||||||
private final String _string;
|
private final String _string;
|
||||||
private final Type _base;
|
private final Type _base;
|
||||||
private final ByteBuffer _buffer;
|
|
||||||
private final Charset _charset;
|
private final Charset _charset;
|
||||||
private final String _charsetString;
|
private final String _charsetString;
|
||||||
private final boolean _assumedCharset;
|
private final boolean _assumedCharset;
|
||||||
|
@ -117,7 +110,6 @@ public class MimeTypes
|
||||||
Type(String s)
|
Type(String s)
|
||||||
{
|
{
|
||||||
_string = s;
|
_string = s;
|
||||||
_buffer = BufferUtil.toBuffer(s);
|
|
||||||
_base = this;
|
_base = this;
|
||||||
_charset = null;
|
_charset = null;
|
||||||
_charsetString = null;
|
_charsetString = null;
|
||||||
|
@ -128,7 +120,6 @@ public class MimeTypes
|
||||||
Type(String s, Type base)
|
Type(String s, Type base)
|
||||||
{
|
{
|
||||||
_string = s;
|
_string = s;
|
||||||
_buffer = BufferUtil.toBuffer(s);
|
|
||||||
_base = base;
|
_base = base;
|
||||||
int i = s.indexOf(";charset=");
|
int i = s.indexOf(";charset=");
|
||||||
_charset = Charset.forName(s.substring(i + 9));
|
_charset = Charset.forName(s.substring(i + 9));
|
||||||
|
@ -141,18 +132,12 @@ public class MimeTypes
|
||||||
{
|
{
|
||||||
_string = s;
|
_string = s;
|
||||||
_base = this;
|
_base = this;
|
||||||
_buffer = BufferUtil.toBuffer(s);
|
|
||||||
_charset = cs;
|
_charset = cs;
|
||||||
_charsetString = _charset == null ? null : _charset.toString().toLowerCase(Locale.ENGLISH);
|
_charsetString = _charset == null ? null : _charset.toString().toLowerCase(Locale.ENGLISH);
|
||||||
_assumedCharset = true;
|
_assumedCharset = true;
|
||||||
_field = new PreEncodedHttpField(HttpHeader.CONTENT_TYPE, _string);
|
_field = new PreEncodedHttpField(HttpHeader.CONTENT_TYPE, _string);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer asBuffer()
|
|
||||||
{
|
|
||||||
return _buffer.asReadOnlyBuffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Charset getCharset()
|
public Charset getCharset()
|
||||||
{
|
{
|
||||||
return _charset;
|
return _charset;
|
||||||
|
@ -222,12 +207,111 @@ public class MimeTypes
|
||||||
})
|
})
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
static
|
protected final Map<String, String> _mimeMap = new HashMap<>();
|
||||||
|
protected final Map<String, String> _inferredEncodings = new HashMap<>();
|
||||||
|
protected final Map<String, String> _assumedEncodings = new HashMap<>();
|
||||||
|
|
||||||
|
public MimeTypes()
|
||||||
{
|
{
|
||||||
for (MimeTypes.Type type : MimeTypes.Type.values())
|
this(DEFAULTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MimeTypes(MimeTypes defaults)
|
||||||
|
{
|
||||||
|
if (defaults != null)
|
||||||
|
{
|
||||||
|
_mimeMap.putAll(defaults.getMimeMap());
|
||||||
|
_assumedEncodings.putAll(defaults.getAssumedMap());
|
||||||
|
_inferredEncodings.putAll(defaults.getInferredMap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the MIME type by filename extension.
|
||||||
|
*
|
||||||
|
* @param filename A file name
|
||||||
|
* @return MIME type matching the last dot extension of the
|
||||||
|
* file name, or matching "*" if none found.
|
||||||
|
*/
|
||||||
|
public String getMimeByExtension(String filename)
|
||||||
|
{
|
||||||
|
String ext = FileID.getExtension(filename);
|
||||||
|
return getMimeForExtension(Objects.requireNonNullElse(ext, "*"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMimeForExtension(String extension)
|
||||||
|
{
|
||||||
|
return _mimeMap.get(extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCharsetInferredFromContentType(String contentType)
|
||||||
|
{
|
||||||
|
return _inferredEncodings.get(contentType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCharsetAssumedFromContentType(String contentType)
|
||||||
|
{
|
||||||
|
return _assumedEncodings.get(contentType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getMimeMap()
|
||||||
|
{
|
||||||
|
return Collections.unmodifiableMap(_mimeMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getInferredMap()
|
||||||
|
{
|
||||||
|
return Collections.unmodifiableMap(_inferredEncodings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getAssumedMap()
|
||||||
|
{
|
||||||
|
return Collections.unmodifiableMap(_assumedEncodings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Mutable extends MimeTypes
|
||||||
|
{
|
||||||
|
public Mutable()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mutable(MimeTypes defaults)
|
||||||
|
{
|
||||||
|
super(defaults);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a mime mapping
|
||||||
|
*
|
||||||
|
* @param extension the extension
|
||||||
|
* @param type the mime type
|
||||||
|
* @return previous value
|
||||||
|
*/
|
||||||
|
public String addMimeMapping(String extension, String type)
|
||||||
|
{
|
||||||
|
if (extension.contains("."))
|
||||||
|
throw new IllegalArgumentException("extensions cannot contain '.'");
|
||||||
|
return _mimeMap.put(StringUtil.asciiToLowerCase(extension), normalizeMimeType(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String addInferred(String contentType, String encoding)
|
||||||
|
{
|
||||||
|
return _inferredEncodings.put(contentType, encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String addAssumed(String contentType, String encoding)
|
||||||
|
{
|
||||||
|
return _assumedEncodings.put(contentType, encoding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final MimeTypes DEFAULTS = new MimeTypes(null)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
for (Type type : Type.values())
|
||||||
{
|
{
|
||||||
if (type.isCharsetAssumed())
|
if (type.isCharsetAssumed())
|
||||||
__assumedEncodings.put(type.asString(), type.getCharsetString());
|
_assumedEncodings.put(type.asString(), type.getCharsetString());
|
||||||
}
|
}
|
||||||
|
|
||||||
String resourceName = "mime.properties";
|
String resourceName = "mime.properties";
|
||||||
|
@ -244,15 +328,20 @@ public class MimeTypes
|
||||||
Properties props = new Properties();
|
Properties props = new Properties();
|
||||||
props.load(reader);
|
props.load(reader);
|
||||||
props.stringPropertyNames().stream()
|
props.stringPropertyNames().stream()
|
||||||
.filter(x -> x != null)
|
.filter(Objects::nonNull)
|
||||||
.forEach(x ->
|
.forEach(x ->
|
||||||
__dftMimeMap.put(StringUtil.asciiToLowerCase(x), normalizeMimeType(props.getProperty(x))));
|
{
|
||||||
|
if (x.contains("."))
|
||||||
|
LOG.warn("ignoring invalid extension {} from mime.properties", x);
|
||||||
|
else
|
||||||
|
_mimeMap.put(StringUtil.asciiToLowerCase(x), normalizeMimeType(props.getProperty(x)));
|
||||||
|
});
|
||||||
|
|
||||||
if (__dftMimeMap.isEmpty())
|
if (_mimeMap.isEmpty())
|
||||||
{
|
{
|
||||||
LOG.warn("Empty mime types at {}", resourceName);
|
LOG.warn("Empty mime types at {}", resourceName);
|
||||||
}
|
}
|
||||||
else if (__dftMimeMap.size() < props.keySet().size())
|
else if (_mimeMap.size() < props.keySet().size())
|
||||||
{
|
{
|
||||||
LOG.warn("Duplicate or null mime-type extension in resource: {}", resourceName);
|
LOG.warn("Duplicate or null mime-type extension in resource: {}", resourceName);
|
||||||
}
|
}
|
||||||
|
@ -286,21 +375,21 @@ public class MimeTypes
|
||||||
Properties props = new Properties();
|
Properties props = new Properties();
|
||||||
props.load(reader);
|
props.load(reader);
|
||||||
props.stringPropertyNames().stream()
|
props.stringPropertyNames().stream()
|
||||||
.filter(t -> t != null)
|
.filter(Objects::nonNull)
|
||||||
.forEach(t ->
|
.forEach(t ->
|
||||||
{
|
{
|
||||||
String charset = props.getProperty(t);
|
String charset = props.getProperty(t);
|
||||||
if (charset.startsWith("-"))
|
if (charset.startsWith("-"))
|
||||||
__assumedEncodings.put(t, charset.substring(1));
|
_assumedEncodings.put(t, charset.substring(1));
|
||||||
else
|
else
|
||||||
__inferredEncodings.put(t, props.getProperty(t));
|
_inferredEncodings.put(t, props.getProperty(t));
|
||||||
});
|
});
|
||||||
|
|
||||||
if (__inferredEncodings.isEmpty())
|
if (_inferredEncodings.isEmpty())
|
||||||
{
|
{
|
||||||
LOG.warn("Empty encodings at {}", resourceName);
|
LOG.warn("Empty encodings at {}", resourceName);
|
||||||
}
|
}
|
||||||
else if ((__inferredEncodings.size() + __assumedEncodings.size()) < props.keySet().size())
|
else if ((_inferredEncodings.size() + _assumedEncodings.size()) < props.keySet().size())
|
||||||
{
|
{
|
||||||
LOG.warn("Null or duplicate encodings in resource: {}", resourceName);
|
LOG.warn("Null or duplicate encodings in resource: {}", resourceName);
|
||||||
}
|
}
|
||||||
|
@ -322,132 +411,11 @@ public class MimeTypes
|
||||||
LOG.warn("Unable to load encoding resource: {} - {}", resourceName, e.toString());
|
LOG.warn("Unable to load encoding resource: {} - {}", resourceName, e.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
private final Map<String, String> _mimeMap = new HashMap<String, String>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor.
|
|
||||||
*/
|
|
||||||
public MimeTypes()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, String> getMimeMap()
|
|
||||||
{
|
|
||||||
return _mimeMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mimeMap A Map of file extension to mime-type.
|
|
||||||
*/
|
|
||||||
public void setMimeMap(Map<String, String> mimeMap)
|
|
||||||
{
|
|
||||||
_mimeMap.clear();
|
|
||||||
if (mimeMap != null)
|
|
||||||
{
|
|
||||||
for (Entry<String, String> ext : mimeMap.entrySet())
|
|
||||||
{
|
|
||||||
_mimeMap.put(StringUtil.asciiToLowerCase(ext.getKey()), normalizeMimeType(ext.getValue()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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)
|
|
||||||
{
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
public String getMimeByExtension(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 (_mimeMap != null)
|
|
||||||
type = _mimeMap.get(ext);
|
|
||||||
if (type == null)
|
|
||||||
type = __dftMimeMap.get(ext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == null)
|
|
||||||
{
|
|
||||||
if (_mimeMap != null)
|
|
||||||
type = _mimeMap.get("*");
|
|
||||||
if (type == null)
|
|
||||||
type = __dftMimeMap.get("*");
|
|
||||||
}
|
|
||||||
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a mime mapping
|
|
||||||
*
|
|
||||||
* @param extension the extension
|
|
||||||
* @param type the mime type
|
|
||||||
*/
|
|
||||||
public void addMimeMapping(String extension, String type)
|
|
||||||
{
|
|
||||||
_mimeMap.put(StringUtil.asciiToLowerCase(extension), normalizeMimeType(type));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Set<String> getKnownMimeTypes()
|
|
||||||
{
|
|
||||||
return new HashSet<>(__dftMimeMap.values());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String normalizeMimeType(String type)
|
private static String normalizeMimeType(String type)
|
||||||
{
|
{
|
||||||
MimeTypes.Type t = CACHE.get(type);
|
Type t = CACHE.get(type);
|
||||||
if (t != null)
|
if (t != null)
|
||||||
return t.asString();
|
return t.asString();
|
||||||
|
|
||||||
|
@ -567,40 +535,6 @@ public class MimeTypes
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 __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 __assumedEncodings;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
public static String getContentTypeWithoutCharset(String value)
|
||||||
{
|
{
|
||||||
int end = value.length();
|
int end = value.length();
|
||||||
|
@ -615,14 +549,7 @@ public class MimeTypes
|
||||||
|
|
||||||
if ('"' == b)
|
if ('"' == b)
|
||||||
{
|
{
|
||||||
if (quote)
|
quote = !quote;
|
||||||
{
|
|
||||||
quote = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
quote = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
|
|
|
@ -154,7 +154,6 @@ svgz=image/svg+xml
|
||||||
swf=application/x-shockwave-flash
|
swf=application/x-shockwave-flash
|
||||||
t=application/x-troff
|
t=application/x-troff
|
||||||
tar=application/x-tar
|
tar=application/x-tar
|
||||||
tar.gz=application/x-gtar
|
|
||||||
tcl=application/x-tcl
|
tcl=application/x-tcl
|
||||||
tex=application/x-tex
|
tex=application/x-tex
|
||||||
texi=application/x-texinfo
|
texi=application/x-texinfo
|
||||||
|
|
|
@ -30,6 +30,8 @@ public class MimeTypesTest
|
||||||
{
|
{
|
||||||
return Stream.of(
|
return Stream.of(
|
||||||
Arguments.of("test.gz", "application/gzip"),
|
Arguments.of("test.gz", "application/gzip"),
|
||||||
|
Arguments.of("test.tar.gz", "application/gzip"),
|
||||||
|
Arguments.of("test.tgz", "application/x-gtar"),
|
||||||
Arguments.of("foo.webp", "image/webp"),
|
Arguments.of("foo.webp", "image/webp"),
|
||||||
Arguments.of("zed.avif", "image/avif"),
|
Arguments.of("zed.avif", "image/avif"),
|
||||||
// make sure that filename case isn't an issue
|
// make sure that filename case isn't an issue
|
||||||
|
|
|
@ -16,6 +16,7 @@ package org.eclipse.jetty.server;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.http.MimeTypes;
|
||||||
import org.eclipse.jetty.util.Attributes;
|
import org.eclipse.jetty.util.Attributes;
|
||||||
import org.eclipse.jetty.util.Decorator;
|
import org.eclipse.jetty.util.Decorator;
|
||||||
import org.eclipse.jetty.util.resource.Resource;
|
import org.eclipse.jetty.util.resource.Resource;
|
||||||
|
@ -47,6 +48,8 @@ public interface Context extends Attributes, Decorator, Executor
|
||||||
|
|
||||||
List<String> getVirtualHosts();
|
List<String> getVirtualHosts();
|
||||||
|
|
||||||
|
MimeTypes getMimeTypes();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
/** execute runnable in container thread scoped to context */
|
/** execute runnable in container thread scoped to context */
|
||||||
void execute(Runnable runnable);
|
void execute(Runnable runnable);
|
||||||
|
|
|
@ -31,6 +31,7 @@ import org.eclipse.jetty.http.DateGenerator;
|
||||||
import org.eclipse.jetty.http.HttpField;
|
import org.eclipse.jetty.http.HttpField;
|
||||||
import org.eclipse.jetty.http.HttpGenerator;
|
import org.eclipse.jetty.http.HttpGenerator;
|
||||||
import org.eclipse.jetty.http.HttpHeader;
|
import org.eclipse.jetty.http.HttpHeader;
|
||||||
|
import org.eclipse.jetty.http.MimeTypes;
|
||||||
import org.eclipse.jetty.http.PreEncodedHttpField;
|
import org.eclipse.jetty.http.PreEncodedHttpField;
|
||||||
import org.eclipse.jetty.io.Connection;
|
import org.eclipse.jetty.io.Connection;
|
||||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||||
|
@ -725,6 +726,12 @@ public class Server extends Handler.Wrapper implements Attributes
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MimeTypes getMimeTypes()
|
||||||
|
{
|
||||||
|
return MimeTypes.DEFAULTS;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClassLoader getClassLoader()
|
public ClassLoader getClassLoader()
|
||||||
{
|
{
|
||||||
|
|
|
@ -65,7 +65,7 @@ public class BufferedResponseHandler extends Handler.Wrapper
|
||||||
public BufferedResponseHandler()
|
public BufferedResponseHandler()
|
||||||
{
|
{
|
||||||
_methods.include(HttpMethod.GET.asString());
|
_methods.include(HttpMethod.GET.asString());
|
||||||
for (String type : MimeTypes.getKnownMimeTypes())
|
for (String type : MimeTypes.DEFAULTS.getMimeMap().values())
|
||||||
{
|
{
|
||||||
if (type.startsWith("image/") ||
|
if (type.startsWith("image/") ||
|
||||||
type.startsWith("audio/") ||
|
type.startsWith("audio/") ||
|
||||||
|
@ -151,7 +151,7 @@ public class BufferedResponseHandler extends Handler.Wrapper
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the mime type is known from the path then apply mime type filtering.
|
// If the mime type is known from the path then apply mime type filtering.
|
||||||
String mimeType = MimeTypes.getDefaultMimeByExtension(path); // TODO context specicif mimetypes : context.getMimeType(path);
|
String mimeType = request.getContext().getMimeTypes().getMimeByExtension(path);
|
||||||
if (mimeType != null)
|
if (mimeType != null)
|
||||||
{
|
{
|
||||||
mimeType = MimeTypes.getContentTypeWithoutCharset(mimeType);
|
mimeType = MimeTypes.getContentTypeWithoutCharset(mimeType);
|
||||||
|
|
|
@ -35,6 +35,7 @@ import java.util.stream.Collectors;
|
||||||
import org.eclipse.jetty.http.HttpField;
|
import org.eclipse.jetty.http.HttpField;
|
||||||
import org.eclipse.jetty.http.HttpHeader;
|
import org.eclipse.jetty.http.HttpHeader;
|
||||||
import org.eclipse.jetty.http.HttpStatus;
|
import org.eclipse.jetty.http.HttpStatus;
|
||||||
|
import org.eclipse.jetty.http.MimeTypes;
|
||||||
import org.eclipse.jetty.server.AliasCheck;
|
import org.eclipse.jetty.server.AliasCheck;
|
||||||
import org.eclipse.jetty.server.Connector;
|
import org.eclipse.jetty.server.Connector;
|
||||||
import org.eclipse.jetty.server.Handler;
|
import org.eclipse.jetty.server.Handler;
|
||||||
|
@ -87,9 +88,15 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace
|
||||||
return "jetty/" + Server.getVersion();
|
return "jetty/" + Server.getVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO should persistent attributes be an Attributes.Layer over server attributes?
|
/*
|
||||||
private final Attributes _persistentAttributes = new Mapped();
|
* The context (specifically it's attributes and mimeTypes) are not implemented as a layer over
|
||||||
|
* the server context, as this handler's context replaces the context in the request, it does not
|
||||||
|
* wrap it. This is so that any cross context dispatch does not inherit attributes and types from
|
||||||
|
* the dispatching context.
|
||||||
|
*/
|
||||||
private final Context _context;
|
private final Context _context;
|
||||||
|
private final Attributes _persistentAttributes = new Mapped();
|
||||||
|
private final MimeTypes.Mutable _mimeTypes = new MimeTypes.Mutable();
|
||||||
private final List<ContextScopeListener> _contextListeners = new CopyOnWriteArrayList<>();
|
private final List<ContextScopeListener> _contextListeners = new CopyOnWriteArrayList<>();
|
||||||
private final List<VHost> _vhosts = new ArrayList<>();
|
private final List<VHost> _vhosts = new ArrayList<>();
|
||||||
|
|
||||||
|
@ -158,6 +165,11 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace
|
||||||
return new Context();
|
return new Context();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MimeTypes.Mutable getMimeTypes()
|
||||||
|
{
|
||||||
|
return _mimeTypes;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dump(Appendable out, String indent) throws IOException
|
public void dump(Appendable out, String indent) throws IOException
|
||||||
{
|
{
|
||||||
|
@ -1002,6 +1014,12 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace
|
||||||
return _contextPath;
|
return _contextPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MimeTypes getMimeTypes()
|
||||||
|
{
|
||||||
|
return _mimeTypes;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
|
|
|
@ -74,9 +74,7 @@ public class ResourceHandler extends Handler.Wrapper
|
||||||
_resourceBase = context.getBaseResource();
|
_resourceBase = context.getBaseResource();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: _mimeTypes = _context == null ? new MimeTypes() : _context.getMimeTypes();
|
_mimeTypes = context == null ? MimeTypes.DEFAULTS : context.getMimeTypes();
|
||||||
if (_mimeTypes == null)
|
|
||||||
_mimeTypes = new MimeTypes();
|
|
||||||
|
|
||||||
_byteBufferPool = getByteBufferPool(context);
|
_byteBufferPool = getByteBufferPool(context);
|
||||||
_resourceService.setHttpContentFactory(newHttpContentFactory());
|
_resourceService.setHttpContentFactory(newHttpContentFactory());
|
||||||
|
@ -320,11 +318,6 @@ public class ResourceHandler extends Handler.Wrapper
|
||||||
return _resourceService.getEncodingCacheSize();
|
return _resourceService.getEncodingCacheSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMimeTypes(MimeTypes mimeTypes)
|
|
||||||
{
|
|
||||||
_mimeTypes = mimeTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param redirectWelcome If true, welcome files are redirected rather than forwarded to.
|
* @param redirectWelcome If true, welcome files are redirected rather than forwarded to.
|
||||||
* redirection is always used if the ResourceHandler is not scoped by
|
* redirection is always used if the ResourceHandler is not scoped by
|
||||||
|
|
|
@ -68,7 +68,7 @@ public class GzipHandler extends Handler.Wrapper implements GzipFactory
|
||||||
{
|
{
|
||||||
_methods.include(HttpMethod.GET.asString());
|
_methods.include(HttpMethod.GET.asString());
|
||||||
_methods.include(HttpMethod.POST.asString());
|
_methods.include(HttpMethod.POST.asString());
|
||||||
for (String type : MimeTypes.getKnownMimeTypes())
|
for (String type : MimeTypes.DEFAULTS.getMimeMap().values())
|
||||||
{
|
{
|
||||||
if ("image/svg+xml".equals(type))
|
if ("image/svg+xml".equals(type))
|
||||||
_paths.exclude("*.svgz");
|
_paths.exclude("*.svgz");
|
||||||
|
@ -624,9 +624,8 @@ public class GzipHandler extends Handler.Wrapper implements GzipFactory
|
||||||
return wrappedRequest.wrapProcessor(super.handle(wrappedRequest));
|
return wrappedRequest.wrapProcessor(super.handle(wrappedRequest));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: get mimetype from context.
|
|
||||||
// Exclude non compressible mime-types known from URI extension. - no Vary because no matter what client, this URI is always excluded
|
// Exclude non compressible mime-types known from URI extension. - no Vary because no matter what client, this URI is always excluded
|
||||||
String mimeType = MimeTypes.getDefaultMimeByExtension(path);
|
String mimeType = request.getContext().getMimeTypes().getMimeByExtension(path);
|
||||||
if (mimeType != null)
|
if (mimeType != null)
|
||||||
{
|
{
|
||||||
mimeType = HttpField.valueParameters(mimeType, null);
|
mimeType = HttpField.valueParameters(mimeType, null);
|
||||||
|
|
|
@ -48,7 +48,6 @@ import org.eclipse.jetty.http.HttpMethod;
|
||||||
import org.eclipse.jetty.http.HttpStatus;
|
import org.eclipse.jetty.http.HttpStatus;
|
||||||
import org.eclipse.jetty.http.HttpTester;
|
import org.eclipse.jetty.http.HttpTester;
|
||||||
import org.eclipse.jetty.http.HttpVersion;
|
import org.eclipse.jetty.http.HttpVersion;
|
||||||
import org.eclipse.jetty.http.MimeTypes;
|
|
||||||
import org.eclipse.jetty.io.Content;
|
import org.eclipse.jetty.io.Content;
|
||||||
import org.eclipse.jetty.server.Context;
|
import org.eclipse.jetty.server.Context;
|
||||||
import org.eclipse.jetty.server.FormFields;
|
import org.eclipse.jetty.server.FormFields;
|
||||||
|
@ -118,8 +117,6 @@ public class GzipHandlerTest
|
||||||
private static final String CONTENT_ETAG = String.format("W/\"%x\"", CONTENT.hashCode());
|
private static final String CONTENT_ETAG = String.format("W/\"%x\"", CONTENT.hashCode());
|
||||||
private static final String CONTENT_ETAG_GZIP = String.format("W/\"%x" + CompressedContentFormat.GZIP.getEtagSuffix() + "\"", CONTENT.hashCode());
|
private static final String CONTENT_ETAG_GZIP = String.format("W/\"%x" + CompressedContentFormat.GZIP.getEtagSuffix() + "\"", CONTENT.hashCode());
|
||||||
|
|
||||||
private static final MimeTypes MIME_TYPES = new MimeTypes();
|
|
||||||
|
|
||||||
public WorkDir _workDir;
|
public WorkDir _workDir;
|
||||||
private Server _server;
|
private Server _server;
|
||||||
private LocalConnector _connector;
|
private LocalConnector _connector;
|
||||||
|
@ -1667,9 +1664,8 @@ public class GzipHandlerTest
|
||||||
if (parameters.get("type") != null)
|
if (parameters.get("type") != null)
|
||||||
defaultContentType = parameters.get("type").getValue();
|
defaultContentType = parameters.get("type").getValue();
|
||||||
|
|
||||||
// TODO get mime type from context.
|
|
||||||
Context context = request.getContext();
|
Context context = request.getContext();
|
||||||
String contentType = MIME_TYPES.getMimeByExtension(filename);
|
String contentType = context.getMimeTypes().getMimeByExtension(filename);
|
||||||
if (contentType != null)
|
if (contentType != null)
|
||||||
return contentType;
|
return contentType;
|
||||||
return defaultContentType;
|
return defaultContentType;
|
||||||
|
|
|
@ -157,7 +157,9 @@ public class FileID
|
||||||
* for the extension (if any), including the dot, lower-cased.
|
* for the extension (if any), including the dot, lower-cased.
|
||||||
*
|
*
|
||||||
* @param filename The string path
|
* @param filename The string path
|
||||||
* @return The last segment extension, or null if not a file, or null if there is no extension present
|
* @return The last segment extension excluding the leading dot;
|
||||||
|
* or null if not a file;
|
||||||
|
* or null if there is no extension present
|
||||||
*/
|
*/
|
||||||
public static String getExtension(String filename)
|
public static String getExtension(String filename)
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,7 +21,6 @@ import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.apache.maven.artifact.Artifact;
|
import org.apache.maven.artifact.Artifact;
|
||||||
import org.apache.maven.plugin.AbstractMojoExecutionException;
|
|
||||||
import org.apache.maven.plugin.MojoExecutionException;
|
import org.apache.maven.plugin.MojoExecutionException;
|
||||||
import org.apache.maven.plugin.MojoFailureException;
|
import org.apache.maven.plugin.MojoFailureException;
|
||||||
import org.apache.maven.plugins.annotations.Parameter;
|
import org.apache.maven.plugins.annotations.Parameter;
|
||||||
|
|
|
@ -19,13 +19,10 @@ import java.net.URL;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
import org.apache.maven.plugin.AbstractMojoExecutionException;
|
|
||||||
import org.apache.maven.plugin.MojoExecutionException;
|
import org.apache.maven.plugin.MojoExecutionException;
|
||||||
import org.apache.maven.plugin.MojoFailureException;
|
|
||||||
import org.apache.maven.plugins.annotations.Mojo;
|
import org.apache.maven.plugins.annotations.Mojo;
|
||||||
import org.apache.maven.plugins.annotations.Parameter;
|
import org.apache.maven.plugins.annotations.Parameter;
|
||||||
import org.apache.maven.plugins.annotations.ResolutionScope;
|
import org.apache.maven.plugins.annotations.ResolutionScope;
|
||||||
import org.eclipse.jetty.util.StringUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate the effective web.xml for a pre-built webapp. This goal will NOT
|
* Generate the effective web.xml for a pre-built webapp. This goal will NOT
|
||||||
|
|
|
@ -19,7 +19,6 @@ import java.nio.file.Paths;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.maven.plugin.AbstractMojoExecutionException;
|
|
||||||
import org.apache.maven.plugin.MojoExecutionException;
|
import org.apache.maven.plugin.MojoExecutionException;
|
||||||
import org.apache.maven.plugins.annotations.Execute;
|
import org.apache.maven.plugins.annotations.Execute;
|
||||||
import org.apache.maven.plugins.annotations.LifecyclePhase;
|
import org.apache.maven.plugins.annotations.LifecyclePhase;
|
||||||
|
|
|
@ -16,7 +16,6 @@ package org.eclipse.jetty.ee10.maven.plugin;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
|
||||||
import org.apache.maven.plugin.AbstractMojoExecutionException;
|
|
||||||
import org.apache.maven.plugin.MojoExecutionException;
|
import org.apache.maven.plugin.MojoExecutionException;
|
||||||
import org.apache.maven.plugins.annotations.Mojo;
|
import org.apache.maven.plugins.annotations.Mojo;
|
||||||
import org.apache.maven.plugins.annotations.Parameter;
|
import org.apache.maven.plugins.annotations.Parameter;
|
||||||
|
|
|
@ -73,7 +73,6 @@ import org.eclipse.jetty.ee10.servlet.security.ConstraintMapping;
|
||||||
import org.eclipse.jetty.ee10.servlet.security.ConstraintSecurityHandler;
|
import org.eclipse.jetty.ee10.servlet.security.ConstraintSecurityHandler;
|
||||||
import org.eclipse.jetty.ee10.servlet.security.SecurityHandler;
|
import org.eclipse.jetty.ee10.servlet.security.SecurityHandler;
|
||||||
import org.eclipse.jetty.http.HttpURI;
|
import org.eclipse.jetty.http.HttpURI;
|
||||||
import org.eclipse.jetty.http.MimeTypes;
|
|
||||||
import org.eclipse.jetty.http.pathmap.MatchedResource;
|
import org.eclipse.jetty.http.pathmap.MatchedResource;
|
||||||
import org.eclipse.jetty.server.Handler;
|
import org.eclipse.jetty.server.Handler;
|
||||||
import org.eclipse.jetty.server.Request;
|
import org.eclipse.jetty.server.Request;
|
||||||
|
@ -192,7 +191,6 @@ public class ServletContextHandler extends ContextHandler implements Graceful
|
||||||
private String _defaultRequestCharacterEncoding;
|
private String _defaultRequestCharacterEncoding;
|
||||||
private String _defaultResponseCharacterEncoding;
|
private String _defaultResponseCharacterEncoding;
|
||||||
private String _contextPathEncoded = "/";
|
private String _contextPathEncoded = "/";
|
||||||
protected MimeTypes _mimeTypes; // TODO move to core context?
|
|
||||||
private Map<String, String> _localeEncodingMap;
|
private Map<String, String> _localeEncodingMap;
|
||||||
private String[] _welcomeFiles;
|
private String[] _welcomeFiles;
|
||||||
private Logger _logger;
|
private Logger _logger;
|
||||||
|
@ -649,24 +647,6 @@ public class ServletContextHandler extends ContextHandler implements Graceful
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Returns the mimeTypes.
|
|
||||||
*/
|
|
||||||
public MimeTypes getMimeTypes()
|
|
||||||
{
|
|
||||||
if (_mimeTypes == null)
|
|
||||||
_mimeTypes = new MimeTypes();
|
|
||||||
return _mimeTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mimeTypes The mimeTypes to set.
|
|
||||||
*/
|
|
||||||
public void setMimeTypes(MimeTypes mimeTypes)
|
|
||||||
{
|
|
||||||
_mimeTypes = mimeTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setWelcomeFiles(String[] files)
|
public void setWelcomeFiles(String[] files)
|
||||||
{
|
{
|
||||||
_welcomeFiles = files;
|
_welcomeFiles = files;
|
||||||
|
@ -1079,9 +1059,6 @@ public class ServletContextHandler extends ContextHandler implements Graceful
|
||||||
if (getServer() != null)
|
if (getServer() != null)
|
||||||
_servletContext.setAttribute("org.eclipse.jetty.server.Executor", getServer().getThreadPool());
|
_servletContext.setAttribute("org.eclipse.jetty.server.Executor", getServer().getThreadPool());
|
||||||
|
|
||||||
if (_mimeTypes == null)
|
|
||||||
_mimeTypes = new MimeTypes();
|
|
||||||
|
|
||||||
_durableListeners.addAll(getEventListeners());
|
_durableListeners.addAll(getEventListeners());
|
||||||
|
|
||||||
getContext().call(() ->
|
getContext().call(() ->
|
||||||
|
@ -2811,9 +2788,7 @@ public class ServletContextHandler extends ContextHandler implements Graceful
|
||||||
@Override
|
@Override
|
||||||
public String getMimeType(String file)
|
public String getMimeType(String file)
|
||||||
{
|
{
|
||||||
if (_mimeTypes == null)
|
return getContext().getMimeTypes().getMimeByExtension(file);
|
||||||
return null;
|
|
||||||
return _mimeTypes.getMimeByExtension(file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -351,12 +351,13 @@ public class ServletContextResponse extends ContextResponse
|
||||||
return _mimeType.getCharsetString();
|
return _mimeType.getCharsetString();
|
||||||
|
|
||||||
// Try charset assumed from content type (assumed charsets are not added to content type header).
|
// Try charset assumed from content type (assumed charsets are not added to content type header).
|
||||||
encoding = MimeTypes.getCharsetAssumedFromContentType(_contentType);
|
MimeTypes mimeTypes = _request.getContext().getMimeTypes();
|
||||||
|
encoding = mimeTypes.getCharsetAssumedFromContentType(_contentType);
|
||||||
if (encoding != null)
|
if (encoding != null)
|
||||||
return encoding;
|
return encoding;
|
||||||
|
|
||||||
// Try char set inferred from content type.
|
// Try char set inferred from content type.
|
||||||
encoding = MimeTypes.getCharsetInferredFromContentType(_contentType);
|
encoding = mimeTypes.getCharsetInferredFromContentType(_contentType);
|
||||||
if (encoding != null)
|
if (encoding != null)
|
||||||
{
|
{
|
||||||
if (setContentType)
|
if (setContentType)
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.ee10.servlets;
|
package org.eclipse.jetty.ee10.servlets;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import jakarta.servlet.Filter;
|
import jakarta.servlet.Filter;
|
||||||
import jakarta.servlet.FilterConfig;
|
import jakarta.servlet.FilterConfig;
|
||||||
import jakarta.servlet.ServletContext;
|
import jakarta.servlet.ServletContext;
|
||||||
|
@ -109,7 +111,7 @@ public abstract class IncludeExcludeBasedFilter implements Filter
|
||||||
String contentType = httpResponse.getContentType();
|
String contentType = httpResponse.getContentType();
|
||||||
LOG.debug("Content Type is: {}", contentType);
|
LOG.debug("Content Type is: {}", contentType);
|
||||||
|
|
||||||
String mimeType = "";
|
String mimeType;
|
||||||
if (contentType != null)
|
if (contentType != null)
|
||||||
{
|
{
|
||||||
mimeType = MimeTypes.getContentTypeWithoutCharset(contentType);
|
mimeType = MimeTypes.getContentTypeWithoutCharset(contentType);
|
||||||
|
@ -118,13 +120,7 @@ public abstract class IncludeExcludeBasedFilter implements Filter
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
String requestUrl = httpRequest.getPathInfo();
|
String requestUrl = httpRequest.getPathInfo();
|
||||||
mimeType = MimeTypes.getDefaultMimeByExtension(requestUrl);
|
mimeType = Objects.requireNonNullElse(httpRequest.getServletContext().getMimeType(requestUrl), "");
|
||||||
|
|
||||||
if (mimeType == null)
|
|
||||||
{
|
|
||||||
mimeType = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG.debug("Guessed mime type is {}", mimeType);
|
LOG.debug("Guessed mime type is {}", mimeType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,11 +165,9 @@ public abstract class IncludeExcludeBasedFilter implements Filter
|
||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
StringBuilder sb = new StringBuilder();
|
return "filter configuration:\n" +
|
||||||
sb.append("filter configuration:\n");
|
"paths:\n" + _paths + "\n" +
|
||||||
sb.append("paths:\n").append(_paths).append("\n");
|
"mime types:\n" + _mimeTypes + "\n" +
|
||||||
sb.append("mime types:\n").append(_mimeTypes).append("\n");
|
"http methods:\n" + _httpMethods;
|
||||||
sb.append("http methods:\n").append(_httpMethods);
|
|
||||||
return sb.toString();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,21 +20,16 @@ import jakarta.servlet.ServletException;
|
||||||
import jakarta.servlet.ServletOutputStream;
|
import jakarta.servlet.ServletOutputStream;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.eclipse.jetty.http.MimeTypes;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test servlet for testing against unusual minGzip configurable.
|
* Test servlet for testing against unusual minGzip configurable.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("serial")
|
|
||||||
public class TestMinGzipSizeServlet extends AbstractFileContentServlet
|
public class TestMinGzipSizeServlet extends AbstractFileContentServlet
|
||||||
{
|
{
|
||||||
private MimeTypes mimeTypes;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(ServletConfig config) throws ServletException
|
public void init(ServletConfig config) throws ServletException
|
||||||
{
|
{
|
||||||
super.init(config);
|
super.init(config);
|
||||||
mimeTypes = new MimeTypes();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -52,7 +47,7 @@ public class TestMinGzipSizeServlet extends AbstractFileContentServlet
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
String mime = mimeTypes.getMimeByExtension(fileName);
|
String mime = request.getServletContext().getMimeType(fileName);
|
||||||
if (mime != null)
|
if (mime != null)
|
||||||
response.setContentType(mime);
|
response.setContentType(mime);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
package org.eclipse.jetty.ee10.servlets;
|
package org.eclipse.jetty.ee10.servlets;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import jakarta.servlet.ServletConfig;
|
import jakarta.servlet.ServletConfig;
|
||||||
import jakarta.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
|
@ -25,16 +26,15 @@ import org.eclipse.jetty.http.MimeTypes;
|
||||||
/**
|
/**
|
||||||
* Test servlet for testing against unusual MimeTypes and Content-Types.
|
* Test servlet for testing against unusual MimeTypes and Content-Types.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("serial")
|
|
||||||
public class TestStaticMimeTypeServlet extends AbstractFileContentServlet
|
public class TestStaticMimeTypeServlet extends AbstractFileContentServlet
|
||||||
{
|
{
|
||||||
private MimeTypes mimeTypes;
|
private MimeTypes.Mutable mimeTypes;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(ServletConfig config) throws ServletException
|
public void init(ServletConfig config) throws ServletException
|
||||||
{
|
{
|
||||||
super.init(config);
|
super.init(config);
|
||||||
mimeTypes = new MimeTypes();
|
mimeTypes = new MimeTypes.Mutable();
|
||||||
// Some real world, yet not terribly common, mime type mappings.
|
// Some real world, yet not terribly common, mime type mappings.
|
||||||
mimeTypes.addMimeMapping("bz2", "application/bzip2");
|
mimeTypes.addMimeMapping("bz2", "application/bzip2");
|
||||||
mimeTypes.addMimeMapping("br", "application/brotli");
|
mimeTypes.addMimeMapping("br", "application/brotli");
|
||||||
|
@ -65,10 +65,7 @@ public class TestStaticMimeTypeServlet extends AbstractFileContentServlet
|
||||||
response.setHeader("ETag", "W/etag-" + fileName);
|
response.setHeader("ETag", "W/etag-" + fileName);
|
||||||
|
|
||||||
String mime = mimeTypes.getMimeByExtension(fileName);
|
String mime = mimeTypes.getMimeByExtension(fileName);
|
||||||
if (mime == null)
|
response.setContentType(Objects.requireNonNullElse(mime, "application/octet-stream"));
|
||||||
response.setContentType("application/octet-stream");
|
|
||||||
else
|
|
||||||
response.setContentType(mime);
|
|
||||||
|
|
||||||
ServletOutputStream out = response.getOutputStream();
|
ServletOutputStream out = response.getOutputStream();
|
||||||
out.write(dataBytes);
|
out.write(dataBytes);
|
||||||
|
|
|
@ -15,19 +15,13 @@ package org.eclipse.jetty.ee9.demos;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import org.eclipse.jetty.ee9.servlet.DefaultServlet;
|
import org.eclipse.jetty.ee9.servlet.DefaultServlet;
|
||||||
import org.eclipse.jetty.http.HttpHeader;
|
|
||||||
import org.eclipse.jetty.http.MimeTypes;
|
|
||||||
import org.eclipse.jetty.server.Handler;
|
import org.eclipse.jetty.server.Handler;
|
||||||
import org.eclipse.jetty.server.Request;
|
import org.eclipse.jetty.server.Request;
|
||||||
import org.eclipse.jetty.server.Server;
|
import org.eclipse.jetty.server.Server;
|
||||||
import org.eclipse.jetty.server.handler.DefaultHandler;
|
import org.eclipse.jetty.server.handler.DefaultHandler;
|
||||||
import org.eclipse.jetty.server.handler.HandlerList;
|
import org.eclipse.jetty.server.handler.HandlerList;
|
||||||
import org.eclipse.jetty.server.handler.ResourceHandler;
|
import org.eclipse.jetty.server.handler.ResourceHandler;
|
||||||
import org.eclipse.jetty.util.BufferUtil;
|
|
||||||
import org.eclipse.jetty.util.URIUtil;
|
|
||||||
import org.eclipse.jetty.util.resource.ResourceFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fast FileServer.
|
* Fast FileServer.
|
||||||
|
@ -80,18 +74,15 @@ public class FastFileServer
|
||||||
|
|
||||||
static class FastFileHandler extends Handler.Abstract
|
static class FastFileHandler extends Handler.Abstract
|
||||||
{
|
{
|
||||||
private final MimeTypes mimeTypes = new MimeTypes();
|
|
||||||
private final File dir;
|
|
||||||
|
|
||||||
private FastFileHandler(File dir)
|
private FastFileHandler(File dir)
|
||||||
{
|
{
|
||||||
this.dir = dir;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Request.Processor handle(Request request) throws Exception
|
public Request.Processor handle(Request request) throws Exception
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
|
// TODO
|
||||||
// return (req, response, callback) ->
|
// return (req, response, callback) ->
|
||||||
// {
|
// {
|
||||||
// response.getHeaders().add(HttpHeader.CONTENT_TYPE, "text/html; charset=utf-8");
|
// response.getHeaders().add(HttpHeader.CONTENT_TYPE, "text/html; charset=utf-8");
|
||||||
|
|
|
@ -64,7 +64,7 @@ public class BufferedResponseHandler extends HandlerWrapper
|
||||||
public BufferedResponseHandler()
|
public BufferedResponseHandler()
|
||||||
{
|
{
|
||||||
_methods.include(HttpMethod.GET.asString());
|
_methods.include(HttpMethod.GET.asString());
|
||||||
for (String type : MimeTypes.getKnownMimeTypes())
|
for (String type : MimeTypes.DEFAULTS.getMimeMap().values())
|
||||||
{
|
{
|
||||||
if (type.startsWith("image/") ||
|
if (type.startsWith("image/") ||
|
||||||
type.startsWith("audio/") ||
|
type.startsWith("audio/") ||
|
||||||
|
@ -165,7 +165,7 @@ public class BufferedResponseHandler extends HandlerWrapper
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the mime type is known from the path then apply mime type filtering.
|
// If the mime type is known from the path then apply mime type filtering.
|
||||||
String mimeType = context == null ? MimeTypes.getDefaultMimeByExtension(path) : context.getMimeType(path);
|
String mimeType = context == null ? MimeTypes.DEFAULTS.getMimeByExtension(path) : context.getMimeType(path);
|
||||||
if (mimeType != null)
|
if (mimeType != null)
|
||||||
{
|
{
|
||||||
mimeType = MimeTypes.getContentTypeWithoutCharset(mimeType);
|
mimeType = MimeTypes.getContentTypeWithoutCharset(mimeType);
|
||||||
|
|
|
@ -194,7 +194,6 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
||||||
private String _defaultRequestCharacterEncoding;
|
private String _defaultRequestCharacterEncoding;
|
||||||
private String _defaultResponseCharacterEncoding;
|
private String _defaultResponseCharacterEncoding;
|
||||||
private String _contextPathEncoded = "/";
|
private String _contextPathEncoded = "/";
|
||||||
private MimeTypes _mimeTypes;
|
|
||||||
private Map<String, String> _localeEncodingMap;
|
private Map<String, String> _localeEncodingMap;
|
||||||
private String[] _welcomeFiles;
|
private String[] _welcomeFiles;
|
||||||
private ErrorHandler _errorHandler;
|
private ErrorHandler _errorHandler;
|
||||||
|
@ -625,9 +624,6 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
||||||
|
|
||||||
setAttribute("org.eclipse.jetty.server.Executor", getServer().getThreadPool());
|
setAttribute("org.eclipse.jetty.server.Executor", getServer().getThreadPool());
|
||||||
|
|
||||||
if (_mimeTypes == null)
|
|
||||||
_mimeTypes = new MimeTypes();
|
|
||||||
|
|
||||||
_durableListeners.addAll(getEventListeners());
|
_durableListeners.addAll(getEventListeners());
|
||||||
|
|
||||||
// allow the call to super.doStart() to be deferred by extended implementations.
|
// allow the call to super.doStart() to be deferred by extended implementations.
|
||||||
|
@ -1182,19 +1178,9 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
||||||
/**
|
/**
|
||||||
* @return Returns the mimeTypes.
|
* @return Returns the mimeTypes.
|
||||||
*/
|
*/
|
||||||
public MimeTypes getMimeTypes()
|
public MimeTypes.Mutable getMimeTypes()
|
||||||
{
|
{
|
||||||
if (_mimeTypes == null)
|
return _coreContextHandler.getMimeTypes();
|
||||||
_mimeTypes = new MimeTypes();
|
|
||||||
return _mimeTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mimeTypes The mimeTypes to set.
|
|
||||||
*/
|
|
||||||
public void setMimeTypes(MimeTypes mimeTypes)
|
|
||||||
{
|
|
||||||
_mimeTypes = mimeTypes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setWelcomeFiles(String[] files)
|
public void setWelcomeFiles(String[] files)
|
||||||
|
@ -1766,9 +1752,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
||||||
@Override
|
@Override
|
||||||
public String getMimeType(String file)
|
public String getMimeType(String file)
|
||||||
{
|
{
|
||||||
if (_mimeTypes == null)
|
return _coreContext.getMimeTypes().getMimeByExtension(file);
|
||||||
return null;
|
|
||||||
return _mimeTypes.getMimeByExtension(file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -103,7 +103,7 @@ public class ResourceHandler extends HandlerWrapper implements ResourceFactory,
|
||||||
APIContext scontext = ContextHandler.getCurrentContext();
|
APIContext scontext = ContextHandler.getCurrentContext();
|
||||||
_context = (scontext == null ? null : scontext.getContextHandler());
|
_context = (scontext == null ? null : scontext.getContextHandler());
|
||||||
if (_mimeTypes == null)
|
if (_mimeTypes == null)
|
||||||
_mimeTypes = _context == null ? new MimeTypes() : _context.getMimeTypes();
|
_mimeTypes = _context == null ? MimeTypes.DEFAULTS : _context.getMimeTypes();
|
||||||
|
|
||||||
_byteBufferPool = getByteBufferPool(_context);
|
_byteBufferPool = getByteBufferPool(_context);
|
||||||
if (_resourceService.getHttpContentFactory() == null)
|
if (_resourceService.getHttpContentFactory() == null)
|
||||||
|
|
|
@ -792,13 +792,16 @@ public class Response implements HttpServletResponse
|
||||||
if (_mimeType != null && _mimeType.isCharsetAssumed())
|
if (_mimeType != null && _mimeType.isCharsetAssumed())
|
||||||
return _mimeType.getCharsetString();
|
return _mimeType.getCharsetString();
|
||||||
|
|
||||||
|
// Get MimeTypes from context
|
||||||
|
MimeTypes mimeTypes = _channel.getRequest().getCoreRequest().getContext().getMimeTypes();
|
||||||
|
|
||||||
// Try charset assumed from content type (assumed charsets are not added to content type header).
|
// Try charset assumed from content type (assumed charsets are not added to content type header).
|
||||||
encoding = MimeTypes.getCharsetAssumedFromContentType(_contentType);
|
encoding = mimeTypes.getCharsetAssumedFromContentType(_contentType);
|
||||||
if (encoding != null)
|
if (encoding != null)
|
||||||
return encoding;
|
return encoding;
|
||||||
|
|
||||||
// Try char set inferred from content type.
|
// Try char set inferred from content type.
|
||||||
encoding = MimeTypes.getCharsetInferredFromContentType(_contentType);
|
encoding = mimeTypes.getCharsetInferredFromContentType(_contentType);
|
||||||
if (encoding != null)
|
if (encoding != null)
|
||||||
{
|
{
|
||||||
if (setContentType)
|
if (setContentType)
|
||||||
|
|
|
@ -49,7 +49,6 @@ import org.eclipse.jetty.http.HttpHeader;
|
||||||
import org.eclipse.jetty.http.HttpURI;
|
import org.eclipse.jetty.http.HttpURI;
|
||||||
import org.eclipse.jetty.http.HttpVersion;
|
import org.eclipse.jetty.http.HttpVersion;
|
||||||
import org.eclipse.jetty.http.MetaData;
|
import org.eclipse.jetty.http.MetaData;
|
||||||
import org.eclipse.jetty.http.MimeTypes;
|
|
||||||
import org.eclipse.jetty.io.ByteArrayEndPoint;
|
import org.eclipse.jetty.io.ByteArrayEndPoint;
|
||||||
import org.eclipse.jetty.io.Content;
|
import org.eclipse.jetty.io.Content;
|
||||||
import org.eclipse.jetty.io.EndPoint;
|
import org.eclipse.jetty.io.EndPoint;
|
||||||
|
@ -446,7 +445,7 @@ public class ResponseTest
|
||||||
public void testLocaleAndContentTypeEncoding() throws Exception
|
public void testLocaleAndContentTypeEncoding() throws Exception
|
||||||
{
|
{
|
||||||
_server.stop();
|
_server.stop();
|
||||||
MimeTypes.getInferredEncodings().put("text/html", "iso-8859-1");
|
_context.getMimeTypes().addInferred("text/html", "iso-8859-1");
|
||||||
_context.addLocaleEncoding("ja", "euc-jp");
|
_context.addLocaleEncoding("ja", "euc-jp");
|
||||||
_context.addLocaleEncoding("zh_CN", "gb18030");
|
_context.addLocaleEncoding("zh_CN", "gb18030");
|
||||||
_server.start();
|
_server.start();
|
||||||
|
|
|
@ -13,12 +13,15 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.ee9.servlets;
|
package org.eclipse.jetty.ee9.servlets;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import jakarta.servlet.Filter;
|
import jakarta.servlet.Filter;
|
||||||
import jakarta.servlet.FilterConfig;
|
import jakarta.servlet.FilterConfig;
|
||||||
import jakarta.servlet.ServletContext;
|
import jakarta.servlet.ServletContext;
|
||||||
import jakarta.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import org.eclipse.jetty.ee9.nested.Request;
|
||||||
import org.eclipse.jetty.http.MimeTypes;
|
import org.eclipse.jetty.http.MimeTypes;
|
||||||
import org.eclipse.jetty.http.pathmap.PathSpecSet;
|
import org.eclipse.jetty.http.pathmap.PathSpecSet;
|
||||||
import org.eclipse.jetty.util.IncludeExclude;
|
import org.eclipse.jetty.util.IncludeExclude;
|
||||||
|
@ -118,12 +121,10 @@ public abstract class IncludeExcludeBasedFilter implements Filter
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
String requestUrl = httpRequest.getPathInfo();
|
String requestUrl = httpRequest.getPathInfo();
|
||||||
mimeType = MimeTypes.getDefaultMimeByExtension(requestUrl);
|
Request baseRequest = Request.getBaseRequest(httpRequest);
|
||||||
|
mimeType = Objects.requireNonNullElse(
|
||||||
if (mimeType == null)
|
(baseRequest == null ? MimeTypes.DEFAULTS : baseRequest.getCoreRequest().getContext().getMimeTypes())
|
||||||
{
|
.getMimeByExtension(requestUrl), "");
|
||||||
mimeType = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG.debug("Guessed mime type is {}", mimeType);
|
LOG.debug("Guessed mime type is {}", mimeType);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,21 +20,17 @@ import jakarta.servlet.ServletException;
|
||||||
import jakarta.servlet.ServletOutputStream;
|
import jakarta.servlet.ServletOutputStream;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.eclipse.jetty.http.MimeTypes;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test servlet for testing against unusual minGzip configurable.
|
* Test servlet for testing against unusual minGzip configurable.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("serial")
|
|
||||||
public class TestMinGzipSizeServlet extends AbstractFileContentServlet
|
public class TestMinGzipSizeServlet extends AbstractFileContentServlet
|
||||||
{
|
{
|
||||||
private MimeTypes mimeTypes;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(ServletConfig config) throws ServletException
|
public void init(ServletConfig config) throws ServletException
|
||||||
{
|
{
|
||||||
super.init(config);
|
super.init(config);
|
||||||
mimeTypes = new MimeTypes();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -52,7 +48,7 @@ public class TestMinGzipSizeServlet extends AbstractFileContentServlet
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
String mime = mimeTypes.getMimeByExtension(fileName);
|
String mime = request.getServletContext().getMimeType(fileName);
|
||||||
if (mime != null)
|
if (mime != null)
|
||||||
response.setContentType(mime);
|
response.setContentType(mime);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
package org.eclipse.jetty.ee9.servlets;
|
package org.eclipse.jetty.ee9.servlets;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import jakarta.servlet.ServletConfig;
|
import jakarta.servlet.ServletConfig;
|
||||||
import jakarta.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
|
@ -25,16 +26,15 @@ import org.eclipse.jetty.http.MimeTypes;
|
||||||
/**
|
/**
|
||||||
* Test servlet for testing against unusual MimeTypes and Content-Types.
|
* Test servlet for testing against unusual MimeTypes and Content-Types.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("serial")
|
|
||||||
public class TestStaticMimeTypeServlet extends AbstractFileContentServlet
|
public class TestStaticMimeTypeServlet extends AbstractFileContentServlet
|
||||||
{
|
{
|
||||||
private MimeTypes mimeTypes;
|
private MimeTypes.Mutable mimeTypes;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(ServletConfig config) throws ServletException
|
public void init(ServletConfig config) throws ServletException
|
||||||
{
|
{
|
||||||
super.init(config);
|
super.init(config);
|
||||||
mimeTypes = new MimeTypes();
|
mimeTypes = new MimeTypes.Mutable();
|
||||||
// Some real world, yet not terribly common, mime type mappings.
|
// Some real world, yet not terribly common, mime type mappings.
|
||||||
mimeTypes.addMimeMapping("bz2", "application/bzip2");
|
mimeTypes.addMimeMapping("bz2", "application/bzip2");
|
||||||
mimeTypes.addMimeMapping("br", "application/brotli");
|
mimeTypes.addMimeMapping("br", "application/brotli");
|
||||||
|
@ -65,10 +65,7 @@ public class TestStaticMimeTypeServlet extends AbstractFileContentServlet
|
||||||
response.setHeader("ETag", "W/etag-" + fileName);
|
response.setHeader("ETag", "W/etag-" + fileName);
|
||||||
|
|
||||||
String mime = mimeTypes.getMimeByExtension(fileName);
|
String mime = mimeTypes.getMimeByExtension(fileName);
|
||||||
if (mime == null)
|
response.setContentType(Objects.requireNonNullElse(mime, "application/octet-stream"));
|
||||||
response.setContentType("application/octet-stream");
|
|
||||||
else
|
|
||||||
response.setContentType(mime);
|
|
||||||
|
|
||||||
ServletOutputStream out = response.getOutputStream();
|
ServletOutputStream out = response.getOutputStream();
|
||||||
out.write(dataBytes);
|
out.write(dataBytes);
|
||||||
|
|
Loading…
Reference in New Issue