diff --git a/akka-http-tests/lib/i have späces.jar b/akka-http-tests/lib/i have späces.jar new file mode 100644 index 0000000000..3d009cbab1 Binary files /dev/null and b/akka-http-tests/lib/i have späces.jar differ diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/FileAndResourceDirectivesSpec.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/FileAndResourceDirectivesSpec.scala index 7fb637d93e..86c7dfb32a 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/FileAndResourceDirectivesSpec.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/FileAndResourceDirectivesSpec.scala @@ -37,7 +37,7 @@ class FileAndResourceDirectivesSpec extends RoutingSpec with Inspectors with Ins Get() ~> getFromFile(Properties.javaHome) ~> check { handled shouldEqual (false) } } "return the file content with the MediaType matching the file extension" in { - val file = File.createTempFile("akkaHttpTest", ".PDF") + val file = File.createTempFile("akka Http Test", ".PDF") try { writeAllText("This is PDF", file) Get() ~> getFromFile(file.getPath) ~> check { @@ -104,12 +104,19 @@ class FileAndResourceDirectivesSpec extends RoutingSpec with Inspectors with Ins "reject requests to directory resources with trailing slash" in { Get() ~> getFromResource("someDir/") ~> check { handled shouldEqual (false) } } - "reject requests to directory resources from an Archive " in { + "reject requests to directory resources from an archive " in { Get() ~> getFromResource("com/typesafe/config") ~> check { handled shouldEqual (false) } } - "reject requests to directory resources from an Archive with trailing slash" in { + "reject requests to directory resources from an archive with trailing slash" in { Get() ~> getFromResource("com/typesafe/config/") ~> check { handled shouldEqual (false) } } + "return the resource from an archive with spaces and umlauts" in { + // contained within lib/jar with späces.jar + Get() ~> getFromResource("test-resource.txt") ~> check { + mediaType shouldEqual `text/plain` + responseAs[String] shouldEqual "I have spaces, too!" + } + } "return the resource content with the MediaType matching the file extension" in { val route = getFromResource("sample.html") @@ -129,7 +136,7 @@ class FileAndResourceDirectivesSpec extends RoutingSpec with Inspectors with Ins runCheck() runCheck() // additional test to check that no internal state is kept } - "return the resource content from an Archive" in { + "return the resource content from an archive" in { Get() ~> getFromResource("com/typesafe/config/Config.class") ~> check { mediaType shouldEqual `application/octet-stream` responseEntity.toStrict(1.second).awaitResult(1.second).data.asByteBuffer.getInt shouldEqual 0xCAFEBABE @@ -160,7 +167,7 @@ class FileAndResourceDirectivesSpec extends RoutingSpec with Inspectors with Ins "return the resource content with the MediaType matching the file extension - example 3" in { Get("subDirectory/empty.pdf") ~> getFromResourceDirectory("") ~> verify } - "return the resource content from an Archive" in { + "return the resource content from an archive" in { Get("Config.class") ~> getFromResourceDirectory("com/typesafe/config") ~> check { mediaType shouldEqual `application/octet-stream` responseEntity.toStrict(1.second).awaitResult(1.second).data.asByteBuffer.getInt shouldEqual 0xCAFEBABE @@ -178,10 +185,10 @@ class FileAndResourceDirectivesSpec extends RoutingSpec with Inspectors with Ins "reject requests to sub directory resources with trailing slash" in { Get("sub/") ~> getFromResourceDirectory("someDir") ~> check { handled shouldEqual (false) } } - "reject requests to directory resources from an Archive" in { + "reject requests to directory resources from an archive" in { Get() ~> getFromResourceDirectory("com/typesafe/config") ~> check { handled shouldEqual (false) } } - "reject requests to directory resources from an Archive with trailing slash" in { + "reject requests to directory resources from an archive with trailing slash" in { Get() ~> getFromResourceDirectory("com/typesafe/config/") ~> check { handled shouldEqual (false) } } } diff --git a/akka-http/src/main/scala/akka/http/scaladsl/server/directives/FileAndResourceDirectives.scala b/akka-http/src/main/scala/akka/http/scaladsl/server/directives/FileAndResourceDirectives.scala index 0420f9050d..5e3b23f36b 100644 --- a/akka-http/src/main/scala/akka/http/scaladsl/server/directives/FileAndResourceDirectives.scala +++ b/akka-http/src/main/scala/akka/http/scaladsl/server/directives/FileAndResourceDirectives.scala @@ -207,12 +207,11 @@ object FileAndResourceDirectives extends FileAndResourceDirectives { if (file.isDirectory) None else Some(ResourceFile(url, file.length(), file.lastModified())) case "jar" ⇒ - val jarFile = url.getFile - val startIndex = if (jarFile.startsWith("file:")) 5 else 0 - val bangIndex = jarFile.indexOf("!") - val jarFilePath = jarFile.substring(startIndex, bangIndex) - val resourcePath = jarFile.substring(bangIndex + 2) - val jar = new java.util.zip.ZipFile(jarFilePath) + val path = new URI(url.getPath).getPath // remove "file:" prefix and normalize whitespace + val bangIndex = path.indexOf('!') + val filePath = path.substring(0, bangIndex) + val resourcePath = path.substring(bangIndex + 2) + val jar = new java.util.zip.ZipFile(filePath) try { val entry = jar.getEntry(resourcePath) Option(jar.getInputStream(entry)) map { is ⇒