From 7728ae4e00d939d8c26d9354c464659ee1a80830 Mon Sep 17 00:00:00 2001 From: Guirong Hu Date: Wed, 17 Aug 2022 16:02:37 +0800 Subject: [PATCH 1/2] Align MimeMappings with Tomcat's defaults Update `MimeMappings` to align with the default values used in Tomcat. The mime mapping are now loaded from a properties file and a test has been added to ensure that they remain in sync with Tomcat's defaults. See gh-32101 --- .../boot/web/server/MimeMappings.java | 191 +-- .../boot/web/server/mime-mappings.properties | 1025 +++++++++++++++++ .../AbstractServletWebServerFactoryTests.java | 17 + 3 files changed, 1056 insertions(+), 177 deletions(-) create mode 100644 spring-boot-project/spring-boot/src/main/resources/org/springframework/boot/web/server/mime-mappings.properties diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/MimeMappings.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/MimeMappings.java index 33928044ef7..3c92df87c0a 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/MimeMappings.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/MimeMappings.java @@ -16,12 +16,16 @@ package org.springframework.boot.web.server; +import java.io.IOException; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; +import java.util.Properties; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.support.PropertiesLoaderUtils; import org.springframework.util.Assert; /** @@ -40,183 +44,16 @@ public final class MimeMappings implements Iterable { static { MimeMappings mappings = new MimeMappings(); - mappings.add("abs", "audio/x-mpeg"); - mappings.add("ai", "application/postscript"); - mappings.add("aif", "audio/x-aiff"); - mappings.add("aifc", "audio/x-aiff"); - mappings.add("aiff", "audio/x-aiff"); - mappings.add("aim", "application/x-aim"); - mappings.add("art", "image/x-jg"); - mappings.add("asf", "video/x-ms-asf"); - mappings.add("asx", "video/x-ms-asf"); - mappings.add("au", "audio/basic"); - mappings.add("avi", "video/x-msvideo"); - mappings.add("avx", "video/x-rad-screenplay"); - mappings.add("bcpio", "application/x-bcpio"); - mappings.add("bin", "application/octet-stream"); - mappings.add("bmp", "image/bmp"); - mappings.add("body", "text/html"); - mappings.add("cdf", "application/x-cdf"); - mappings.add("cer", "application/pkix-cert"); - mappings.add("class", "application/java"); - mappings.add("cpio", "application/x-cpio"); - mappings.add("csh", "application/x-csh"); - mappings.add("css", "text/css"); - mappings.add("dib", "image/bmp"); - mappings.add("doc", "application/msword"); - mappings.add("dtd", "application/xml-dtd"); - mappings.add("dv", "video/x-dv"); - mappings.add("dvi", "application/x-dvi"); - mappings.add("eot", "application/vnd.ms-fontobject"); - mappings.add("eps", "application/postscript"); - mappings.add("etx", "text/x-setext"); - mappings.add("exe", "application/octet-stream"); - mappings.add("gif", "image/gif"); - mappings.add("gtar", "application/x-gtar"); - mappings.add("gz", "application/x-gzip"); - mappings.add("hdf", "application/x-hdf"); - mappings.add("hqx", "application/mac-binhex40"); - mappings.add("htc", "text/x-component"); - mappings.add("htm", "text/html"); - mappings.add("html", "text/html"); - mappings.add("ief", "image/ief"); - mappings.add("jad", "text/vnd.sun.j2me.app-descriptor"); - mappings.add("jar", "application/java-archive"); - mappings.add("java", "text/x-java-source"); - mappings.add("jnlp", "application/x-java-jnlp-file"); - mappings.add("jpe", "image/jpeg"); - mappings.add("jpeg", "image/jpeg"); - mappings.add("jpg", "image/jpeg"); - mappings.add("js", "application/javascript"); - mappings.add("jsf", "text/plain"); - mappings.add("json", "application/json"); - mappings.add("jspf", "text/plain"); - mappings.add("kar", "audio/midi"); - mappings.add("latex", "application/x-latex"); - mappings.add("m3u", "audio/x-mpegurl"); - mappings.add("mac", "image/x-macpaint"); - mappings.add("man", "text/troff"); - mappings.add("mathml", "application/mathml+xml"); - mappings.add("me", "text/troff"); - mappings.add("mid", "audio/midi"); - mappings.add("midi", "audio/midi"); - mappings.add("mif", "application/x-mif"); - mappings.add("mov", "video/quicktime"); - mappings.add("movie", "video/x-sgi-movie"); - mappings.add("mp1", "audio/mpeg"); - mappings.add("mp2", "audio/mpeg"); - mappings.add("mp3", "audio/mpeg"); - mappings.add("mp4", "video/mp4"); - mappings.add("mpa", "audio/mpeg"); - mappings.add("mpe", "video/mpeg"); - mappings.add("mpeg", "video/mpeg"); - mappings.add("mpega", "audio/x-mpeg"); - mappings.add("mpg", "video/mpeg"); - mappings.add("mpv2", "video/mpeg2"); - mappings.add("ms", "application/x-wais-source"); - mappings.add("nc", "application/x-netcdf"); - mappings.add("oda", "application/oda"); - mappings.add("odb", "application/vnd.oasis.opendocument.database"); - mappings.add("odc", "application/vnd.oasis.opendocument.chart"); - mappings.add("odf", "application/vnd.oasis.opendocument.formula"); - mappings.add("odg", "application/vnd.oasis.opendocument.graphics"); - mappings.add("odi", "application/vnd.oasis.opendocument.image"); - mappings.add("odm", "application/vnd.oasis.opendocument.text-master"); - mappings.add("odp", "application/vnd.oasis.opendocument.presentation"); - mappings.add("ods", "application/vnd.oasis.opendocument.spreadsheet"); - mappings.add("odt", "application/vnd.oasis.opendocument.text"); - mappings.add("otg", "application/vnd.oasis.opendocument.graphics-template"); - mappings.add("oth", "application/vnd.oasis.opendocument.text-web"); - mappings.add("otp", "application/vnd.oasis.opendocument.presentation-template"); - mappings.add("ots", "application/vnd.oasis.opendocument.spreadsheet-template"); - mappings.add("ott", "application/vnd.oasis.opendocument.text-template"); - mappings.add("ogx", "application/ogg"); - mappings.add("ogv", "video/ogg"); - mappings.add("oga", "audio/ogg"); - mappings.add("ogg", "audio/ogg"); - mappings.add("otf", "application/x-font-opentype"); - mappings.add("spx", "audio/ogg"); - mappings.add("flac", "audio/flac"); - mappings.add("anx", "application/annodex"); - mappings.add("axa", "audio/annodex"); - mappings.add("axv", "video/annodex"); - mappings.add("xspf", "application/xspf+xml"); - mappings.add("pbm", "image/x-portable-bitmap"); - mappings.add("pct", "image/pict"); - mappings.add("pdf", "application/pdf"); - mappings.add("pgm", "image/x-portable-graymap"); - mappings.add("pic", "image/pict"); - mappings.add("pict", "image/pict"); - mappings.add("pls", "audio/x-scpls"); - mappings.add("png", "image/png"); - mappings.add("pnm", "image/x-portable-anymap"); - mappings.add("pnt", "image/x-macpaint"); - mappings.add("ppm", "image/x-portable-pixmap"); - mappings.add("ppt", "application/vnd.ms-powerpoint"); - mappings.add("pps", "application/vnd.ms-powerpoint"); - mappings.add("ps", "application/postscript"); - mappings.add("psd", "image/vnd.adobe.photoshop"); - mappings.add("qt", "video/quicktime"); - mappings.add("qti", "image/x-quicktime"); - mappings.add("qtif", "image/x-quicktime"); - mappings.add("ras", "image/x-cmu-raster"); - mappings.add("rdf", "application/rdf+xml"); - mappings.add("rgb", "image/x-rgb"); - mappings.add("rm", "application/vnd.rn-realmedia"); - mappings.add("roff", "text/troff"); - mappings.add("rtf", "application/rtf"); - mappings.add("rtx", "text/richtext"); - mappings.add("sfnt", "application/font-sfnt"); - mappings.add("sh", "application/x-sh"); - mappings.add("shar", "application/x-shar"); - mappings.add("sit", "application/x-stuffit"); - mappings.add("snd", "audio/basic"); - mappings.add("src", "application/x-wais-source"); - mappings.add("sv4cpio", "application/x-sv4cpio"); - mappings.add("sv4crc", "application/x-sv4crc"); - mappings.add("svg", "image/svg+xml"); - mappings.add("svgz", "image/svg+xml"); - mappings.add("swf", "application/x-shockwave-flash"); - mappings.add("t", "text/troff"); - mappings.add("tar", "application/x-tar"); - mappings.add("tcl", "application/x-tcl"); - mappings.add("tex", "application/x-tex"); - mappings.add("texi", "application/x-texinfo"); - mappings.add("texinfo", "application/x-texinfo"); - mappings.add("tif", "image/tiff"); - mappings.add("tiff", "image/tiff"); - mappings.add("tr", "text/troff"); - mappings.add("tsv", "text/tab-separated-values"); - mappings.add("ttf", "application/x-font-ttf"); - mappings.add("txt", "text/plain"); - mappings.add("ulw", "audio/basic"); - mappings.add("ustar", "application/x-ustar"); - mappings.add("vxml", "application/voicexml+xml"); - mappings.add("xbm", "image/x-xbitmap"); - mappings.add("xht", "application/xhtml+xml"); - mappings.add("xhtml", "application/xhtml+xml"); - mappings.add("xls", "application/vnd.ms-excel"); - mappings.add("xml", "application/xml"); - mappings.add("xpm", "image/x-xpixmap"); - mappings.add("xsl", "application/xml"); - mappings.add("xslt", "application/xslt+xml"); - mappings.add("xul", "application/vnd.mozilla.xul+xml"); - mappings.add("xwd", "image/x-xwindowdump"); - mappings.add("vsd", "application/vnd.visio"); - mappings.add("wasm", "application/wasm"); - mappings.add("wav", "audio/x-wav"); - mappings.add("wbmp", "image/vnd.wap.wbmp"); - mappings.add("wml", "text/vnd.wap.wml"); - mappings.add("wmlc", "application/vnd.wap.wmlc"); - mappings.add("wmls", "text/vnd.wap.wmlsc"); - mappings.add("wmlscriptc", "application/vnd.wap.wmlscriptc"); - mappings.add("wmv", "video/x-ms-wmv"); - mappings.add("woff", "application/font-woff"); - mappings.add("woff2", "application/font-woff2"); - mappings.add("wrl", "model/vrml"); - mappings.add("wspolicy", "application/wspolicy+xml"); - mappings.add("z", "application/x-compress"); - mappings.add("zip", "application/zip"); + try { + Properties defaultMimeMappings = PropertiesLoaderUtils + .loadProperties(new ClassPathResource("mime-mappings.properties", MimeMappings.class)); + for (String extension : defaultMimeMappings.stringPropertyNames()) { + mappings.add(extension, defaultMimeMappings.getProperty(extension)); + } + } + catch (IOException ex) { + throw new IllegalArgumentException("Unable to load the default MIME types", ex); + } DEFAULT = unmodifiableMappings(mappings); } diff --git a/spring-boot-project/spring-boot/src/main/resources/org/springframework/boot/web/server/mime-mappings.properties b/spring-boot-project/spring-boot/src/main/resources/org/springframework/boot/web/server/mime-mappings.properties new file mode 100644 index 00000000000..ab9ebf00190 --- /dev/null +++ b/spring-boot-project/spring-boot/src/main/resources/org/springframework/boot/web/server/mime-mappings.properties @@ -0,0 +1,1025 @@ +# Copyright 2012-2022 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +123=application/vnd.lotus-1-2-3 +3dml=text/vnd.in3d.3dml +3ds=image/x-3ds +3g2=video/3gpp2 +3gp=video/3gpp +7z=application/x-7z-compressed +aab=application/x-authorware-bin +aac=audio/x-aac +aam=application/x-authorware-map +aas=application/x-authorware-seg +abs=audio/x-mpeg +abw=application/x-abiword +ac=application/pkix-attr-cert +acc=application/vnd.americandynamics.acc +ace=application/x-ace-compressed +acu=application/vnd.acucobol +acutc=application/vnd.acucorp +adp=audio/adpcm +aep=application/vnd.audiograph +afm=application/x-font-type1 +afp=application/vnd.ibm.modcap +ahead=application/vnd.ahead.space +ai=application/postscript +aif=audio/x-aiff +aifc=audio/x-aiff +aiff=audio/x-aiff +aim=application/x-aim +air=application/vnd.adobe.air-application-installer-package+zip +ait=application/vnd.dvb.ait +ami=application/vnd.amiga.ami +anx=application/annodex +apk=application/vnd.android.package-archive +appcache=text/cache-manifest +application=application/x-ms-application +apr=application/vnd.lotus-approach +arc=application/x-freearc +art=image/x-jg +asc=application/pgp-signature +asf=video/x-ms-asf +asm=text/x-asm +aso=application/vnd.accpac.simply.aso +asx=video/x-ms-asf +atc=application/vnd.acucorp +atom=application/atom+xml +atomcat=application/atomcat+xml +atomsvc=application/atomsvc+xml +atx=application/vnd.antix.game-component +au=audio/basic +avi=video/x-msvideo +avx=video/x-rad-screenplay +aw=application/applixware +axa=audio/annodex +axv=video/annodex +azf=application/vnd.airzip.filesecure.azf +azs=application/vnd.airzip.filesecure.azs +azw=application/vnd.amazon.ebook +bat=application/x-msdownload +bcpio=application/x-bcpio +bdf=application/x-font-bdf +bdm=application/vnd.syncml.dm+wbxml +bed=application/vnd.realvnc.bed +bh2=application/vnd.fujitsu.oasysprs +bin=application/octet-stream +blb=application/x-blorb +blorb=application/x-blorb +bmi=application/vnd.bmi +bmp=image/bmp +body=text/html +book=application/vnd.framemaker +box=application/vnd.previewsystems.box +boz=application/x-bzip2 +bpk=application/octet-stream +btif=image/prs.btif +bz=application/x-bzip +bz2=application/x-bzip2 +c=text/x-c +c11amc=application/vnd.cluetrust.cartomobile-config +c11amz=application/vnd.cluetrust.cartomobile-config-pkg +c4d=application/vnd.clonk.c4group +c4f=application/vnd.clonk.c4group +c4g=application/vnd.clonk.c4group +c4p=application/vnd.clonk.c4group +c4u=application/vnd.clonk.c4group +cab=application/vnd.ms-cab-compressed +caf=audio/x-caf +cap=application/vnd.tcpdump.pcap +car=application/vnd.curl.car +cat=application/vnd.ms-pki.seccat +cb7=application/x-cbr +cba=application/x-cbr +cbr=application/x-cbr +cbt=application/x-cbr +cbz=application/x-cbr +cc=text/x-c +cct=application/x-director +ccxml=application/ccxml+xml +cdbcmsg=application/vnd.contact.cmsg +cdf=application/x-cdf +cdkey=application/vnd.mediastation.cdkey +cdmia=application/cdmi-capability +cdmic=application/cdmi-container +cdmid=application/cdmi-domain +cdmio=application/cdmi-object +cdmiq=application/cdmi-queue +cdx=chemical/x-cdx +cdxml=application/vnd.chemdraw+xml +cdy=application/vnd.cinderella +cer=application/pkix-cert +cfs=application/x-cfs-compressed +cgm=image/cgm +chat=application/x-chat +chm=application/vnd.ms-htmlhelp +chrt=application/vnd.kde.kchart +cif=chemical/x-cif +cii=application/vnd.anser-web-certificate-issue-initiation +cil=application/vnd.ms-artgalry +cla=application/vnd.claymore +class=application/java +clkk=application/vnd.crick.clicker.keyboard +clkp=application/vnd.crick.clicker.palette +clkt=application/vnd.crick.clicker.template +clkw=application/vnd.crick.clicker.wordbank +clkx=application/vnd.crick.clicker +clp=application/x-msclip +cmc=application/vnd.cosmocaller +cmdf=chemical/x-cmdf +cml=chemical/x-cml +cmp=application/vnd.yellowriver-custom-menu +cmx=image/x-cmx +cod=application/vnd.rim.cod +com=application/x-msdownload +conf=text/plain +cpio=application/x-cpio +cpp=text/x-c +cpt=application/mac-compactpro +crd=application/x-mscardfile +crl=application/pkix-crl +crt=application/x-x509-ca-cert +cryptonote=application/vnd.rig.cryptonote +csh=application/x-csh +csml=chemical/x-csml +csp=application/vnd.commonspace +css=text/css +cst=application/x-director +csv=text/csv +cu=application/cu-seeme +curl=text/vnd.curl +cww=application/prs.cww +cxt=application/x-director +cxx=text/x-c +dae=model/vnd.collada+xml +daf=application/vnd.mobius.daf +dart=application/vnd.dart +dataless=application/vnd.fdsn.seed +davmount=application/davmount+xml +dbk=application/docbook+xml +dcr=application/x-director +dcurl=text/vnd.curl.dcurl +dd2=application/vnd.oma.dd2+xml +ddd=application/vnd.fujixerox.ddd +deb=application/x-debian-package +def=text/plain +deploy=application/octet-stream +der=application/x-x509-ca-cert +dfac=application/vnd.dreamfactory +dgc=application/x-dgc-compressed +dib=image/bmp +dic=text/x-c +dir=application/x-director +dis=application/vnd.mobius.dis +dist=application/octet-stream +distz=application/octet-stream +djv=image/vnd.djvu +djvu=image/vnd.djvu +dll=application/x-msdownload +dmg=application/x-apple-diskimage +dmp=application/vnd.tcpdump.pcap +dms=application/octet-stream +dna=application/vnd.dna +doc=application/msword +docm=application/vnd.ms-word.document.macroenabled.12 +docx=application/vnd.openxmlformats-officedocument.wordprocessingml.document +dot=application/msword +dotm=application/vnd.ms-word.template.macroenabled.12 +dotx=application/vnd.openxmlformats-officedocument.wordprocessingml.template +dp=application/vnd.osgi.dp +dpg=application/vnd.dpgraph +dra=audio/vnd.dra +dsc=text/prs.lines.tag +dssc=application/dssc+der +dtb=application/x-dtbook+xml +dtd=application/xml-dtd +dts=audio/vnd.dts +dtshd=audio/vnd.dts.hd +dump=application/octet-stream +dv=video/x-dv +dvb=video/vnd.dvb.file +dvi=application/x-dvi +dwf=model/vnd.dwf +dwg=image/vnd.dwg +dxf=image/vnd.dxf +dxp=application/vnd.spotfire.dxp +dxr=application/x-director +ecelp4800=audio/vnd.nuera.ecelp4800 +ecelp7470=audio/vnd.nuera.ecelp7470 +ecelp9600=audio/vnd.nuera.ecelp9600 +ecma=application/ecmascript +edm=application/vnd.novadigm.edm +edx=application/vnd.novadigm.edx +efif=application/vnd.picsel +ei6=application/vnd.pg.osasli +elc=application/octet-stream +emf=application/x-msmetafile +eml=message/rfc822 +emma=application/emma+xml +emz=application/x-msmetafile +eol=audio/vnd.digital-winds +eot=application/vnd.ms-fontobject +eps=application/postscript +epub=application/epub+zip +es3=application/vnd.eszigno3+xml +esa=application/vnd.osgi.subsystem +esf=application/vnd.epson.esf +et3=application/vnd.eszigno3+xml +etx=text/x-setext +eva=application/x-eva +evy=application/x-envoy +exe=application/octet-stream +exi=application/exi +ext=application/vnd.novadigm.ext +ez=application/andrew-inset +ez2=application/vnd.ezpix-album +ez3=application/vnd.ezpix-package +f=text/x-fortran +f4v=video/x-f4v +f77=text/x-fortran +f90=text/x-fortran +fbs=image/vnd.fastbidsheet +fcdt=application/vnd.adobe.formscentral.fcdt +fcs=application/vnd.isac.fcs +fdf=application/vnd.fdf +fe_launch=application/vnd.denovo.fcselayout-link +fg5=application/vnd.fujitsu.oasysgp +fgd=application/x-director +fh=image/x-freehand +fh4=image/x-freehand +fh5=image/x-freehand +fh7=image/x-freehand +fhc=image/x-freehand +fig=application/x-xfig +flac=audio/flac +fli=video/x-fli +flo=application/vnd.micrografx.flo +flv=video/x-flv +flw=application/vnd.kde.kivio +flx=text/vnd.fmi.flexstor +fly=text/vnd.fly +fm=application/vnd.framemaker +fnc=application/vnd.frogans.fnc +for=text/x-fortran +fpx=image/vnd.fpx +frame=application/vnd.framemaker +fsc=application/vnd.fsc.weblaunch +fst=image/vnd.fst +ftc=application/vnd.fluxtime.clip +fti=application/vnd.anser-web-funds-transfer-initiation +fvt=video/vnd.fvt +fxp=application/vnd.adobe.fxp +fxpl=application/vnd.adobe.fxp +fzs=application/vnd.fuzzysheet +g2w=application/vnd.geoplan +g3=image/g3fax +g3w=application/vnd.geospace +gac=application/vnd.groove-account +gam=application/x-tads +gbr=application/rpki-ghostbusters +gca=application/x-gca-compressed +gdl=model/vnd.gdl +geo=application/vnd.dynageo +gex=application/vnd.geometry-explorer +ggb=application/vnd.geogebra.file +ggt=application/vnd.geogebra.tool +ghf=application/vnd.groove-help +gif=image/gif +gim=application/vnd.groove-identity-message +gml=application/gml+xml +gmx=application/vnd.gmx +gnumeric=application/x-gnumeric +gph=application/vnd.flographit +gpx=application/gpx+xml +gqf=application/vnd.grafeq +gqs=application/vnd.grafeq +gram=application/srgs +gramps=application/x-gramps-xml +gre=application/vnd.geometry-explorer +grv=application/vnd.groove-injector +grxml=application/srgs+xml +gsf=application/x-font-ghostscript +gtar=application/x-gtar +gtm=application/vnd.groove-tool-message +gtw=model/vnd.gtw +gv=text/vnd.graphviz +gxf=application/gxf +gxt=application/vnd.geonext +gz=application/x-gzip +h=text/x-c +h261=video/h261 +h263=video/h263 +h264=video/h264 +hal=application/vnd.hal+xml +hbci=application/vnd.hbci +hdf=application/x-hdf +hh=text/x-c +hlp=application/winhlp +hpgl=application/vnd.hp-hpgl +hpid=application/vnd.hp-hpid +hps=application/vnd.hp-hps +hqx=application/mac-binhex40 +htc=text/x-component +htke=application/vnd.kenameaapp +htm=text/html +html=text/html +hvd=application/vnd.yamaha.hv-dic +hvp=application/vnd.yamaha.hv-voice +hvs=application/vnd.yamaha.hv-script +i2g=application/vnd.intergeo +icc=application/vnd.iccprofile +ice=x-conference/x-cooltalk +icm=application/vnd.iccprofile +ico=image/x-icon +ics=text/calendar +ief=image/ief +ifb=text/calendar +ifm=application/vnd.shana.informed.formdata +iges=model/iges +igl=application/vnd.igloader +igm=application/vnd.insors.igm +igs=model/iges +igx=application/vnd.micrografx.igx +iif=application/vnd.shana.informed.interchange +imp=application/vnd.accpac.simply.imp +ims=application/vnd.ms-ims +in=text/plain +ink=application/inkml+xml +inkml=application/inkml+xml +install=application/x-install-instructions +iota=application/vnd.astraea-software.iota +ipfix=application/ipfix +ipk=application/vnd.shana.informed.package +irm=application/vnd.ibm.rights-management +irp=application/vnd.irepository.package+xml +iso=application/x-iso9660-image +itp=application/vnd.shana.informed.formtemplate +ivp=application/vnd.immervision-ivp +ivu=application/vnd.immervision-ivu +jad=text/vnd.sun.j2me.app-descriptor +jam=application/vnd.jam +jar=application/java-archive +java=text/x-java-source +jisp=application/vnd.jisp +jlt=application/vnd.hp-jlyt +jnlp=application/x-java-jnlp-file +joda=application/vnd.joost.joda-archive +jpe=image/jpeg +jpeg=image/jpeg +jpg=image/jpeg +jpgm=video/jpm +jpgv=video/jpeg +jpm=video/jpm +js=application/javascript +jsf=text/plain +json=application/json +jsonml=application/jsonml+json +jspf=text/plain +kar=audio/midi +karbon=application/vnd.kde.karbon +kfo=application/vnd.kde.kformula +kia=application/vnd.kidspiration +kml=application/vnd.google-earth.kml+xml +kmz=application/vnd.google-earth.kmz +kne=application/vnd.kinar +knp=application/vnd.kinar +kon=application/vnd.kde.kontour +kpr=application/vnd.kde.kpresenter +kpt=application/vnd.kde.kpresenter +kpxx=application/vnd.ds-keypoint +ksp=application/vnd.kde.kspread +ktr=application/vnd.kahootz +ktx=image/ktx +ktz=application/vnd.kahootz +kwd=application/vnd.kde.kword +kwt=application/vnd.kde.kword +lasxml=application/vnd.las.las+xml +latex=application/x-latex +lbd=application/vnd.llamagraphics.life-balance.desktop +lbe=application/vnd.llamagraphics.life-balance.exchange+xml +les=application/vnd.hhe.lesson-player +lha=application/x-lzh-compressed +link66=application/vnd.route66.link66+xml +list=text/plain +list3820=application/vnd.ibm.modcap +listafp=application/vnd.ibm.modcap +lnk=application/x-ms-shortcut +log=text/plain +lostxml=application/lost+xml +lrf=application/octet-stream +lrm=application/vnd.ms-lrm +ltf=application/vnd.frogans.ltf +lvp=audio/vnd.lucent.voice +lwp=application/vnd.lotus-wordpro +lzh=application/x-lzh-compressed +m13=application/x-msmediaview +m14=application/x-msmediaview +m1v=video/mpeg +m21=application/mp21 +m2a=audio/mpeg +m2v=video/mpeg +m3a=audio/mpeg +m3u=audio/x-mpegurl +m3u8=application/vnd.apple.mpegurl +m4a=audio/mp4 +m4b=audio/mp4 +m4r=audio/mp4 +m4u=video/vnd.mpegurl +m4v=video/mp4 +ma=application/mathematica +mac=image/x-macpaint +mads=application/mads+xml +mag=application/vnd.ecowin.chart +maker=application/vnd.framemaker +man=text/troff +mar=application/octet-stream +mathml=application/mathml+xml +mb=application/mathematica +mbk=application/vnd.mobius.mbk +mbox=application/mbox +mc1=application/vnd.medcalcdata +mcd=application/vnd.mcd +mcurl=text/vnd.curl.mcurl +mdb=application/x-msaccess +mdi=image/vnd.ms-modi +me=text/troff +mesh=model/mesh +meta4=application/metalink4+xml +metalink=application/metalink+xml +mets=application/mets+xml +mfm=application/vnd.mfmp +mft=application/rpki-manifest +mgp=application/vnd.osgeo.mapguide.package +mgz=application/vnd.proteus.magazine +mid=audio/midi +midi=audio/midi +mie=application/x-mie +mif=application/x-mif +mime=message/rfc822 +mj2=video/mj2 +mjp2=video/mj2 +mk3d=video/x-matroska +mka=audio/x-matroska +mks=video/x-matroska +mkv=video/x-matroska +mlp=application/vnd.dolby.mlp +mmd=application/vnd.chipnuts.karaoke-mmd +mmf=application/vnd.smaf +mmr=image/vnd.fujixerox.edmics-mmr +mng=video/x-mng +mny=application/x-msmoney +mobi=application/x-mobipocket-ebook +mods=application/mods+xml +mov=video/quicktime +movie=video/x-sgi-movie +mp1=audio/mpeg +mp2=audio/mpeg +mp21=application/mp21 +mp2a=audio/mpeg +mp3=audio/mpeg +mp4=video/mp4 +mp4a=audio/mp4 +mp4s=application/mp4 +mp4v=video/mp4 +mpa=audio/mpeg +mpc=application/vnd.mophun.certificate +mpe=video/mpeg +mpeg=video/mpeg +mpega=audio/x-mpeg +mpg=video/mpeg +mpg4=video/mp4 +mpga=audio/mpeg +mpkg=application/vnd.apple.installer+xml +mpm=application/vnd.blueice.multipass +mpn=application/vnd.mophun.application +mpp=application/vnd.ms-project +mpt=application/vnd.ms-project +mpv2=video/mpeg2 +mpy=application/vnd.ibm.minipay +mqy=application/vnd.mobius.mqy +mrc=application/marc +mrcx=application/marcxml+xml +ms=text/troff +mscml=application/mediaservercontrol+xml +mseed=application/vnd.fdsn.mseed +mseq=application/vnd.mseq +msf=application/vnd.epson.msf +msh=model/mesh +msi=application/x-msdownload +msl=application/vnd.mobius.msl +msty=application/vnd.muvee.style +mts=model/vnd.mts +mus=application/vnd.musician +musicxml=application/vnd.recordare.musicxml+xml +mvb=application/x-msmediaview +mwf=application/vnd.mfer +mxf=application/mxf +mxl=application/vnd.recordare.musicxml +mxml=application/xv+xml +mxs=application/vnd.triscape.mxs +mxu=video/vnd.mpegurl +n-gage=application/vnd.nokia.n-gage.symbian.install +n3=text/n3 +nb=application/mathematica +nbp=application/vnd.wolfram.player +nc=application/x-netcdf +ncx=application/x-dtbncx+xml +nfo=text/x-nfo +ngdat=application/vnd.nokia.n-gage.data +nitf=application/vnd.nitf +nlu=application/vnd.neurolanguage.nlu +nml=application/vnd.enliven +nnd=application/vnd.noblenet-directory +nns=application/vnd.noblenet-sealer +nnw=application/vnd.noblenet-web +npx=image/vnd.net-fpx +nsc=application/x-conference +nsf=application/vnd.lotus-notes +ntf=application/vnd.nitf +nzb=application/x-nzb +oa2=application/vnd.fujitsu.oasys2 +oa3=application/vnd.fujitsu.oasys3 +oas=application/vnd.fujitsu.oasys +obd=application/x-msbinder +obj=application/x-tgif +oda=application/oda +odb=application/vnd.oasis.opendocument.database +odc=application/vnd.oasis.opendocument.chart +odf=application/vnd.oasis.opendocument.formula +odft=application/vnd.oasis.opendocument.formula-template +odg=application/vnd.oasis.opendocument.graphics +odi=application/vnd.oasis.opendocument.image +odm=application/vnd.oasis.opendocument.text-master +odp=application/vnd.oasis.opendocument.presentation +ods=application/vnd.oasis.opendocument.spreadsheet +odt=application/vnd.oasis.opendocument.text +oga=audio/ogg +ogg=audio/ogg +ogv=video/ogg +ogx=application/ogg +omdoc=application/omdoc+xml +onepkg=application/onenote +onetmp=application/onenote +onetoc=application/onenote +onetoc2=application/onenote +opf=application/oebps-package+xml +opml=text/x-opml +oprc=application/vnd.palm +org=application/vnd.lotus-organizer +osf=application/vnd.yamaha.openscoreformat +osfpvg=application/vnd.yamaha.openscoreformat.osfpvg+xml +otc=application/vnd.oasis.opendocument.chart-template +otf=font/otf +otg=application/vnd.oasis.opendocument.graphics-template +oth=application/vnd.oasis.opendocument.text-web +oti=application/vnd.oasis.opendocument.image-template +otp=application/vnd.oasis.opendocument.presentation-template +ots=application/vnd.oasis.opendocument.spreadsheet-template +ott=application/vnd.oasis.opendocument.text-template +oxps=application/oxps +oxt=application/vnd.openofficeorg.extension +p=text/x-pascal +p10=application/pkcs10 +p12=application/x-pkcs12 +p7b=application/x-pkcs7-certificates +p7c=application/pkcs7-mime +p7m=application/pkcs7-mime +p7r=application/x-pkcs7-certreqresp +p7s=application/pkcs7-signature +p8=application/pkcs8 +pas=text/x-pascal +paw=application/vnd.pawaafile +pbd=application/vnd.powerbuilder6 +pbm=image/x-portable-bitmap +pcap=application/vnd.tcpdump.pcap +pcf=application/x-font-pcf +pcl=application/vnd.hp-pcl +pclxl=application/vnd.hp-pclxl +pct=image/pict +pcurl=application/vnd.curl.pcurl +pcx=image/x-pcx +pdb=application/vnd.palm +pdf=application/pdf +pfa=application/x-font-type1 +pfb=application/x-font-type1 +pfm=application/x-font-type1 +pfr=application/font-tdpfr +pfx=application/x-pkcs12 +pgm=image/x-portable-graymap +pgn=application/x-chess-pgn +pgp=application/pgp-encrypted +pic=image/pict +pict=image/pict +pkg=application/octet-stream +pki=application/pkixcmp +pkipath=application/pkix-pkipath +plb=application/vnd.3gpp.pic-bw-large +plc=application/vnd.mobius.plc +plf=application/vnd.pocketlearn +pls=audio/x-scpls +pml=application/vnd.ctc-posml +png=image/png +pnm=image/x-portable-anymap +pnt=image/x-macpaint +portpkg=application/vnd.macports.portpkg +pot=application/vnd.ms-powerpoint +potm=application/vnd.ms-powerpoint.template.macroenabled.12 +potx=application/vnd.openxmlformats-officedocument.presentationml.template +ppam=application/vnd.ms-powerpoint.addin.macroenabled.12 +ppd=application/vnd.cups-ppd +ppm=image/x-portable-pixmap +pps=application/vnd.ms-powerpoint +ppsm=application/vnd.ms-powerpoint.slideshow.macroenabled.12 +ppsx=application/vnd.openxmlformats-officedocument.presentationml.slideshow +ppt=application/vnd.ms-powerpoint +pptm=application/vnd.ms-powerpoint.presentation.macroenabled.12 +pptx=application/vnd.openxmlformats-officedocument.presentationml.presentation +pqa=application/vnd.palm +prc=application/x-mobipocket-ebook +pre=application/vnd.lotus-freelance +prf=application/pics-rules +ps=application/postscript +psb=application/vnd.3gpp.pic-bw-small +psd=image/vnd.adobe.photoshop +psf=application/x-font-linux-psf +pskcxml=application/pskc+xml +ptid=application/vnd.pvi.ptid1 +pub=application/x-mspublisher +pvb=application/vnd.3gpp.pic-bw-var +pwn=application/vnd.3m.post-it-notes +pya=audio/vnd.ms-playready.media.pya +pyv=video/vnd.ms-playready.media.pyv +qam=application/vnd.epson.quickanime +qbo=application/vnd.intu.qbo +qfx=application/vnd.intu.qfx +qps=application/vnd.publishare-delta-tree +qt=video/quicktime +qti=image/x-quicktime +qtif=image/x-quicktime +qwd=application/vnd.quark.quarkxpress +qwt=application/vnd.quark.quarkxpress +qxb=application/vnd.quark.quarkxpress +qxd=application/vnd.quark.quarkxpress +qxl=application/vnd.quark.quarkxpress +qxt=application/vnd.quark.quarkxpress +ra=audio/x-pn-realaudio +ram=audio/x-pn-realaudio +rar=application/x-rar-compressed +ras=image/x-cmu-raster +rcprofile=application/vnd.ipunplugged.rcprofile +rdf=application/rdf+xml +rdz=application/vnd.data-vision.rdz +rep=application/vnd.businessobjects +res=application/x-dtbresource+xml +rgb=image/x-rgb +rif=application/reginfo+xml +rip=audio/vnd.rip +ris=application/x-research-info-systems +rl=application/resource-lists+xml +rlc=image/vnd.fujixerox.edmics-rlc +rld=application/resource-lists-diff+xml +rm=application/vnd.rn-realmedia +rmi=audio/midi +rmp=audio/x-pn-realaudio-plugin +rms=application/vnd.jcp.javame.midlet-rms +rmvb=application/vnd.rn-realmedia-vbr +rnc=application/relax-ng-compact-syntax +roa=application/rpki-roa +roff=text/troff +rp9=application/vnd.cloanto.rp9 +rpss=application/vnd.nokia.radio-presets +rpst=application/vnd.nokia.radio-preset +rq=application/sparql-query +rs=application/rls-services+xml +rsd=application/rsd+xml +rss=application/rss+xml +rtf=application/rtf +rtx=text/richtext +s=text/x-asm +s3m=audio/s3m +saf=application/vnd.yamaha.smaf-audio +sbml=application/sbml+xml +sc=application/vnd.ibm.secure-container +scd=application/x-msschedule +scm=application/vnd.lotus-screencam +scq=application/scvp-cv-request +scs=application/scvp-cv-response +scurl=text/vnd.curl.scurl +sda=application/vnd.stardivision.draw +sdc=application/vnd.stardivision.calc +sdd=application/vnd.stardivision.impress +sdkd=application/vnd.solent.sdkm+xml +sdkm=application/vnd.solent.sdkm+xml +sdp=application/sdp +sdw=application/vnd.stardivision.writer +see=application/vnd.seemail +seed=application/vnd.fdsn.seed +sema=application/vnd.sema +semd=application/vnd.semd +semf=application/vnd.semf +ser=application/java-serialized-object +setpay=application/set-payment-initiation +setreg=application/set-registration-initiation +sfd-hdstx=application/vnd.hydrostatix.sof-data +sfs=application/vnd.spotfire.sfs +sfv=text/x-sfv +sgi=image/sgi +sgl=application/vnd.stardivision.writer-global +sgm=text/sgml +sgml=text/sgml +sh=application/x-sh +shar=application/x-shar +shf=application/shf+xml +sid=image/x-mrsid-image +sig=application/pgp-signature +sil=audio/silk +silo=model/mesh +sis=application/vnd.symbian.install +sisx=application/vnd.symbian.install +sit=application/x-stuffit +sitx=application/x-stuffitx +skd=application/vnd.koan +skm=application/vnd.koan +skp=application/vnd.koan +skt=application/vnd.koan +sldm=application/vnd.ms-powerpoint.slide.macroenabled.12 +sldx=application/vnd.openxmlformats-officedocument.presentationml.slide +slt=application/vnd.epson.salt +sm=application/vnd.stepmania.stepchart +smf=application/vnd.stardivision.math +smi=application/smil+xml +smil=application/smil+xml +smv=video/x-smv +smzip=application/vnd.stepmania.package +snd=audio/basic +snf=application/x-font-snf +so=application/octet-stream +spc=application/x-pkcs7-certificates +spf=application/vnd.yamaha.smaf-phrase +spl=application/x-futuresplash +spot=text/vnd.in3d.spot +spp=application/scvp-vp-response +spq=application/scvp-vp-request +spx=audio/ogg +sql=application/x-sql +src=application/x-wais-source +srt=application/x-subrip +sru=application/sru+xml +srx=application/sparql-results+xml +ssdl=application/ssdl+xml +sse=application/vnd.kodak-descriptor +ssf=application/vnd.epson.ssf +ssml=application/ssml+xml +st=application/vnd.sailingtracker.track +stc=application/vnd.sun.xml.calc.template +std=application/vnd.sun.xml.draw.template +stf=application/vnd.wt.stf +sti=application/vnd.sun.xml.impress.template +stk=application/hyperstudio +stl=application/vnd.ms-pki.stl +str=application/vnd.pg.format +stw=application/vnd.sun.xml.writer.template +sub=text/vnd.dvb.subtitle +sus=application/vnd.sus-calendar +susp=application/vnd.sus-calendar +sv4cpio=application/x-sv4cpio +sv4crc=application/x-sv4crc +svc=application/vnd.dvb.service +svd=application/vnd.svd +svg=image/svg+xml +svgz=image/svg+xml +swa=application/x-director +swf=application/x-shockwave-flash +swi=application/vnd.aristanetworks.swi +sxc=application/vnd.sun.xml.calc +sxd=application/vnd.sun.xml.draw +sxg=application/vnd.sun.xml.writer.global +sxi=application/vnd.sun.xml.impress +sxm=application/vnd.sun.xml.math +sxw=application/vnd.sun.xml.writer +t=text/troff +t3=application/x-t3vm-image +taglet=application/vnd.mynfc +tao=application/vnd.tao.intent-module-archive +tar=application/x-tar +tcap=application/vnd.3gpp2.tcap +tcl=application/x-tcl +teacher=application/vnd.smart.teacher +tei=application/tei+xml +teicorpus=application/tei+xml +tex=application/x-tex +texi=application/x-texinfo +texinfo=application/x-texinfo +text=text/plain +tfi=application/thraud+xml +tfm=application/x-tex-tfm +tga=image/x-tga +thmx=application/vnd.ms-officetheme +tif=image/tiff +tiff=image/tiff +tmo=application/vnd.tmobile-livetv +torrent=application/x-bittorrent +tpl=application/vnd.groove-tool-template +tpt=application/vnd.trid.tpt +tr=text/troff +tra=application/vnd.trueapp +trm=application/x-msterminal +tsd=application/timestamped-data +tsv=text/tab-separated-values +ttc=font/collection +ttf=font/ttf +ttl=text/turtle +twd=application/vnd.simtech-mindmapper +twds=application/vnd.simtech-mindmapper +txd=application/vnd.genomatix.tuxedo +txf=application/vnd.mobius.txf +txt=text/plain +u32=application/x-authorware-bin +udeb=application/x-debian-package +ufd=application/vnd.ufdl +ufdl=application/vnd.ufdl +ulw=audio/basic +ulx=application/x-glulx +umj=application/vnd.umajin +unityweb=application/vnd.unity +uoml=application/vnd.uoml+xml +uri=text/uri-list +uris=text/uri-list +urls=text/uri-list +ustar=application/x-ustar +utz=application/vnd.uiq.theme +uu=text/x-uuencode +uva=audio/vnd.dece.audio +uvd=application/vnd.dece.data +uvf=application/vnd.dece.data +uvg=image/vnd.dece.graphic +uvh=video/vnd.dece.hd +uvi=image/vnd.dece.graphic +uvm=video/vnd.dece.mobile +uvp=video/vnd.dece.pd +uvs=video/vnd.dece.sd +uvt=application/vnd.dece.ttml+xml +uvu=video/vnd.uvvu.mp4 +uvv=video/vnd.dece.video +uvva=audio/vnd.dece.audio +uvvd=application/vnd.dece.data +uvvf=application/vnd.dece.data +uvvg=image/vnd.dece.graphic +uvvh=video/vnd.dece.hd +uvvi=image/vnd.dece.graphic +uvvm=video/vnd.dece.mobile +uvvp=video/vnd.dece.pd +uvvs=video/vnd.dece.sd +uvvt=application/vnd.dece.ttml+xml +uvvu=video/vnd.uvvu.mp4 +uvvv=video/vnd.dece.video +uvvx=application/vnd.dece.unspecified +uvvz=application/vnd.dece.zip +uvx=application/vnd.dece.unspecified +uvz=application/vnd.dece.zip +vcard=text/vcard +vcd=application/x-cdlink +vcf=text/x-vcard +vcg=application/vnd.groove-vcard +vcs=text/x-vcalendar +vcx=application/vnd.vcx +vis=application/vnd.visionary +viv=video/vnd.vivo +vob=video/x-ms-vob +vor=application/vnd.stardivision.writer +vox=application/x-authorware-bin +vrml=model/vrml +vsd=application/vnd.visio +vsf=application/vnd.vsf +vss=application/vnd.visio +vst=application/vnd.visio +vsw=application/vnd.visio +vtu=model/vnd.vtu +vxml=application/voicexml+xml +w3d=application/x-director +wad=application/x-doom +wasm=application/wasm +wav=audio/x-wav +wax=audio/x-ms-wax +wbmp=image/vnd.wap.wbmp +wbs=application/vnd.criticaltools.wbs+xml +wbxml=application/vnd.wap.wbxml +wcm=application/vnd.ms-works +wdb=application/vnd.ms-works +wdp=image/vnd.ms-photo +weba=audio/webm +webm=video/webm +webp=image/webp +wg=application/vnd.pmi.widget +wgt=application/widget +wks=application/vnd.ms-works +wm=video/x-ms-wm +wma=audio/x-ms-wma +wmd=application/x-ms-wmd +wmf=application/x-msmetafile +wml=text/vnd.wap.wml +wmlc=application/vnd.wap.wmlc +wmls=text/vnd.wap.wmlscript +wmlsc=application/vnd.wap.wmlscriptc +wmv=video/x-ms-wmv +wmx=video/x-ms-wmx +wmz=application/x-msmetafile +woff=font/woff +woff2=font/woff2 +wpd=application/vnd.wordperfect +wpl=application/vnd.ms-wpl +wps=application/vnd.ms-works +wqd=application/vnd.wqd +wri=application/x-mswrite +wrl=model/vrml +wsdl=application/wsdl+xml +wspolicy=application/wspolicy+xml +wtb=application/vnd.webturbo +wvx=video/x-ms-wvx +x32=application/x-authorware-bin +x3d=model/x3d+xml +x3db=model/x3d+binary +x3dbz=model/x3d+binary +x3dv=model/x3d+vrml +x3dvz=model/x3d+vrml +x3dz=model/x3d+xml +xaml=application/xaml+xml +xap=application/x-silverlight-app +xar=application/vnd.xara +xbap=application/x-ms-xbap +xbd=application/vnd.fujixerox.docuworks.binder +xbm=image/x-xbitmap +xdf=application/xcap-diff+xml +xdm=application/vnd.syncml.dm+xml +xdp=application/vnd.adobe.xdp+xml +xdssc=application/dssc+xml +xdw=application/vnd.fujixerox.docuworks +xenc=application/xenc+xml +xer=application/patch-ops-error+xml +xfdf=application/vnd.adobe.xfdf +xfdl=application/vnd.xfdl +xht=application/xhtml+xml +xhtml=application/xhtml+xml +xhvml=application/xv+xml +xif=image/vnd.xiff +xla=application/vnd.ms-excel +xlam=application/vnd.ms-excel.addin.macroenabled.12 +xlc=application/vnd.ms-excel +xlf=application/x-xliff+xml +xlm=application/vnd.ms-excel +xls=application/vnd.ms-excel +xlsb=application/vnd.ms-excel.sheet.binary.macroenabled.12 +xlsm=application/vnd.ms-excel.sheet.macroenabled.12 +xlsx=application/vnd.openxmlformats-officedocument.spreadsheetml.sheet +xlt=application/vnd.ms-excel +xltm=application/vnd.ms-excel.template.macroenabled.12 +xltx=application/vnd.openxmlformats-officedocument.spreadsheetml.template +xlw=application/vnd.ms-excel +xm=audio/xm +xml=application/xml +xo=application/vnd.olpc-sugar +xop=application/xop+xml +xpi=application/x-xpinstall +xpl=application/xproc+xml +xpm=image/x-xpixmap +xpr=application/vnd.is-xpr +xps=application/vnd.ms-xpsdocument +xpw=application/vnd.intercon.formnet +xpx=application/vnd.intercon.formnet +xsl=application/xml +xslt=application/xslt+xml +xsm=application/vnd.syncml+xml +xspf=application/xspf+xml +xul=application/vnd.mozilla.xul+xml +xvm=application/xv+xml +xvml=application/xv+xml +xwd=image/x-xwindowdump +xyz=chemical/x-xyz +xz=application/x-xz +yang=application/yang +yin=application/yin+xml +z=application/x-compress +z1=application/x-zmachine +z2=application/x-zmachine +z3=application/x-zmachine +z4=application/x-zmachine +z5=application/x-zmachine +z6=application/x-zmachine +z7=application/x-zmachine +z8=application/x-zmachine +zaz=application/vnd.zzazz.deck+xml +zip=application/zip +zir=application/vnd.zul +zirz=application/vnd.zul +zmm=application/vnd.handheld-entertainment+xml diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java index 832663f6e84..5e3a872544f 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java @@ -45,6 +45,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; +import java.util.Properties; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Callable; @@ -77,6 +78,7 @@ import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; +import org.apache.catalina.startup.Tomcat; import org.apache.catalina.webresources.TomcatURLStreamHandlerFactory; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; @@ -134,6 +136,7 @@ import org.springframework.boot.web.servlet.server.Session.SessionTrackingMode; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; +import org.springframework.core.io.support.PropertiesLoaderUtils; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.client.ClientHttpRequest; @@ -958,6 +961,20 @@ public abstract class AbstractServletWebServerFactoryTests { assertThat(configuredMimeMappings.size()).isEqualTo(expectedMimeMappings.size()); } + @Test + void mimeMappingsContainsDefaultsOfTomcat() throws IOException { + AbstractServletWebServerFactory factory = getFactory(); + this.webServer = factory.getWebServer(); + Map configuredMimeMappings = getActualMimeMappings(); + // override defaults, see org.apache.catalina.startup.MimeTypeMappings.properties + Properties tomcatDefaultMimeMappings = PropertiesLoaderUtils + .loadProperties(new ClassPathResource("MimeTypeMappings.properties", Tomcat.class)); + for (String extension : tomcatDefaultMimeMappings.stringPropertyNames()) { + assertThat(configuredMimeMappings).containsEntry(extension, + tomcatDefaultMimeMappings.getProperty(extension)); + } + } + @Test void rootServletContextResource() { AbstractServletWebServerFactory factory = getFactory(); From 86f38e15f00910328df5f8b751c2d48b5532e57a Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Mon, 22 Aug 2022 20:00:06 -0700 Subject: [PATCH 2/2] Polish 'Align MimeMappings with Tomcat's defaults' Refine `MimeMappings` so that common default mappings are included by default and the complete set is only loaded when needed. The `TomcatServletWebServerFactory` has been updated so that if `TomcatEmbeddedContext` is in use the mime mapping are used directly rather than being copied to another Map. The `AbstractServletWebServerFactory` class has also been changed to use a lazy copy of the mappings. This should mean that the complete set of properties is only loaded if the user mutates the mappings. See gh-32101 --- .../tomcat/TomcatEmbeddedContext.java | 27 ++ .../tomcat/TomcatServletWebServerFactory.java | 14 +- .../boot/web/server/MimeMappings.java | 288 ++++++++++++++---- .../AbstractServletWebServerFactory.java | 3 +- .../resources/META-INF/spring/aot.factories | 5 +- .../boot/web/server/MimeMappingsTests.java | 73 +++++ 6 files changed, 351 insertions(+), 59 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatEmbeddedContext.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatEmbeddedContext.java index 633e6df3d92..48f37a1bb93 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatEmbeddedContext.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatEmbeddedContext.java @@ -17,6 +17,7 @@ package org.springframework.boot.web.embedded.tomcat; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.TreeMap; @@ -30,6 +31,7 @@ import org.apache.catalina.core.StandardContext; import org.apache.catalina.core.StandardWrapper; import org.apache.catalina.session.ManagerBase; +import org.springframework.boot.web.server.MimeMappings; import org.springframework.boot.web.server.WebServerException; import org.springframework.util.ClassUtils; @@ -44,6 +46,8 @@ class TomcatEmbeddedContext extends StandardContext { private TomcatStarter starter; + private MimeMappings mimeMappings; + @Override public boolean loadOnStartup(Container[] children) { // deferred until later (see deferredLoadOnStartup) @@ -118,4 +122,27 @@ class TomcatEmbeddedContext extends StandardContext { return this.starter; } + void setMimeMappings(MimeMappings mimeMappings) { + this.mimeMappings = mimeMappings; + } + + @Override + public String[] findMimeMappings() { + List mappings = new ArrayList<>(); + mappings.addAll(Arrays.asList(super.findMimeMappings())); + if (this.mimeMappings != null) { + this.mimeMappings.forEach((mapping) -> mappings.add(mapping.getExtension())); + } + return mappings.toArray(String[]::new); + } + + @Override + public String findMimeMapping(String extension) { + String mimeMapping = super.findMimeMapping(extension); + if (mimeMapping != null) { + return mimeMapping; + } + return (this.mimeMappings != null) ? this.mimeMappings.get(extension) : null; + } + } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactory.java index 5d3086143c8..9420c7696d7 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactory.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactory.java @@ -389,9 +389,7 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto tomcatErrorPage.setExceptionType(errorPage.getExceptionName()); context.addErrorPage(tomcatErrorPage); } - for (MimeMappings.Mapping mapping : getMimeMappings()) { - context.addMimeMapping(mapping.getExtension(), mapping.getMimeType()); - } + setMimeMappings(context); configureSession(context); configureCookieProcessor(context); new DisableReferenceClearingContextCustomizer().customize(context); @@ -423,6 +421,16 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto } } + private void setMimeMappings(Context context) { + if (context instanceof TomcatEmbeddedContext embeddedContext) { + embeddedContext.setMimeMappings(getMimeMappings()); + return; + } + for (MimeMappings.Mapping mapping : getMimeMappings()) { + context.addMimeMapping(mapping.getExtension(), mapping.getMimeType()); + } + } + private void configureCookieProcessor(Context context) { SameSite sessionSameSite = getSession().getCookie().getSameSite(); List suppliers = new ArrayList<>(); diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/MimeMappings.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/MimeMappings.java index 3c92df87c0a..b731532830c 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/MimeMappings.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/MimeMappings.java @@ -21,9 +21,13 @@ import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashMap; +import java.util.Locale; import java.util.Map; -import java.util.Properties; +import java.util.Map.Entry; +import java.util.concurrent.atomic.AtomicBoolean; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.support.PropertiesLoaderUtils; import org.springframework.util.Assert; @@ -33,29 +37,15 @@ import org.springframework.util.Assert; * {@literal <mime-mapping>} element traditionally found in web.xml. * * @author Phillip Webb + * @author Guirong Hu * @since 2.0.0 */ -public final class MimeMappings implements Iterable { +public sealed class MimeMappings implements Iterable { /** * Default mime mapping commonly used. */ - public static final MimeMappings DEFAULT; - - static { - MimeMappings mappings = new MimeMappings(); - try { - Properties defaultMimeMappings = PropertiesLoaderUtils - .loadProperties(new ClassPathResource("mime-mappings.properties", MimeMappings.class)); - for (String extension : defaultMimeMappings.stringPropertyNames()) { - mappings.add(extension, defaultMimeMappings.getProperty(extension)); - } - } - catch (IOException ex) { - throw new IllegalArgumentException("Unable to load the default MIME types", ex); - } - DEFAULT = unmodifiableMappings(mappings); - } + public static final MimeMappings DEFAULT = new DefaultMimeMappings(); private final Map map; @@ -90,14 +80,44 @@ public final class MimeMappings implements Iterable { * @param mappings source mappings * @param mutable if the new object should be mutable. */ - private MimeMappings(MimeMappings mappings, boolean mutable) { + MimeMappings(MimeMappings mappings, boolean mutable) { Assert.notNull(mappings, "Mappings must not be null"); this.map = (mutable ? new LinkedHashMap<>(mappings.map) : Collections.unmodifiableMap(mappings.map)); } - @Override - public Iterator iterator() { - return getAll().iterator(); + /** + * Add a new mime mapping. + * @param extension the file extension (excluding '.') + * @param mimeType the mime type to map + * @return any previous mapping or {@code null} + */ + public String add(String extension, String mimeType) { + Assert.notNull(extension, "Extension must not be null"); + Assert.notNull(mimeType, "MimeType must not be null"); + Mapping previous = this.map.put(extension.toLowerCase(Locale.ENGLISH), new Mapping(extension, mimeType)); + return (previous != null) ? previous.getMimeType() : null; + } + + /** + * Remove an existing mapping. + * @param extension the file extension (excluding '.') + * @return the removed mime mapping or {@code null} if no item was removed + */ + public String remove(String extension) { + Assert.notNull(extension, "Extension must not be null"); + Mapping previous = this.map.remove(extension.toLowerCase(Locale.ENGLISH)); + return (previous != null) ? previous.getMimeType() : null; + } + + /** + * Get a mime mapping for the given extension. + * @param extension the file extension (excluding '.') + * @return a mime mapping or {@code null} + */ + public String get(String extension) { + Assert.notNull(extension, "Extension must not be null"); + Mapping mapping = this.map.get(extension.toLowerCase(Locale.ENGLISH)); + return (mapping != null) ? mapping.getMimeType() : null; } /** @@ -108,35 +128,9 @@ public final class MimeMappings implements Iterable { return this.map.values(); } - /** - * Add a new mime mapping. - * @param extension the file extension (excluding '.') - * @param mimeType the mime type to map - * @return any previous mapping or {@code null} - */ - public String add(String extension, String mimeType) { - Mapping previous = this.map.put(extension, new Mapping(extension, mimeType)); - return (previous != null) ? previous.getMimeType() : null; - } - - /** - * Get a mime mapping for the given extension. - * @param extension the file extension (excluding '.') - * @return a mime mapping or {@code null} - */ - public String get(String extension) { - Mapping mapping = this.map.get(extension); - return (mapping != null) ? mapping.getMimeType() : null; - } - - /** - * Remove an existing mapping. - * @param extension the file extension (excluding '.') - * @return the removed mime mapping or {@code null} if no item was removed - */ - public String remove(String extension) { - Mapping previous = this.map.remove(extension); - return (previous != null) ? previous.getMimeType() : null; + @Override + public final Iterator iterator() { + return getAll().iterator(); } @Override @@ -148,14 +142,18 @@ public final class MimeMappings implements Iterable { return true; } if (obj instanceof MimeMappings other) { - return this.map.equals(other.map); + return getMap().equals(other.map); } return false; } @Override public int hashCode() { - return this.map.hashCode(); + return getMap().hashCode(); + } + + Map getMap() { + return this.map; } /** @@ -165,9 +163,22 @@ public final class MimeMappings implements Iterable { * @return an unmodifiable view of the specified mappings. */ public static MimeMappings unmodifiableMappings(MimeMappings mappings) { + Assert.notNull(mappings, "Mappings must not be null"); return new MimeMappings(mappings, false); } + /** + * Crate a new lazy copy of the given mappings will only copy entries if the mappings + * are mutated. + * @param mappings the source mappings + * @return a new mappings instance + * @since 3.0.0 + */ + public static MimeMappings lazyCopy(MimeMappings mappings) { + Assert.notNull(mappings, "Mappings must not be null"); + return new LazyMimeMappingsCopy(mappings); + } + /** * A single mime mapping. */ @@ -218,4 +229,175 @@ public final class MimeMappings implements Iterable { } + /** + * {@link MimeMappings} implementation used for {@link MimeMappings#DEFAULT}. Provides + * in-memory access for common mappings and lazily loads the complete set when + * necessary. + */ + static final class DefaultMimeMappings extends MimeMappings { + + static final String MIME_MAPPINGS_PROPERTIES = "mime-mappings.properties"; + + private static final MimeMappings COMMON; + + static { + MimeMappings mappings = new MimeMappings(); + mappings.add("avi", "video/x-msvideo"); + mappings.add("bin", "application/octet-stream"); + mappings.add("body", "text/html"); + mappings.add("class", "application/java"); + mappings.add("css", "text/css"); + mappings.add("dtd", "application/xml-dtd"); + mappings.add("gif", "image/gif"); + mappings.add("gtar", "application/x-gtar"); + mappings.add("gz", "application/x-gzip"); + mappings.add("htm", "text/html"); + mappings.add("html", "text/html"); + mappings.add("jar", "application/java-archive"); + mappings.add("java", "text/x-java-source"); + mappings.add("jnlp", "application/x-java-jnlp-file"); + mappings.add("jpe", "image/jpeg"); + mappings.add("jpeg", "image/jpeg"); + mappings.add("jpg", "image/jpeg"); + mappings.add("js", "application/javascript"); + mappings.add("json", "application/json"); + mappings.add("otf", "application/x-font-opentype"); + mappings.add("pdf", "application/pdf"); + mappings.add("png", "image/png"); + mappings.add("ps", "application/postscript"); + mappings.add("tar", "application/x-tar"); + mappings.add("tif", "image/tiff"); + mappings.add("tiff", "image/tiff"); + mappings.add("ttf", "application/x-font-ttf"); + mappings.add("txt", "text/plain"); + mappings.add("xht", "application/xhtml+xml"); + mappings.add("xhtml", "application/xhtml+xml"); + mappings.add("xls", "application/vnd.ms-excel"); + mappings.add("xml", "application/xml"); + mappings.add("xsl", "application/xml"); + mappings.add("xslt", "application/xslt+xml"); + mappings.add("wasm", "application/wasm"); + mappings.add("zip", "application/zip"); + COMMON = unmodifiableMappings(mappings); + } + + private volatile Map loaded; + + DefaultMimeMappings() { + super(new MimeMappings(), false); + } + + @Override + public Collection getAll() { + return load().values(); + } + + @Override + public String get(String extension) { + Assert.notNull(extension, "Extension must not be null"); + extension = extension.toLowerCase(Locale.ENGLISH); + Map loaded = this.loaded; + if (loaded != null) { + return get(loaded, extension); + } + String commonMimeType = COMMON.get(extension); + if (commonMimeType != null) { + return commonMimeType; + } + loaded = load(); + return get(loaded, extension); + } + + private String get(Map mappings, String extension) { + Mapping mapping = mappings.get(extension); + return (mapping != null) ? mapping.getMimeType() : null; + } + + @Override + Map getMap() { + return load(); + } + + private Map load() { + Map loaded = this.loaded; + if (loaded != null) { + return loaded; + } + try { + loaded = new LinkedHashMap<>(); + for (Entry entry : PropertiesLoaderUtils + .loadProperties(new ClassPathResource(MIME_MAPPINGS_PROPERTIES, getClass())).entrySet()) { + loaded.put((String) entry.getKey(), + new Mapping((String) entry.getKey(), (String) entry.getValue())); + } + loaded = Collections.unmodifiableMap(loaded); + this.loaded = loaded; + return loaded; + } + catch (IOException ex) { + throw new IllegalArgumentException("Unable to load the default MIME types", ex); + } + } + + } + + /** + * {@link MimeMappings} implementation used to create a lazy copy only when the + * mappings are mutated. + */ + static final class LazyMimeMappingsCopy extends MimeMappings { + + private final MimeMappings source; + + private AtomicBoolean copied = new AtomicBoolean(); + + LazyMimeMappingsCopy(MimeMappings source) { + this.source = source; + } + + @Override + public String add(String extension, String mimeType) { + copyIfNecessary(); + return super.add(extension, mimeType); + } + + @Override + public String remove(String extension) { + copyIfNecessary(); + return super.remove(extension); + } + + private void copyIfNecessary() { + if (this.copied.compareAndSet(false, true)) { + this.source.forEach((mapping) -> add(mapping.getExtension(), mapping.getMimeType())); + } + } + + @Override + public String get(String extension) { + return !this.copied.get() ? this.source.get(extension) : super.get(extension); + } + + @Override + public Collection getAll() { + return !this.copied.get() ? this.source.getAll() : super.getAll(); + } + + @Override + Map getMap() { + return !this.copied.get() ? this.source.getMap() : super.getMap(); + } + + } + + static class MimeMappingsRuntimeHints implements RuntimeHintsRegistrar { + + @Override + public void registerHints(RuntimeHints hints, ClassLoader classLoader) { + hints.resources().registerPattern( + "org/springframework/boot/web/server/" + DefaultMimeMappings.MIME_MAPPINGS_PROPERTIES); + } + + } + } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactory.java index bc9e2d7b3e3..75d4b1f2fda 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactory.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactory.java @@ -69,7 +69,7 @@ public abstract class AbstractServletWebServerFactory extends AbstractConfigurab private boolean registerDefaultServlet = false; - private MimeMappings mimeMappings = new MimeMappings(MimeMappings.DEFAULT); + private MimeMappings mimeMappings = MimeMappings.lazyCopy(MimeMappings.DEFAULT); private List initializers = new ArrayList<>(); @@ -173,6 +173,7 @@ public abstract class AbstractServletWebServerFactory extends AbstractConfigurab @Override public void setMimeMappings(MimeMappings mimeMappings) { + Assert.notNull(mimeMappings, "MimeMappings must not be null"); this.mimeMappings = new MimeMappings(mimeMappings); } diff --git a/spring-boot-project/spring-boot/src/main/resources/META-INF/spring/aot.factories b/spring-boot-project/spring-boot/src/main/resources/META-INF/spring/aot.factories index 7f5bbaa03ef..557835873c7 100644 --- a/spring-boot-project/spring-boot/src/main/resources/META-INF/spring/aot.factories +++ b/spring-boot-project/spring-boot/src/main/resources/META-INF/spring/aot.factories @@ -1,11 +1,12 @@ org.springframework.aot.hint.RuntimeHintsRegistrar=\ +org.springframework.boot.SpringApplication.SpringApplicationRuntimeHints,\ +org.springframework.boot.WebApplicationType.WebApplicationTypeRuntimeHints,\ org.springframework.boot.context.config.ConfigDataLocationRuntimeHints,\ org.springframework.boot.env.PropertySourceRuntimeHints,\ org.springframework.boot.json.JacksonRuntimeHints,\ org.springframework.boot.logging.java.JavaLoggingSystemRuntimeHints,\ org.springframework.boot.logging.logback.LogbackRuntimeHints,\ -org.springframework.boot.SpringApplication.SpringApplicationRuntimeHints,\ -org.springframework.boot.WebApplicationType.WebApplicationTypeRuntimeHints +org.springframework.boot.web.server.MimeMappings.MimeMappingsRuntimeHints org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor=\ org.springframework.boot.context.properties.ConfigurationPropertiesBeanFactoryInitializationAotProcessor diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/MimeMappingsTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/MimeMappingsTests.java index b28a8e5dcc7..0d84f76e80a 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/MimeMappingsTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/server/MimeMappingsTests.java @@ -24,6 +24,13 @@ import java.util.regex.Pattern; import org.junit.jupiter.api.Test; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; +import org.springframework.boot.web.server.MimeMappings.DefaultMimeMappings; +import org.springframework.boot.web.server.MimeMappings.Mapping; +import org.springframework.boot.web.server.MimeMappings.MimeMappingsRuntimeHints; +import org.springframework.test.util.ReflectionTestUtils; + import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -31,6 +38,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; * Tests for {@link MimeMappings}. * * @author Phillip Webb + * @author Guirong Hu */ class MimeMappingsTests { @@ -143,4 +151,69 @@ class MimeMappingsTests { assertThat(MimeMappings.DEFAULT).allSatisfy((mapping) -> assertThat(mapping.getMimeType()).matches(pattern)); } + @Test + void getCommonTypeOnDefaultMimeMappingsDoesNotLoadMappings() { + DefaultMimeMappings mappings = new DefaultMimeMappings(); + assertThat(mappings.get("json")).isEqualTo("application/json"); + assertThat((Object) mappings).extracting("loaded").isNull(); + } + + @Test + void getExoticTypeOnDefaultMimeMappingsLoadsMappings() { + DefaultMimeMappings mappings = new DefaultMimeMappings(); + assertThat(mappings.get("123")).isEqualTo("application/vnd.lotus-1-2-3"); + assertThat((Object) mappings).extracting("loaded").isNotNull(); + } + + @Test + void iterateOnDefaultMimeMappingsLoadsMappings() { + DefaultMimeMappings mappings = new DefaultMimeMappings(); + assertThat(mappings).isNotEmpty(); + assertThat((Object) mappings).extracting("loaded").isNotNull(); + } + + @Test + void commonMappingsAreSubsetOfAllMappings() { + MimeMappings commonMappings = (MimeMappings) ReflectionTestUtils.getField(DefaultMimeMappings.class, "COMMON"); + for (Mapping commonMapping : commonMappings) { + assertThat(MimeMappings.DEFAULT.get(commonMapping.getExtension())).isEqualTo(commonMapping.getMimeType()); + } + } + + @Test + void lazyCopyWhenNotMutatedDelegates() { + DefaultMimeMappings mappings = new DefaultMimeMappings(); + MimeMappings lazyCopy = MimeMappings.lazyCopy(mappings); + assertThat(lazyCopy.get("json")).isEqualTo("application/json"); + assertThat((Object) mappings).extracting("loaded").isNull(); + } + + @Test + void lazyCopyWhenMutatedCreatesCopy() { + DefaultMimeMappings mappings = new DefaultMimeMappings(); + MimeMappings lazyCopy = MimeMappings.lazyCopy(mappings); + lazyCopy.add("json", "other/json"); + assertThat(lazyCopy.get("json")).isEqualTo("other/json"); + assertThat((Object) mappings).extracting("loaded").isNotNull(); + } + + @Test + void lazyCopyWhenMutatedCreatesCopyOnlyOnce() { + MimeMappings mappings = new MimeMappings(); + mappings.add("json", "one/json"); + MimeMappings lazyCopy = MimeMappings.lazyCopy(mappings); + assertThat(lazyCopy.get("json")).isEqualTo("one/json"); + mappings.add("json", "two/json"); + lazyCopy.add("json", "other/json"); + assertThat(lazyCopy.get("json")).isEqualTo("other/json"); + } + + @Test + void shouldRegisterHints() { + RuntimeHints runtimeHints = new RuntimeHints(); + new MimeMappingsRuntimeHints().registerHints(runtimeHints, getClass().getClassLoader()); + assertThat(RuntimeHintsPredicates.resource() + .forResource("org/springframework/boot/web/server/mime-mappings.properties")).accepts(runtimeHints); + } + }