From 60d4dce0193fb9d592f2fe065908bfc88da89dff Mon Sep 17 00:00:00 2001 From: "Juan J. Martinez" Date: Sun, 16 Jan 2022 00:22:24 +0000 Subject: Refactor Gemini protocol --- server/test/src/ServerSpec.scala | 209 --------------------- server/test/src/TestData.scala | 108 +++++++++++ server/test/src/URIUtilsSpec.scala | 26 +++ server/test/src/handlers/ProtocolHandlerSpec.scala | 100 ++++++++++ 4 files changed, 234 insertions(+), 209 deletions(-) create mode 100644 server/test/src/TestData.scala create mode 100644 server/test/src/URIUtilsSpec.scala create mode 100644 server/test/src/handlers/ProtocolHandlerSpec.scala (limited to 'server/test') diff --git a/server/test/src/ServerSpec.scala b/server/test/src/ServerSpec.scala index 7d8c1fa..a7a2db0 100644 --- a/server/test/src/ServerSpec.scala +++ b/server/test/src/ServerSpec.scala @@ -1,115 +1,11 @@ package net.usebox.gemini.server -import java.nio.file.FileSystems - -import scala.concurrent.duration._ - import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers import akka.util.ByteString class ServerSpec extends AnyFlatSpec with Matchers { - def getPath(value: String) = FileSystems.getDefault().getPath(value) - - behavior of "validPath" - - it should "return true for the emtpy path" in { - Server(TestData.conf).validPath("") shouldBe true - } - - it should "return true for valid paths" in { - List("/", "/file", "/./", "/.", "/dir/", "/dir/../").foreach { p => - Server(TestData.conf).validPath(p) shouldBe true - } - } - - it should "return false for invalid paths" in { - List("/../", "/..", "/dir/../..", "/dir/../..", "/./../", "/./dir/.././../") - .foreach { p => - Server(TestData.conf).validPath(p) shouldBe false - } - } - - behavior of "guessMimeType using the internal resolver" - - it should "resolve a known MIME type" in { - Server(TestData.conf) - .guessMimeType( - getPath("file.html"), - None - ) shouldBe "text/html" - } - - it should "resolve de default MIME type for unknown types" in { - Server(TestData.conf) - .guessMimeType( - getPath("unknow"), - None - ) shouldBe TestData.conf.defaultMimeType - } - - it should "resolve gemini MIME type" in { - Server(TestData.conf) - .guessMimeType( - getPath("file.gmi"), - None - ) shouldBe "text/gemini" - Server(TestData.conf) - .guessMimeType( - getPath("file.gemini"), - None - ) shouldBe "text/gemini" - } - - it should "resolve gemini MIME type, including parameters" in { - Server(TestData.conf) - .guessMimeType( - getPath("file.gmi"), - Some("param") - ) shouldBe "text/gemini; param" - Server(TestData.conf) - .guessMimeType( - getPath("file.gemini"), - Some("param") - ) shouldBe "text/gemini; param" - } - - it should "gemini MIME type parameters are sanitized" in { - Server(TestData.conf) - .guessMimeType( - getPath("file.gmi"), - Some(" ; param") - ) shouldBe "text/gemini; param" - } - - behavior of "guessMimeType using the configured types" - - it should "resolve a known MIME type" in { - Server(TestData.conf.copy(mimeTypes = TestData.mimeTypes)) - .guessMimeType( - getPath("file.gmi"), - None - ) shouldBe "config" - } - - it should "include parameters for text/gemini MIME types" in { - Server( - TestData.conf.copy(mimeTypes = Some(Map("text/gemini" -> List(".gmi")))) - ).guessMimeType( - getPath("file.gmi"), - Some("param") - ) shouldBe "text/gemini; param" - } - - it should "resolve de default MIME type for unknown types" in { - Server(TestData.conf.copy(mimeTypes = TestData.mimeTypes)) - .guessMimeType( - getPath("unknow"), - None - ) shouldBe TestData.conf.defaultMimeType - } - behavior of "decodeUTF8" it should "return right on valid UTF-8 codes" in { @@ -706,109 +602,4 @@ class ServerSpec extends AnyFlatSpec with Matchers { cgi.body should include("GATEWAY_INTERFACE=CGI/1.1") cgi.body should include("PATH_INFO=/path/info") } - - object TestData { - - val host = "localhost" - val port = 1965 - val portStr = port.toString() - - val conf = ServiceConf( - address = "127.0.0.1", - port = port, - defaultMimeType = "text/plain", - idleTimeout = 10.seconds, - virtualHosts = List( - VirtualHost( - host = host, - root = getClass.getResource("/").getPath() - ) - ), - genCertValidFor = 1.day, - enabledProtocols = Nil, - enabledCipherSuites = Nil - ) - - val cgiConf = ServiceConf.initConf( - conf.copy(virtualHosts = - List( - conf - .virtualHosts(0) - .copy( - directoryListing = true, - directories = List( - Directory( - "dir/", - directoryListing = Some(false), - allowCgi = Some(true) - ) - ) - ) - ) - ) - ) - - val cgiPrefConf = ServiceConf.initConf( - conf.copy(virtualHosts = - List( - conf - .virtualHosts(0) - .copy( - directoryListing = true, - directories = List( - Directory( - "dir/", - directoryListing = Some(false), - allowCgi = Some(true) - ), - Directory( - "dir/sub/", - directoryListing = Some(false), - allowCgi = Some(true) - ) - ) - ) - ) - ) - ) - - val cgiEnvConf = cgiConf.copy(virtualHosts = - List( - cgiConf - .virtualHosts(0) - .copy( - environment = Some(Map("env1" -> "value")) - ) - ) - ) - - val cgiIndexConf = cgiConf.copy(virtualHosts = - List( - cgiConf - .virtualHosts(0) - .copy( - indexFile = "cgi" - ) - ) - ) - - val confUserDir = conf.copy(virtualHosts = - List( - conf - .virtualHosts(0) - .copy( - userDirectories = true, - userDirectoryPath = Some( - getClass.getResource("/").getPath() + "{user}/public_gemini/" - ) - ) - ) - ) - - val mimeTypes = Some( - Map( - "config" -> List(".gmi", ".gemini") - ) - ) - } } diff --git a/server/test/src/TestData.scala b/server/test/src/TestData.scala new file mode 100644 index 0000000..df3fbd6 --- /dev/null +++ b/server/test/src/TestData.scala @@ -0,0 +1,108 @@ +package net.usebox.gemini.server + +import scala.concurrent.duration._ + +object TestData { + + val host = "localhost" + val port = 1965 + val portStr = port.toString() + + val conf = ServiceConf( + address = "127.0.0.1", + port = port, + defaultMimeType = "text/plain", + idleTimeout = 10.seconds, + virtualHosts = List( + VirtualHost( + host = host, + root = getClass.getResource("/").getPath() + ) + ), + genCertValidFor = 1.day, + enabledProtocols = Nil, + enabledCipherSuites = Nil + ) + + val cgiConf = ServiceConf.initConf( + conf.copy(virtualHosts = + List( + conf + .virtualHosts(0) + .copy( + directoryListing = true, + directories = List( + Directory( + "dir/", + directoryListing = Some(false), + allowCgi = Some(true) + ) + ) + ) + ) + ) + ) + + val cgiPrefConf = ServiceConf.initConf( + conf.copy(virtualHosts = + List( + conf + .virtualHosts(0) + .copy( + directoryListing = true, + directories = List( + Directory( + "dir/", + directoryListing = Some(false), + allowCgi = Some(true) + ), + Directory( + "dir/sub/", + directoryListing = Some(false), + allowCgi = Some(true) + ) + ) + ) + ) + ) + ) + + val cgiEnvConf = cgiConf.copy(virtualHosts = + List( + cgiConf + .virtualHosts(0) + .copy( + environment = Some(Map("env1" -> "value")) + ) + ) + ) + + val cgiIndexConf = cgiConf.copy(virtualHosts = + List( + cgiConf + .virtualHosts(0) + .copy( + indexFile = "cgi" + ) + ) + ) + + val confUserDir = conf.copy(virtualHosts = + List( + conf + .virtualHosts(0) + .copy( + userDirectories = true, + userDirectoryPath = Some( + getClass.getResource("/").getPath() + "{user}/public_gemini/" + ) + ) + ) + ) + + val mimeTypes = Some( + Map( + "config" -> List(".gmi", ".gemini") + ) + ) +} diff --git a/server/test/src/URIUtilsSpec.scala b/server/test/src/URIUtilsSpec.scala new file mode 100644 index 0000000..ab00c86 --- /dev/null +++ b/server/test/src/URIUtilsSpec.scala @@ -0,0 +1,26 @@ +package net.usebox.gemini.server + +import org.scalatest.flatspec.AnyFlatSpec +import org.scalatest.matchers.should.Matchers + +import URIUtils._ + +class URIUtilsSpec extends AnyFlatSpec with Matchers { + + behavior of "validPath" + + it should "return true for the emtpy path" in { + "".isValidPath shouldBe true + } + + it should "return true for valid paths" in { + List("/", "/file", "/./", "/.", "/dir/", "/dir/../").foreach( + _.isValidPath shouldBe true + ) + } + + it should "return false for invalid paths" in { + List("/../", "/..", "/dir/../..", "/dir/../..", "/./../", "/./dir/.././../") + .foreach(_.isValidPath shouldBe false) + } +} diff --git a/server/test/src/handlers/ProtocolHandlerSpec.scala b/server/test/src/handlers/ProtocolHandlerSpec.scala new file mode 100644 index 0000000..d35c9f2 --- /dev/null +++ b/server/test/src/handlers/ProtocolHandlerSpec.scala @@ -0,0 +1,100 @@ +package net.usebox.gemini.server.handlers + +import java.nio.file.FileSystems +import java.net.URI + +import org.scalatest.flatspec.AnyFlatSpec +import org.scalatest.matchers.should.Matchers + +import net.usebox.gemini.server.{ServiceConf, Response} +import net.usebox.gemini.server.TestData + +class ProtocolHandlerSpec extends AnyFlatSpec with Matchers { + + def getPath(value: String) = FileSystems.getDefault().getPath(value) + + class TestHandler(conf: ServiceConf) extends ProtocolHandler(conf) { + def handle(req: String, uri: URI, remoteAddr: String): Response = ??? + } + + val handler = new TestHandler(TestData.conf) + + behavior of "guessMimeType using the internal resolver" + + it should "resolve a known MIME type" in { + handler + .guessMimeType( + getPath("file.html"), + None + ) shouldBe "text/html" + } + + it should "resolve de default MIME type for unknown types" in { + handler + .guessMimeType( + getPath("unknow"), + None + ) shouldBe TestData.conf.defaultMimeType + } + + it should "resolve gemini MIME type" in { + handler + .guessMimeType( + getPath("file.gmi"), + None + ) shouldBe "text/gemini" + handler + .guessMimeType( + getPath("file.gemini"), + None + ) shouldBe "text/gemini" + } + + it should "resolve gemini MIME type, including parameters" in { + handler + .guessMimeType( + getPath("file.gmi"), + Some("param") + ) shouldBe "text/gemini; param" + handler + .guessMimeType( + getPath("file.gemini"), + Some("param") + ) shouldBe "text/gemini; param" + } + + it should "gemini MIME type parameters are sanitized" in { + handler + .guessMimeType( + getPath("file.gmi"), + Some(" ; param") + ) shouldBe "text/gemini; param" + } + + behavior of "guessMimeType using the configured types" + + it should "resolve a known MIME type" in { + new TestHandler(TestData.conf.copy(mimeTypes = TestData.mimeTypes)) + .guessMimeType( + getPath("file.gmi"), + None + ) shouldBe "config" + } + + it should "include parameters for text/gemini MIME types" in { + new TestHandler( + TestData.conf.copy(mimeTypes = Some(Map("text/gemini" -> List(".gmi")))) + ).guessMimeType( + getPath("file.gmi"), + Some("param") + ) shouldBe "text/gemini; param" + } + + it should "resolve de default MIME type for unknown types" in { + new TestHandler(TestData.conf.copy(mimeTypes = TestData.mimeTypes)) + .guessMimeType( + getPath("unknow"), + None + ) shouldBe TestData.conf.defaultMimeType + } +} -- cgit v1.2.3