Mutable server MimeTypes (#8933)

Make the MimeTypes available from the server mutable.
Context MimeTypes are now wrappers over the server MimeTypes, so configuration at the server level is inherited by all contexts.
This commit is contained in:
Greg Wilkins 2022-11-24 16:57:29 +11:00 committed by GitHub
parent 2460b86d41
commit ca3055423a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 153 additions and 4 deletions

View File

@ -273,6 +273,7 @@ public class MimeTypes
{
public Mutable()
{
this(DEFAULTS);
}
public Mutable(MimeTypes defaults)
@ -305,6 +306,80 @@ public class MimeTypes
}
}
public static class Wrapper extends Mutable
{
private MimeTypes _wrapped;
public Wrapper()
{
super(null);
}
public MimeTypes getWrapped()
{
return _wrapped;
}
public void setWrapped(MimeTypes wrapped)
{
_wrapped = wrapped;
}
@Override
public String getMimeForExtension(String extension)
{
String mime = super.getMimeForExtension(extension);
return mime == null && _wrapped != null ? _wrapped.getMimeForExtension(extension) : mime;
}
@Override
public String getCharsetInferredFromContentType(String contentType)
{
String charset = super.getCharsetInferredFromContentType(contentType);
return charset == null && _wrapped != null ? _wrapped.getCharsetInferredFromContentType(contentType) : charset;
}
@Override
public String getCharsetAssumedFromContentType(String contentType)
{
String charset = super.getCharsetAssumedFromContentType(contentType);
return charset == null && _wrapped != null ? _wrapped.getCharsetAssumedFromContentType(contentType) : charset;
}
@Override
public Map<String, String> getMimeMap()
{
Map<String, String> map = super.getMimeMap();
if (_wrapped == null || map.isEmpty())
return map;
map = new HashMap<>(map);
map.putAll(_wrapped.getMimeMap());
return Collections.unmodifiableMap(map);
}
@Override
public Map<String, String> getInferredMap()
{
Map<String, String> map = super.getInferredMap();
if (_wrapped == null || map.isEmpty())
return map;
map = new HashMap<>(map);
map.putAll(_wrapped.getInferredMap());
return Collections.unmodifiableMap(map);
}
@Override
public Map<String, String> getAssumedMap()
{
Map<String, String> map = super.getAssumedMap();
if (_wrapped == null || map.isEmpty())
return map;
map = new HashMap<>(map);
map.putAll(_wrapped.getAssumedMap());
return Collections.unmodifiableMap(map);
}
}
public static final MimeTypes DEFAULTS = new MimeTypes(null)
{
{

View File

@ -126,4 +126,62 @@ public class MimeTypesTest
assertThat("MimeTypes.getContentTypeWithoutCharset(\"" + contentTypeWithCharset + "\")",
MimeTypes.getContentTypeWithoutCharset(contentTypeWithCharset), is(expectedContentType));
}
@Test
public void testWrapper()
{
MimeTypes.Wrapper wrapper = new MimeTypes.Wrapper();
assertThat(wrapper.getMimeMap().size(), is(0));
assertThat(wrapper.getInferredMap().size(), is(0));
assertThat(wrapper.getAssumedMap().size(), is(0));
wrapper.addMimeMapping("txt", "text/plain");
wrapper.addInferred("text/plain", "usascii");
wrapper.addAssumed("json", "utf-8");
assertThat(wrapper.getMimeMap().size(), is(1));
assertThat(wrapper.getInferredMap().size(), is(1));
assertThat(wrapper.getAssumedMap().size(), is(1));
assertThat(wrapper.getMimeByExtension("fee.txt"), is("text/plain"));
assertThat(wrapper.getCharsetInferredFromContentType("text/plain"), is("usascii"));
assertThat(wrapper.getCharsetAssumedFromContentType("json"), is("utf-8"));
MimeTypes.Mutable wrapped = new MimeTypes.Mutable(null);
wrapper.setWrapped(wrapped);
assertThat(wrapper.getMimeMap().size(), is(1));
assertThat(wrapper.getInferredMap().size(), is(1));
assertThat(wrapper.getAssumedMap().size(), is(1));
assertThat(wrapper.getMimeByExtension("fee.txt"), is("text/plain"));
assertThat(wrapper.getCharsetInferredFromContentType("text/plain"), is("usascii"));
assertThat(wrapper.getCharsetAssumedFromContentType("json"), is("utf-8"));
wrapped.addMimeMapping("txt", "overridden");
wrapped.addInferred("text/plain", "overridden");
wrapped.addAssumed("json", "overridden");
assertThat(wrapper.getMimeMap().size(), is(1));
assertThat(wrapper.getInferredMap().size(), is(1));
assertThat(wrapper.getAssumedMap().size(), is(1));
assertThat(wrapper.getMimeByExtension("fee.txt"), is("text/plain"));
assertThat(wrapper.getCharsetInferredFromContentType("text/plain"), is("usascii"));
assertThat(wrapper.getCharsetAssumedFromContentType("json"), is("utf-8"));
wrapped.addMimeMapping("xml", "text/xml");
wrapped.addInferred("text/xml", "iso-8859-1");
wrapped.addAssumed("text/xxx", "assumed");
assertThat(wrapped.getMimeMap().size(), is(2));
assertThat(wrapped.getInferredMap().size(), is(2));
assertThat(wrapped.getAssumedMap().size(), is(2));
assertThat(wrapper.getMimeMap().size(), is(2));
assertThat(wrapper.getInferredMap().size(), is(2));
assertThat(wrapper.getAssumedMap().size(), is(2));
assertThat(wrapper.getMimeByExtension("fee.txt"), is("text/plain"));
assertThat(wrapper.getCharsetInferredFromContentType("text/plain"), is("usascii"));
assertThat(wrapper.getCharsetAssumedFromContentType("json"), is("utf-8"));
assertThat(wrapper.getMimeByExtension("fee.xml"), is("text/xml"));
assertThat(wrapper.getCharsetInferredFromContentType("text/xml"), is("iso-8859-1"));
assertThat(wrapper.getCharsetAssumedFromContentType("text/xxx"), is("assumed"));
}
}

View File

@ -70,6 +70,7 @@ public class Server extends Handler.Wrapper implements Attributes
private final List<Connector> _connectors = new CopyOnWriteArrayList<>();
private final Context _serverContext = new ServerContext();
private final AutoLock _dateLock = new AutoLock();
private final MimeTypes.Mutable _mimeTypes = new MimeTypes.Mutable();
private String _serverInfo = __serverInfo;
private boolean _stopAtShutdown;
private boolean _dumpAfterStart;
@ -141,6 +142,11 @@ public class Server extends Handler.Wrapper implements Attributes
return _serverContext;
}
public MimeTypes.Mutable getMimeTypes()
{
return _mimeTypes;
}
@Override
public InvocationType getInvocationType()
{
@ -729,7 +735,7 @@ public class Server extends Handler.Wrapper implements Attributes
@Override
public MimeTypes getMimeTypes()
{
return MimeTypes.DEFAULTS;
return _mimeTypes;
}
@Override

View File

@ -96,7 +96,7 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace
*/
private final Context _context;
private final Attributes _persistentAttributes = new Mapped();
private final MimeTypes.Mutable _mimeTypes = new MimeTypes.Mutable();
private final MimeTypes.Wrapper _mimeTypes = new MimeTypes.Wrapper();
private final List<ContextScopeListener> _contextListeners = new CopyOnWriteArrayList<>();
private final List<VHost> _vhosts = new ArrayList<>();
@ -160,11 +160,23 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace
addAliasCheck(new SymlinkAllowedResourceAliasChecker(this));
}
@Override
public void setServer(Server server)
{
super.setServer(server);
_mimeTypes.setWrapped(server.getMimeTypes());
}
protected Context newContext()
{
return new Context();
}
/**
* @return A mutable MimeTypes that wraps the {@link Server#getMimeTypes()}
* once {@link ContextHandler#setServer(Server)} has been called.
* @see MimeTypes.Wrapper
*/
public MimeTypes.Mutable getMimeTypes()
{
return _mimeTypes;

View File

@ -179,8 +179,6 @@ public class ContextHandlerTest
assertThat(stream.getResponse().getStatus(), equalTo(200));
assertThat(stream.getResponseHeaders().get(HttpHeader.CONTENT_TYPE), equalTo(MimeTypes.Type.TEXT_PLAIN_UTF_8.asString()));
assertThat(BufferUtil.toString(stream.getResponseContent()), equalTo(helloHandler.getMessage()));
}
private void assertInContext(Request request)