Jetty 12 mimetype cleanup (#8919)

MimeTypes now available via context.

Signed-off-by: Greg Wilkins <gregw@webtide.com>
This commit is contained in:
Greg Wilkins 2022-11-23 14:30:11 +11:00 committed by GitHub
parent 84208f9955
commit a44af984b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 305 additions and 432 deletions

View File

@ -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"),
@ -53,41 +47,41 @@ public class MimeTypes
MULTIPART_FORM_DATA("multipart/form-data"), MULTIPART_FORM_DATA("multipart/form-data"),
TEXT_HTML("text/html") TEXT_HTML("text/html")
{
@Override
public HttpField getContentTypeField(Charset charset)
{ {
if (Objects.equals(charset, StandardCharsets.UTF_8)) @Override
return TEXT_HTML_UTF_8.getContentTypeField(); public HttpField getContentTypeField(Charset charset)
if (Objects.equals(charset, StandardCharsets.ISO_8859_1)) {
return TEXT_HTML_8859_1.getContentTypeField(); if (Objects.equals(charset, StandardCharsets.UTF_8))
return super.getContentTypeField(charset); return TEXT_HTML_UTF_8.getContentTypeField();
} if (Objects.equals(charset, StandardCharsets.ISO_8859_1))
}, return TEXT_HTML_8859_1.getContentTypeField();
return super.getContentTypeField(charset);
}
},
TEXT_PLAIN("text/plain") TEXT_PLAIN("text/plain")
{
@Override
public HttpField getContentTypeField(Charset charset)
{ {
if (Objects.equals(charset, StandardCharsets.UTF_8)) @Override
return TEXT_PLAIN_UTF_8.getContentTypeField(); public HttpField getContentTypeField(Charset charset)
if (Objects.equals(charset, StandardCharsets.ISO_8859_1)) {
return TEXT_PLAIN_8859_1.getContentTypeField(); if (Objects.equals(charset, StandardCharsets.UTF_8))
return super.getContentTypeField(charset); return TEXT_PLAIN_UTF_8.getContentTypeField();
} if (Objects.equals(charset, StandardCharsets.ISO_8859_1))
}, return TEXT_PLAIN_8859_1.getContentTypeField();
return super.getContentTypeField(charset);
}
},
TEXT_XML("text/xml") TEXT_XML("text/xml")
{
@Override
public HttpField getContentTypeField(Charset charset)
{ {
if (Objects.equals(charset, StandardCharsets.UTF_8)) @Override
return TEXT_XML_UTF_8.getContentTypeField(); public HttpField getContentTypeField(Charset charset)
if (Objects.equals(charset, StandardCharsets.ISO_8859_1)) {
return TEXT_XML_8859_1.getContentTypeField(); if (Objects.equals(charset, StandardCharsets.UTF_8))
return super.getContentTypeField(charset); return TEXT_XML_UTF_8.getContentTypeField();
} if (Objects.equals(charset, StandardCharsets.ISO_8859_1))
}, return TEXT_XML_8859_1.getContentTypeField();
return super.getContentTypeField(charset);
}
},
TEXT_JSON("text/json", StandardCharsets.UTF_8), TEXT_JSON("text/json", StandardCharsets.UTF_8),
APPLICATION_JSON("application/json", StandardCharsets.UTF_8), APPLICATION_JSON("application/json", StandardCharsets.UTF_8),
@ -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,232 +207,215 @@ 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);
{ }
if (type.isCharsetAssumed())
__assumedEncodings.put(type.asString(), type.getCharsetString());
}
String resourceName = "mime.properties"; public MimeTypes(MimeTypes defaults)
try (InputStream stream = MimeTypes.class.getResourceAsStream(resourceName)) {
if (defaults != null)
{ {
if (stream == null) _mimeMap.putAll(defaults.getMimeMap());
{ _assumedEncodings.putAll(defaults.getAssumedMap());
LOG.warn("Missing mime-type resource: {}", resourceName); _inferredEncodings.putAll(defaults.getInferredMap());
}
else
{
try (InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8))
{
Properties props = new Properties();
props.load(reader);
props.stringPropertyNames().stream()
.filter(x -> x != null)
.forEach(x ->
__dftMimeMap.put(StringUtil.asciiToLowerCase(x), normalizeMimeType(props.getProperty(x))));
if (__dftMimeMap.isEmpty())
{
LOG.warn("Empty mime types at {}", resourceName);
}
else if (__dftMimeMap.size() < props.keySet().size())
{
LOG.warn("Duplicate or null mime-type extension in resource: {}", resourceName);
}
}
catch (IOException e)
{
if (LOG.isDebugEnabled())
LOG.warn("Unable to read mime-type resource: {}", resourceName, e);
else
LOG.warn("Unable to read mime-type resource: {} - {}", resourceName, e.toString());
}
}
}
catch (IOException e)
{
if (LOG.isDebugEnabled())
LOG.warn("Unable to load mime-type resource: {}", resourceName, e);
else
LOG.warn("Unable to load mime-type resource: {} - {}", resourceName, e.toString());
}
resourceName = "encoding.properties";
try (InputStream stream = MimeTypes.class.getResourceAsStream(resourceName))
{
if (stream == null)
LOG.warn("Missing encoding resource: {}", resourceName);
else
{
try (InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8))
{
Properties props = new Properties();
props.load(reader);
props.stringPropertyNames().stream()
.filter(t -> t != null)
.forEach(t ->
{
String charset = props.getProperty(t);
if (charset.startsWith("-"))
__assumedEncodings.put(t, charset.substring(1));
else
__inferredEncodings.put(t, props.getProperty(t));
});
if (__inferredEncodings.isEmpty())
{
LOG.warn("Empty encodings at {}", resourceName);
}
else if ((__inferredEncodings.size() + __assumedEncodings.size()) < props.keySet().size())
{
LOG.warn("Null or duplicate encodings in resource: {}", resourceName);
}
}
catch (IOException e)
{
if (LOG.isDebugEnabled())
LOG.warn("Unable to read encoding resource: {}", resourceName, e);
else
LOG.warn("Unable to read encoding resource: {} - {}", resourceName, e.toString());
}
}
}
catch (IOException e)
{
if (LOG.isDebugEnabled())
LOG.warn("Unable to load encoding resource: {}", resourceName, e);
else
LOG.warn("Unable to load encoding resource: {} - {}", resourceName, e.toString());
} }
} }
private final Map<String, String> _mimeMap = new HashMap<String, String>();
/** /**
* Constructor. * 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 MimeTypes() 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() public Map<String, String> getMimeMap()
{ {
return _mimeMap; return Collections.unmodifiableMap(_mimeMap);
} }
/** public Map<String, String> getInferredMap()
* @param mimeMap A Map of file extension to mime-type.
*/
public void setMimeMap(Map<String, String> mimeMap)
{ {
_mimeMap.clear(); return Collections.unmodifiableMap(_inferredEncodings);
if (mimeMap != null) }
public Map<String, String> getAssumedMap()
{
return Collections.unmodifiableMap(_assumedEncodings);
}
public static class Mutable extends MimeTypes
{
public Mutable()
{ {
for (Entry<String, String> ext : mimeMap.entrySet()) }
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())
{ {
_mimeMap.put(StringUtil.asciiToLowerCase(ext.getKey()), normalizeMimeType(ext.getValue())); if (type.isCharsetAssumed())
_assumedEncodings.put(type.asString(), type.getCharsetString());
}
String resourceName = "mime.properties";
try (InputStream stream = MimeTypes.class.getResourceAsStream(resourceName))
{
if (stream == null)
{
LOG.warn("Missing mime-type resource: {}", resourceName);
}
else
{
try (InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8))
{
Properties props = new Properties();
props.load(reader);
props.stringPropertyNames().stream()
.filter(Objects::nonNull)
.forEach(x ->
{
if (x.contains("."))
LOG.warn("ignoring invalid extension {} from mime.properties", x);
else
_mimeMap.put(StringUtil.asciiToLowerCase(x), normalizeMimeType(props.getProperty(x)));
});
if (_mimeMap.isEmpty())
{
LOG.warn("Empty mime types at {}", resourceName);
}
else if (_mimeMap.size() < props.keySet().size())
{
LOG.warn("Duplicate or null mime-type extension in resource: {}", resourceName);
}
}
catch (IOException e)
{
if (LOG.isDebugEnabled())
LOG.warn("Unable to read mime-type resource: {}", resourceName, e);
else
LOG.warn("Unable to read mime-type resource: {} - {}", resourceName, e.toString());
}
}
}
catch (IOException e)
{
if (LOG.isDebugEnabled())
LOG.warn("Unable to load mime-type resource: {}", resourceName, e);
else
LOG.warn("Unable to load mime-type resource: {} - {}", resourceName, e.toString());
}
resourceName = "encoding.properties";
try (InputStream stream = MimeTypes.class.getResourceAsStream(resourceName))
{
if (stream == null)
LOG.warn("Missing encoding resource: {}", resourceName);
else
{
try (InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8))
{
Properties props = new Properties();
props.load(reader);
props.stringPropertyNames().stream()
.filter(Objects::nonNull)
.forEach(t ->
{
String charset = props.getProperty(t);
if (charset.startsWith("-"))
_assumedEncodings.put(t, charset.substring(1));
else
_inferredEncodings.put(t, props.getProperty(t));
});
if (_inferredEncodings.isEmpty())
{
LOG.warn("Empty encodings at {}", resourceName);
}
else if ((_inferredEncodings.size() + _assumedEncodings.size()) < props.keySet().size())
{
LOG.warn("Null or duplicate encodings in resource: {}", resourceName);
}
}
catch (IOException e)
{
if (LOG.isDebugEnabled())
LOG.warn("Unable to read encoding resource: {}", resourceName, e);
else
LOG.warn("Unable to read encoding resource: {} - {}", resourceName, e.toString());
}
}
}
catch (IOException e)
{
if (LOG.isDebugEnabled())
LOG.warn("Unable to load encoding resource: {}", resourceName, e);
else
LOG.warn("Unable to load encoding resource: {} - {}", resourceName, e.toString());
} }
} }
} };
/**
* 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)
{ {

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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()
{ {

View File

@ -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);

View File

@ -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()
{ {

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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)
{ {

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -349,14 +349,15 @@ public class ServletContextResponse extends ContextResponse
// Try charset from mime type. // Try charset from mime type.
if (_mimeType != null && _mimeType.isCharsetAssumed()) if (_mimeType != null && _mimeType.isCharsetAssumed())
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)

View File

@ -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();
} }
} }

View File

@ -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);
} }

View File

@ -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);

View File

@ -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");

View File

@ -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);

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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();

View File

@ -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);
} }

View File

@ -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);
} }

View File

@ -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);