diff --git a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/MimeTypes.java b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/MimeTypes.java index 025fd63e925..e90a59a2a54 100644 --- a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/MimeTypes.java +++ b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/MimeTypes.java @@ -16,19 +16,16 @@ package org.eclipse.jetty.http; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.Locale; import java.util.Map; -import java.util.Map.Entry; import java.util.Objects; 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.StringUtil; import org.slf4j.Logger; @@ -39,12 +36,9 @@ import org.slf4j.LoggerFactory; */ public class MimeTypes { + static final Logger LOG = LoggerFactory.getLogger(MimeTypes.class); - private static final Logger LOG = LoggerFactory.getLogger(MimeTypes.class); - private static final Map __dftMimeMap = new HashMap(); - private static final Map __inferredEncodings = new HashMap(); - private static final Map __assumedEncodings = new HashMap(); - + /** Enumeration of predefined MimeTypes. This is not exhaustive */ public enum Type { FORM_ENCODED("application/x-www-form-urlencoded"), @@ -53,41 +47,41 @@ public class MimeTypes MULTIPART_FORM_DATA("multipart/form-data"), TEXT_HTML("text/html") - { - @Override - public HttpField getContentTypeField(Charset charset) { - if (Objects.equals(charset, StandardCharsets.UTF_8)) - return TEXT_HTML_UTF_8.getContentTypeField(); - if (Objects.equals(charset, StandardCharsets.ISO_8859_1)) - return TEXT_HTML_8859_1.getContentTypeField(); - return super.getContentTypeField(charset); - } - }, + @Override + public HttpField getContentTypeField(Charset charset) + { + if (Objects.equals(charset, StandardCharsets.UTF_8)) + 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") - { - @Override - public HttpField getContentTypeField(Charset charset) { - if (Objects.equals(charset, StandardCharsets.UTF_8)) - return TEXT_PLAIN_UTF_8.getContentTypeField(); - if (Objects.equals(charset, StandardCharsets.ISO_8859_1)) - return TEXT_PLAIN_8859_1.getContentTypeField(); - return super.getContentTypeField(charset); - } - }, + @Override + public HttpField getContentTypeField(Charset charset) + { + if (Objects.equals(charset, StandardCharsets.UTF_8)) + 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") - { - @Override - public HttpField getContentTypeField(Charset charset) { - if (Objects.equals(charset, StandardCharsets.UTF_8)) - return TEXT_XML_UTF_8.getContentTypeField(); - if (Objects.equals(charset, StandardCharsets.ISO_8859_1)) - return TEXT_XML_8859_1.getContentTypeField(); - return super.getContentTypeField(charset); - } - }, + @Override + public HttpField getContentTypeField(Charset charset) + { + if (Objects.equals(charset, StandardCharsets.UTF_8)) + 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), APPLICATION_JSON("application/json", StandardCharsets.UTF_8), @@ -108,7 +102,6 @@ public class MimeTypes private final String _string; private final Type _base; - private final ByteBuffer _buffer; private final Charset _charset; private final String _charsetString; private final boolean _assumedCharset; @@ -117,7 +110,6 @@ public class MimeTypes Type(String s) { _string = s; - _buffer = BufferUtil.toBuffer(s); _base = this; _charset = null; _charsetString = null; @@ -128,7 +120,6 @@ public class MimeTypes Type(String s, Type base) { _string = s; - _buffer = BufferUtil.toBuffer(s); _base = base; int i = s.indexOf(";charset="); _charset = Charset.forName(s.substring(i + 9)); @@ -141,18 +132,12 @@ public class MimeTypes { _string = s; _base = this; - _buffer = BufferUtil.toBuffer(s); _charset = cs; _charsetString = _charset == null ? null : _charset.toString().toLowerCase(Locale.ENGLISH); _assumedCharset = true; _field = new PreEncodedHttpField(HttpHeader.CONTENT_TYPE, _string); } - public ByteBuffer asBuffer() - { - return _buffer.asReadOnlyBuffer(); - } - public Charset getCharset() { return _charset; @@ -222,232 +207,215 @@ public class MimeTypes }) .build(); - static + protected final Map _mimeMap = new HashMap<>(); + protected final Map _inferredEncodings = new HashMap<>(); + protected final Map _assumedEncodings = new HashMap<>(); + + public MimeTypes() { - for (MimeTypes.Type type : MimeTypes.Type.values()) - { - if (type.isCharsetAssumed()) - __assumedEncodings.put(type.asString(), type.getCharsetString()); - } + this(DEFAULTS); + } - String resourceName = "mime.properties"; - try (InputStream stream = MimeTypes.class.getResourceAsStream(resourceName)) + public MimeTypes(MimeTypes defaults) + { + if (defaults != null) { - 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(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()); + _mimeMap.putAll(defaults.getMimeMap()); + _assumedEncodings.putAll(defaults.getAssumedMap()); + _inferredEncodings.putAll(defaults.getInferredMap()); } } - private final Map _mimeMap = new HashMap(); - /** - * 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 getMimeMap() { - return _mimeMap; + return Collections.unmodifiableMap(_mimeMap); } - /** - * @param mimeMap A Map of file extension to mime-type. - */ - public void setMimeMap(Map mimeMap) + public Map getInferredMap() { - _mimeMap.clear(); - if (mimeMap != null) + return Collections.unmodifiableMap(_inferredEncodings); + } + + public Map getAssumedMap() + { + return Collections.unmodifiableMap(_assumedEncodings); + } + + public static class Mutable extends MimeTypes + { + public Mutable() { - for (Entry 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 getKnownMimeTypes() - { - return new HashSet<>(__dftMimeMap.values()); - } + }; private static String normalizeMimeType(String type) { - MimeTypes.Type t = CACHE.get(type); + Type t = CACHE.get(type); if (t != null) return t.asString(); @@ -567,40 +535,6 @@ public class MimeTypes 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 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 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) { int end = value.length(); @@ -615,14 +549,7 @@ public class MimeTypes if ('"' == b) { - if (quote) - { - quote = false; - } - else - { - quote = true; - } + quote = !quote; switch (state) { diff --git a/jetty-core/jetty-http/src/main/resources/org/eclipse/jetty/http/mime.properties b/jetty-core/jetty-http/src/main/resources/org/eclipse/jetty/http/mime.properties index fe22dea39f1..b5039375d29 100644 --- a/jetty-core/jetty-http/src/main/resources/org/eclipse/jetty/http/mime.properties +++ b/jetty-core/jetty-http/src/main/resources/org/eclipse/jetty/http/mime.properties @@ -154,7 +154,6 @@ svgz=image/svg+xml swf=application/x-shockwave-flash t=application/x-troff tar=application/x-tar -tar.gz=application/x-gtar tcl=application/x-tcl tex=application/x-tex texi=application/x-texinfo diff --git a/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/MimeTypesTest.java b/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/MimeTypesTest.java index 9f7651e9f22..5d9704423d3 100644 --- a/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/MimeTypesTest.java +++ b/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/MimeTypesTest.java @@ -30,6 +30,8 @@ public class MimeTypesTest { return Stream.of( 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("zed.avif", "image/avif"), // make sure that filename case isn't an issue diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Context.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Context.java index c3daec8cad3..69ffa56d419 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Context.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Context.java @@ -16,6 +16,7 @@ package org.eclipse.jetty.server; import java.util.List; import java.util.concurrent.Executor; +import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.util.Attributes; import org.eclipse.jetty.util.Decorator; import org.eclipse.jetty.util.resource.Resource; @@ -47,6 +48,8 @@ public interface Context extends Attributes, Decorator, Executor List getVirtualHosts(); + MimeTypes getMimeTypes(); + @Override /** execute runnable in container thread scoped to context */ void execute(Runnable runnable); diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java index 78ce8581b71..c8a5560dff3 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java @@ -31,6 +31,7 @@ import org.eclipse.jetty.http.DateGenerator; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpGenerator; import org.eclipse.jetty.http.HttpHeader; +import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.http.PreEncodedHttpField; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.server.handler.ContextHandler; @@ -725,6 +726,12 @@ public class Server extends Handler.Wrapper implements Attributes return null; } + @Override + public MimeTypes getMimeTypes() + { + return MimeTypes.DEFAULTS; + } + @Override public ClassLoader getClassLoader() { diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/BufferedResponseHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/BufferedResponseHandler.java index 9b4bf9988a5..cabee3fd5bd 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/BufferedResponseHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/BufferedResponseHandler.java @@ -65,7 +65,7 @@ public class BufferedResponseHandler extends Handler.Wrapper public BufferedResponseHandler() { _methods.include(HttpMethod.GET.asString()); - for (String type : MimeTypes.getKnownMimeTypes()) + for (String type : MimeTypes.DEFAULTS.getMimeMap().values()) { if (type.startsWith("image/") || 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. - String mimeType = MimeTypes.getDefaultMimeByExtension(path); // TODO context specicif mimetypes : context.getMimeType(path); + String mimeType = request.getContext().getMimeTypes().getMimeByExtension(path); if (mimeType != null) { mimeType = MimeTypes.getContentTypeWithoutCharset(mimeType); diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index 5cf3ff98339..2534e3f467e 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -35,6 +35,7 @@ import java.util.stream.Collectors; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpStatus; +import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.server.AliasCheck; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Handler; @@ -87,9 +88,15 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace 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 Attributes _persistentAttributes = new Mapped(); + private final MimeTypes.Mutable _mimeTypes = new MimeTypes.Mutable(); private final List _contextListeners = new CopyOnWriteArrayList<>(); private final List _vhosts = new ArrayList<>(); @@ -158,6 +165,11 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace return new Context(); } + public MimeTypes.Mutable getMimeTypes() + { + return _mimeTypes; + } + @Override public void dump(Appendable out, String indent) throws IOException { @@ -1002,6 +1014,12 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace return _contextPath; } + @Override + public MimeTypes getMimeTypes() + { + return _mimeTypes; + } + @Override public String toString() { diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java index f2f931a4920..fedefec7123 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java @@ -74,9 +74,7 @@ public class ResourceHandler extends Handler.Wrapper _resourceBase = context.getBaseResource(); } - // TODO: _mimeTypes = _context == null ? new MimeTypes() : _context.getMimeTypes(); - if (_mimeTypes == null) - _mimeTypes = new MimeTypes(); + _mimeTypes = context == null ? MimeTypes.DEFAULTS : context.getMimeTypes(); _byteBufferPool = getByteBufferPool(context); _resourceService.setHttpContentFactory(newHttpContentFactory()); @@ -320,11 +318,6 @@ public class ResourceHandler extends Handler.Wrapper return _resourceService.getEncodingCacheSize(); } - public void setMimeTypes(MimeTypes mimeTypes) - { - _mimeTypes = mimeTypes; - } - /** * @param redirectWelcome If true, welcome files are redirected rather than forwarded to. * redirection is always used if the ResourceHandler is not scoped by diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java index 478b975eb1b..9ca2a1ca483 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java @@ -68,7 +68,7 @@ public class GzipHandler extends Handler.Wrapper implements GzipFactory { _methods.include(HttpMethod.GET.asString()); _methods.include(HttpMethod.POST.asString()); - for (String type : MimeTypes.getKnownMimeTypes()) + for (String type : MimeTypes.DEFAULTS.getMimeMap().values()) { if ("image/svg+xml".equals(type)) _paths.exclude("*.svgz"); @@ -624,9 +624,8 @@ public class GzipHandler extends Handler.Wrapper implements GzipFactory 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 - String mimeType = MimeTypes.getDefaultMimeByExtension(path); + String mimeType = request.getContext().getMimeTypes().getMimeByExtension(path); if (mimeType != null) { mimeType = HttpField.valueParameters(mimeType, null); diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/gzip/GzipHandlerTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/gzip/GzipHandlerTest.java index 36c986c8fc0..c19d47ac890 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/gzip/GzipHandlerTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/gzip/GzipHandlerTest.java @@ -48,7 +48,6 @@ import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpTester; import org.eclipse.jetty.http.HttpVersion; -import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.io.Content; import org.eclipse.jetty.server.Context; 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_GZIP = String.format("W/\"%x" + CompressedContentFormat.GZIP.getEtagSuffix() + "\"", CONTENT.hashCode()); - private static final MimeTypes MIME_TYPES = new MimeTypes(); - public WorkDir _workDir; private Server _server; private LocalConnector _connector; @@ -1667,9 +1664,8 @@ public class GzipHandlerTest if (parameters.get("type") != null) defaultContentType = parameters.get("type").getValue(); - // TODO get mime type from context. Context context = request.getContext(); - String contentType = MIME_TYPES.getMimeByExtension(filename); + String contentType = context.getMimeTypes().getMimeByExtension(filename); if (contentType != null) return contentType; return defaultContentType; diff --git a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/FileID.java b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/FileID.java index d27d07bd0b3..0a05ee26214 100644 --- a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/FileID.java +++ b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/FileID.java @@ -157,7 +157,9 @@ public class FileID * for the extension (if any), including the dot, lower-cased. * * @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) { diff --git a/jetty-ee10/jetty-ee10-maven-plugin/src/main/java/org/eclipse/jetty/ee10/maven/plugin/AbstractUnassembledWebAppMojo.java b/jetty-ee10/jetty-ee10-maven-plugin/src/main/java/org/eclipse/jetty/ee10/maven/plugin/AbstractUnassembledWebAppMojo.java index 5cbc243d977..78fc5a1ed93 100644 --- a/jetty-ee10/jetty-ee10-maven-plugin/src/main/java/org/eclipse/jetty/ee10/maven/plugin/AbstractUnassembledWebAppMojo.java +++ b/jetty-ee10/jetty-ee10-maven-plugin/src/main/java/org/eclipse/jetty/ee10/maven/plugin/AbstractUnassembledWebAppMojo.java @@ -21,7 +21,6 @@ import java.util.List; import java.util.stream.Collectors; import org.apache.maven.artifact.Artifact; -import org.apache.maven.plugin.AbstractMojoExecutionException; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Parameter; diff --git a/jetty-ee10/jetty-ee10-maven-plugin/src/main/java/org/eclipse/jetty/ee10/maven/plugin/JettyEffectiveWebXml.java b/jetty-ee10/jetty-ee10-maven-plugin/src/main/java/org/eclipse/jetty/ee10/maven/plugin/JettyEffectiveWebXml.java index 99be425a7b4..5c1e4fd1955 100644 --- a/jetty-ee10/jetty-ee10-maven-plugin/src/main/java/org/eclipse/jetty/ee10/maven/plugin/JettyEffectiveWebXml.java +++ b/jetty-ee10/jetty-ee10-maven-plugin/src/main/java/org/eclipse/jetty/ee10/maven/plugin/JettyEffectiveWebXml.java @@ -19,13 +19,10 @@ import java.net.URL; import java.nio.file.Path; import java.nio.file.Paths; -import org.apache.maven.plugin.AbstractMojoExecutionException; 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.Parameter; 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 diff --git a/jetty-ee10/jetty-ee10-maven-plugin/src/main/java/org/eclipse/jetty/ee10/maven/plugin/JettyRunWarMojo.java b/jetty-ee10/jetty-ee10-maven-plugin/src/main/java/org/eclipse/jetty/ee10/maven/plugin/JettyRunWarMojo.java index 8d5b69a5825..54533af55d2 100644 --- a/jetty-ee10/jetty-ee10-maven-plugin/src/main/java/org/eclipse/jetty/ee10/maven/plugin/JettyRunWarMojo.java +++ b/jetty-ee10/jetty-ee10-maven-plugin/src/main/java/org/eclipse/jetty/ee10/maven/plugin/JettyRunWarMojo.java @@ -19,7 +19,6 @@ import java.nio.file.Paths; import java.util.Date; import java.util.Set; -import org.apache.maven.plugin.AbstractMojoExecutionException; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.Execute; import org.apache.maven.plugins.annotations.LifecyclePhase; diff --git a/jetty-ee10/jetty-ee10-maven-plugin/src/main/java/org/eclipse/jetty/ee10/maven/plugin/JettyStartWarMojo.java b/jetty-ee10/jetty-ee10-maven-plugin/src/main/java/org/eclipse/jetty/ee10/maven/plugin/JettyStartWarMojo.java index a47d6679c7b..b6f6288f429 100644 --- a/jetty-ee10/jetty-ee10-maven-plugin/src/main/java/org/eclipse/jetty/ee10/maven/plugin/JettyStartWarMojo.java +++ b/jetty-ee10/jetty-ee10-maven-plugin/src/main/java/org/eclipse/jetty/ee10/maven/plugin/JettyStartWarMojo.java @@ -16,7 +16,6 @@ package org.eclipse.jetty.ee10.maven.plugin; import java.io.File; import java.nio.file.Path; -import org.apache.maven.plugin.AbstractMojoExecutionException; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java index 99bab2447fa..10aa708da8b 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java @@ -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.SecurityHandler; import org.eclipse.jetty.http.HttpURI; -import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.http.pathmap.MatchedResource; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Request; @@ -192,7 +191,6 @@ public class ServletContextHandler extends ContextHandler implements Graceful private String _defaultRequestCharacterEncoding; private String _defaultResponseCharacterEncoding; private String _contextPathEncoded = "/"; - protected MimeTypes _mimeTypes; // TODO move to core context? private Map _localeEncodingMap; private String[] _welcomeFiles; 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) { _welcomeFiles = files; @@ -1079,9 +1059,6 @@ public class ServletContextHandler extends ContextHandler implements Graceful if (getServer() != null) _servletContext.setAttribute("org.eclipse.jetty.server.Executor", getServer().getThreadPool()); - if (_mimeTypes == null) - _mimeTypes = new MimeTypes(); - _durableListeners.addAll(getEventListeners()); getContext().call(() -> @@ -2811,9 +2788,7 @@ public class ServletContextHandler extends ContextHandler implements Graceful @Override public String getMimeType(String file) { - if (_mimeTypes == null) - return null; - return _mimeTypes.getMimeByExtension(file); + return getContext().getMimeTypes().getMimeByExtension(file); } @Override diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextResponse.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextResponse.java index 9863184d543..5140e6e616b 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextResponse.java +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextResponse.java @@ -349,14 +349,15 @@ public class ServletContextResponse extends ContextResponse // Try charset from mime type. if (_mimeType != null && _mimeType.isCharsetAssumed()) return _mimeType.getCharsetString(); - + // 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) return encoding; // Try char set inferred from content type. - encoding = MimeTypes.getCharsetInferredFromContentType(_contentType); + encoding = mimeTypes.getCharsetInferredFromContentType(_contentType); if (encoding != null) { if (setContentType) diff --git a/jetty-ee10/jetty-ee10-servlets/src/main/java/org/eclipse/jetty/ee10/servlets/IncludeExcludeBasedFilter.java b/jetty-ee10/jetty-ee10-servlets/src/main/java/org/eclipse/jetty/ee10/servlets/IncludeExcludeBasedFilter.java index 7f3d47e21c9..ad37935e76e 100644 --- a/jetty-ee10/jetty-ee10-servlets/src/main/java/org/eclipse/jetty/ee10/servlets/IncludeExcludeBasedFilter.java +++ b/jetty-ee10/jetty-ee10-servlets/src/main/java/org/eclipse/jetty/ee10/servlets/IncludeExcludeBasedFilter.java @@ -13,6 +13,8 @@ package org.eclipse.jetty.ee10.servlets; +import java.util.Objects; + import jakarta.servlet.Filter; import jakarta.servlet.FilterConfig; import jakarta.servlet.ServletContext; @@ -109,7 +111,7 @@ public abstract class IncludeExcludeBasedFilter implements Filter String contentType = httpResponse.getContentType(); LOG.debug("Content Type is: {}", contentType); - String mimeType = ""; + String mimeType; if (contentType != null) { mimeType = MimeTypes.getContentTypeWithoutCharset(contentType); @@ -118,13 +120,7 @@ public abstract class IncludeExcludeBasedFilter implements Filter else { String requestUrl = httpRequest.getPathInfo(); - mimeType = MimeTypes.getDefaultMimeByExtension(requestUrl); - - if (mimeType == null) - { - mimeType = ""; - } - + mimeType = Objects.requireNonNullElse(httpRequest.getServletContext().getMimeType(requestUrl), ""); LOG.debug("Guessed mime type is {}", mimeType); } @@ -169,11 +165,9 @@ public abstract class IncludeExcludeBasedFilter implements Filter @Override public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("filter configuration:\n"); - sb.append("paths:\n").append(_paths).append("\n"); - sb.append("mime types:\n").append(_mimeTypes).append("\n"); - sb.append("http methods:\n").append(_httpMethods); - return sb.toString(); + return "filter configuration:\n" + + "paths:\n" + _paths + "\n" + + "mime types:\n" + _mimeTypes + "\n" + + "http methods:\n" + _httpMethods; } } diff --git a/jetty-ee10/jetty-ee10-servlets/src/test/java/org/eclipse/jetty/ee10/servlets/TestMinGzipSizeServlet.java b/jetty-ee10/jetty-ee10-servlets/src/test/java/org/eclipse/jetty/ee10/servlets/TestMinGzipSizeServlet.java index c7405f6293c..7fccbb48217 100644 --- a/jetty-ee10/jetty-ee10-servlets/src/test/java/org/eclipse/jetty/ee10/servlets/TestMinGzipSizeServlet.java +++ b/jetty-ee10/jetty-ee10-servlets/src/test/java/org/eclipse/jetty/ee10/servlets/TestMinGzipSizeServlet.java @@ -20,21 +20,16 @@ import jakarta.servlet.ServletException; import jakarta.servlet.ServletOutputStream; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import org.eclipse.jetty.http.MimeTypes; /** * Test servlet for testing against unusual minGzip configurable. */ -@SuppressWarnings("serial") public class TestMinGzipSizeServlet extends AbstractFileContentServlet { - private MimeTypes mimeTypes; - @Override public void init(ServletConfig config) throws ServletException { super.init(config); - mimeTypes = new MimeTypes(); } @Override @@ -52,7 +47,7 @@ public class TestMinGzipSizeServlet extends AbstractFileContentServlet } else { - String mime = mimeTypes.getMimeByExtension(fileName); + String mime = request.getServletContext().getMimeType(fileName); if (mime != null) response.setContentType(mime); } diff --git a/jetty-ee10/jetty-ee10-servlets/src/test/java/org/eclipse/jetty/ee10/servlets/TestStaticMimeTypeServlet.java b/jetty-ee10/jetty-ee10-servlets/src/test/java/org/eclipse/jetty/ee10/servlets/TestStaticMimeTypeServlet.java index e8d2f469d87..e60c5e44069 100644 --- a/jetty-ee10/jetty-ee10-servlets/src/test/java/org/eclipse/jetty/ee10/servlets/TestStaticMimeTypeServlet.java +++ b/jetty-ee10/jetty-ee10-servlets/src/test/java/org/eclipse/jetty/ee10/servlets/TestStaticMimeTypeServlet.java @@ -14,6 +14,7 @@ package org.eclipse.jetty.ee10.servlets; import java.io.IOException; +import java.util.Objects; import jakarta.servlet.ServletConfig; import jakarta.servlet.ServletException; @@ -25,16 +26,15 @@ import org.eclipse.jetty.http.MimeTypes; /** * Test servlet for testing against unusual MimeTypes and Content-Types. */ -@SuppressWarnings("serial") public class TestStaticMimeTypeServlet extends AbstractFileContentServlet { - private MimeTypes mimeTypes; + private MimeTypes.Mutable mimeTypes; @Override public void init(ServletConfig config) throws ServletException { super.init(config); - mimeTypes = new MimeTypes(); + mimeTypes = new MimeTypes.Mutable(); // Some real world, yet not terribly common, mime type mappings. mimeTypes.addMimeMapping("bz2", "application/bzip2"); mimeTypes.addMimeMapping("br", "application/brotli"); @@ -65,10 +65,7 @@ public class TestStaticMimeTypeServlet extends AbstractFileContentServlet response.setHeader("ETag", "W/etag-" + fileName); String mime = mimeTypes.getMimeByExtension(fileName); - if (mime == null) - response.setContentType("application/octet-stream"); - else - response.setContentType(mime); + response.setContentType(Objects.requireNonNullElse(mime, "application/octet-stream")); ServletOutputStream out = response.getOutputStream(); out.write(dataBytes); diff --git a/jetty-ee9/jetty-ee9-demos/jetty-ee9-demo-embedded/src/main/java/org/eclipse/jetty/ee9/demos/FastFileServer.java b/jetty-ee9/jetty-ee9-demos/jetty-ee9-demo-embedded/src/main/java/org/eclipse/jetty/ee9/demos/FastFileServer.java index aa10ab763dc..270e4355d66 100644 --- a/jetty-ee9/jetty-ee9-demos/jetty-ee9-demo-embedded/src/main/java/org/eclipse/jetty/ee9/demos/FastFileServer.java +++ b/jetty-ee9/jetty-ee9-demos/jetty-ee9-demo-embedded/src/main/java/org/eclipse/jetty/ee9/demos/FastFileServer.java @@ -15,19 +15,13 @@ package org.eclipse.jetty.ee9.demos; import java.io.File; -import jakarta.servlet.http.HttpServletResponse; 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.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.DefaultHandler; import org.eclipse.jetty.server.handler.HandlerList; 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. @@ -80,18 +74,15 @@ public class FastFileServer static class FastFileHandler extends Handler.Abstract { - private final MimeTypes mimeTypes = new MimeTypes(); - private final File dir; - private FastFileHandler(File dir) { - this.dir = dir; } @Override public Request.Processor handle(Request request) throws Exception { return null; + // TODO // return (req, response, callback) -> // { // response.getHeaders().add(HttpHeader.CONTENT_TYPE, "text/html; charset=utf-8"); diff --git a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/BufferedResponseHandler.java b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/BufferedResponseHandler.java index 05aa44f8ef7..14a8c8a2084 100644 --- a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/BufferedResponseHandler.java +++ b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/BufferedResponseHandler.java @@ -64,7 +64,7 @@ public class BufferedResponseHandler extends HandlerWrapper public BufferedResponseHandler() { _methods.include(HttpMethod.GET.asString()); - for (String type : MimeTypes.getKnownMimeTypes()) + for (String type : MimeTypes.DEFAULTS.getMimeMap().values()) { if (type.startsWith("image/") || 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. - String mimeType = context == null ? MimeTypes.getDefaultMimeByExtension(path) : context.getMimeType(path); + String mimeType = context == null ? MimeTypes.DEFAULTS.getMimeByExtension(path) : context.getMimeType(path); if (mimeType != null) { mimeType = MimeTypes.getContentTypeWithoutCharset(mimeType); diff --git a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ContextHandler.java b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ContextHandler.java index aa010fc9ae3..91dac11a678 100644 --- a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ContextHandler.java +++ b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ContextHandler.java @@ -194,7 +194,6 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu private String _defaultRequestCharacterEncoding; private String _defaultResponseCharacterEncoding; private String _contextPathEncoded = "/"; - private MimeTypes _mimeTypes; private Map _localeEncodingMap; private String[] _welcomeFiles; private ErrorHandler _errorHandler; @@ -625,9 +624,6 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu setAttribute("org.eclipse.jetty.server.Executor", getServer().getThreadPool()); - if (_mimeTypes == null) - _mimeTypes = new MimeTypes(); - _durableListeners.addAll(getEventListeners()); // 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. */ - public MimeTypes getMimeTypes() + public MimeTypes.Mutable getMimeTypes() { - if (_mimeTypes == null) - _mimeTypes = new MimeTypes(); - return _mimeTypes; - } - - /** - * @param mimeTypes The mimeTypes to set. - */ - public void setMimeTypes(MimeTypes mimeTypes) - { - _mimeTypes = mimeTypes; + return _coreContextHandler.getMimeTypes(); } public void setWelcomeFiles(String[] files) @@ -1766,9 +1752,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu @Override public String getMimeType(String file) { - if (_mimeTypes == null) - return null; - return _mimeTypes.getMimeByExtension(file); + return _coreContext.getMimeTypes().getMimeByExtension(file); } @Override diff --git a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ResourceHandler.java b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ResourceHandler.java index f2cf0368ddb..1628ec8d48f 100644 --- a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ResourceHandler.java +++ b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ResourceHandler.java @@ -103,7 +103,7 @@ public class ResourceHandler extends HandlerWrapper implements ResourceFactory, APIContext scontext = ContextHandler.getCurrentContext(); _context = (scontext == null ? null : scontext.getContextHandler()); if (_mimeTypes == null) - _mimeTypes = _context == null ? new MimeTypes() : _context.getMimeTypes(); + _mimeTypes = _context == null ? MimeTypes.DEFAULTS : _context.getMimeTypes(); _byteBufferPool = getByteBufferPool(_context); if (_resourceService.getHttpContentFactory() == null) diff --git a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/Response.java b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/Response.java index 2b6288c40ff..ef49623c993 100644 --- a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/Response.java +++ b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/Response.java @@ -792,13 +792,16 @@ public class Response implements HttpServletResponse if (_mimeType != null && _mimeType.isCharsetAssumed()) 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). - encoding = MimeTypes.getCharsetAssumedFromContentType(_contentType); + encoding = mimeTypes.getCharsetAssumedFromContentType(_contentType); if (encoding != null) return encoding; // Try char set inferred from content type. - encoding = MimeTypes.getCharsetInferredFromContentType(_contentType); + encoding = mimeTypes.getCharsetInferredFromContentType(_contentType); if (encoding != null) { if (setContentType) diff --git a/jetty-ee9/jetty-ee9-nested/src/test/java/org/eclipse/jetty/ee9/nested/ResponseTest.java b/jetty-ee9/jetty-ee9-nested/src/test/java/org/eclipse/jetty/ee9/nested/ResponseTest.java index c4666521b0f..e42066daf76 100644 --- a/jetty-ee9/jetty-ee9-nested/src/test/java/org/eclipse/jetty/ee9/nested/ResponseTest.java +++ b/jetty-ee9/jetty-ee9-nested/src/test/java/org/eclipse/jetty/ee9/nested/ResponseTest.java @@ -49,7 +49,6 @@ import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; -import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.io.ByteArrayEndPoint; import org.eclipse.jetty.io.Content; import org.eclipse.jetty.io.EndPoint; @@ -446,7 +445,7 @@ public class ResponseTest public void testLocaleAndContentTypeEncoding() throws Exception { _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("zh_CN", "gb18030"); _server.start(); diff --git a/jetty-ee9/jetty-ee9-servlets/src/main/java/org/eclipse/jetty/ee9/servlets/IncludeExcludeBasedFilter.java b/jetty-ee9/jetty-ee9-servlets/src/main/java/org/eclipse/jetty/ee9/servlets/IncludeExcludeBasedFilter.java index 282e5d6d356..e5b493b6b07 100644 --- a/jetty-ee9/jetty-ee9-servlets/src/main/java/org/eclipse/jetty/ee9/servlets/IncludeExcludeBasedFilter.java +++ b/jetty-ee9/jetty-ee9-servlets/src/main/java/org/eclipse/jetty/ee9/servlets/IncludeExcludeBasedFilter.java @@ -13,12 +13,15 @@ package org.eclipse.jetty.ee9.servlets; +import java.util.Objects; + import jakarta.servlet.Filter; import jakarta.servlet.FilterConfig; import jakarta.servlet.ServletContext; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import org.eclipse.jetty.ee9.nested.Request; import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.http.pathmap.PathSpecSet; import org.eclipse.jetty.util.IncludeExclude; @@ -118,12 +121,10 @@ public abstract class IncludeExcludeBasedFilter implements Filter else { String requestUrl = httpRequest.getPathInfo(); - mimeType = MimeTypes.getDefaultMimeByExtension(requestUrl); - - if (mimeType == null) - { - mimeType = ""; - } + Request baseRequest = Request.getBaseRequest(httpRequest); + mimeType = Objects.requireNonNullElse( + (baseRequest == null ? MimeTypes.DEFAULTS : baseRequest.getCoreRequest().getContext().getMimeTypes()) + .getMimeByExtension(requestUrl), ""); LOG.debug("Guessed mime type is {}", mimeType); } diff --git a/jetty-ee9/jetty-ee9-servlets/src/test/java/org/eclipse/jetty/ee9/servlets/TestMinGzipSizeServlet.java b/jetty-ee9/jetty-ee9-servlets/src/test/java/org/eclipse/jetty/ee9/servlets/TestMinGzipSizeServlet.java index f9a8d87bd99..dca9cb4ce07 100644 --- a/jetty-ee9/jetty-ee9-servlets/src/test/java/org/eclipse/jetty/ee9/servlets/TestMinGzipSizeServlet.java +++ b/jetty-ee9/jetty-ee9-servlets/src/test/java/org/eclipse/jetty/ee9/servlets/TestMinGzipSizeServlet.java @@ -20,21 +20,17 @@ import jakarta.servlet.ServletException; import jakarta.servlet.ServletOutputStream; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import org.eclipse.jetty.http.MimeTypes; /** * Test servlet for testing against unusual minGzip configurable. */ -@SuppressWarnings("serial") public class TestMinGzipSizeServlet extends AbstractFileContentServlet { - private MimeTypes mimeTypes; @Override public void init(ServletConfig config) throws ServletException { super.init(config); - mimeTypes = new MimeTypes(); } @Override @@ -52,7 +48,7 @@ public class TestMinGzipSizeServlet extends AbstractFileContentServlet } else { - String mime = mimeTypes.getMimeByExtension(fileName); + String mime = request.getServletContext().getMimeType(fileName); if (mime != null) response.setContentType(mime); } diff --git a/jetty-ee9/jetty-ee9-servlets/src/test/java/org/eclipse/jetty/ee9/servlets/TestStaticMimeTypeServlet.java b/jetty-ee9/jetty-ee9-servlets/src/test/java/org/eclipse/jetty/ee9/servlets/TestStaticMimeTypeServlet.java index 0ca80a6ae17..7e8120abaab 100644 --- a/jetty-ee9/jetty-ee9-servlets/src/test/java/org/eclipse/jetty/ee9/servlets/TestStaticMimeTypeServlet.java +++ b/jetty-ee9/jetty-ee9-servlets/src/test/java/org/eclipse/jetty/ee9/servlets/TestStaticMimeTypeServlet.java @@ -14,6 +14,7 @@ package org.eclipse.jetty.ee9.servlets; import java.io.IOException; +import java.util.Objects; import jakarta.servlet.ServletConfig; import jakarta.servlet.ServletException; @@ -25,16 +26,15 @@ import org.eclipse.jetty.http.MimeTypes; /** * Test servlet for testing against unusual MimeTypes and Content-Types. */ -@SuppressWarnings("serial") public class TestStaticMimeTypeServlet extends AbstractFileContentServlet { - private MimeTypes mimeTypes; + private MimeTypes.Mutable mimeTypes; @Override public void init(ServletConfig config) throws ServletException { super.init(config); - mimeTypes = new MimeTypes(); + mimeTypes = new MimeTypes.Mutable(); // Some real world, yet not terribly common, mime type mappings. mimeTypes.addMimeMapping("bz2", "application/bzip2"); mimeTypes.addMimeMapping("br", "application/brotli"); @@ -65,10 +65,7 @@ public class TestStaticMimeTypeServlet extends AbstractFileContentServlet response.setHeader("ETag", "W/etag-" + fileName); String mime = mimeTypes.getMimeByExtension(fileName); - if (mime == null) - response.setContentType("application/octet-stream"); - else - response.setContentType(mime); + response.setContentType(Objects.requireNonNullElse(mime, "application/octet-stream")); ServletOutputStream out = response.getOutputStream(); out.write(dataBytes);