summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorJuan J. Martinez <jjm@usebox.net>2021-02-28 08:15:55 +0000
committerJuan J. Martinez <jjm@usebox.net>2021-07-22 19:49:51 +0100
commitfc60ea8c4d52c5015edce1e4c6086d80e7a7d830 (patch)
tree3df752bef15d3a6e3367c8155a4904571e20479b /server
parent71df19c2da98428f52242e274c1d11f1c4c1ecdf (diff)
downloadspacebeans-fc60ea8c4d52c5015edce1e4c6086d80e7a7d830.tar.gz
spacebeans-fc60ea8c4d52c5015edce1e4c6086d80e7a7d830.zip
Flags per directory, override vhost settings
Diffstat (limited to 'server')
-rw-r--r--server/src/net/usebox/gemini/server/Server.scala2
-rw-r--r--server/src/net/usebox/gemini/server/ServiceConf.scala46
-rw-r--r--server/test/src/ServerSpec.scala79
3 files changed, 111 insertions, 16 deletions
diff --git a/server/src/net/usebox/gemini/server/Server.scala b/server/src/net/usebox/gemini/server/Server.scala
index ed9252d..2e9bb6b 100644
--- a/server/src/net/usebox/gemini/server/Server.scala
+++ b/server/src/net/usebox/gemini/server/Server.scala
@@ -142,7 +142,7 @@ case class Server(conf: ServiceConf) {
bodySize = dirFile.length(),
bodyPath = Some(dirFilePath)
)
- } else if (vhost.directoryListing) {
+ } else if (vhost.getDirectoryListing(resource)) {
logger.debug("directory listing")
DirListing(
req,
diff --git a/server/src/net/usebox/gemini/server/ServiceConf.scala b/server/src/net/usebox/gemini/server/ServiceConf.scala
index 9c0f8e8..f0751d2 100644
--- a/server/src/net/usebox/gemini/server/ServiceConf.scala
+++ b/server/src/net/usebox/gemini/server/ServiceConf.scala
@@ -1,21 +1,39 @@
package net.usebox.gemini.server
+import java.nio.file.{Path, FileSystems}
+
+import scala.concurrent.duration.FiniteDuration
+
import pureconfig._
import pureconfig.generic.semiauto._
-import scala.concurrent.duration.FiniteDuration
+import org.log4s._
case class KeyStore(path: String, alias: String, password: String)
+case class Directory(path: String, directoryListing: Option[Boolean])
+
case class VirtualHost(
host: String,
root: String,
keyStore: Option[KeyStore] = None,
indexFile: String = "index.gmi",
directoryListing: Boolean = true,
- geminiParams: Option[String] = None
+ geminiParams: Option[String] = None,
+ directories: List[Directory]
)
+object VirtualHost {
+ implicit class VirtualHostOps(vhost: VirtualHost) {
+ def getDirectoryListing(path: Path): Boolean =
+ vhost.directories
+ .find(_.path == path.toString())
+ .fold(vhost.directoryListing)(loc =>
+ loc.directoryListing.getOrElse(vhost.directoryListing)
+ )
+ }
+}
+
case class ServiceConf(
address: String,
port: Int,
@@ -30,9 +48,31 @@ case class ServiceConf(
object ServiceConf {
+ private[this] val logger = getLogger
+
implicit val keyStoreReader = deriveReader[KeyStore]
+ implicit val directoryHostReader = deriveReader[Directory]
implicit val virtualHostReader = deriveReader[VirtualHost]
implicit val serviceConfReader = deriveReader[ServiceConf]
- def load(confFile: String) = ConfigSource.file(confFile).load[ServiceConf]
+ def load(confFile: String) =
+ ConfigSource.file(confFile).load[ServiceConf].map { conf =>
+ conf.copy(virtualHosts = conf.virtualHosts.map { vhost =>
+ vhost.copy(directories = vhost.directories.map { dir =>
+ val path =
+ FileSystems
+ .getDefault()
+ .getPath(vhost.root, dir.path)
+ .normalize()
+
+ if (!path.toFile().isDirectory())
+ logger.warn(
+ s"In virtual host '${vhost.host}': directory entry '${dir.path}' is not a directory"
+ )
+
+ dir
+ .copy(path = path.toString())
+ })
+ })
+ }
}
diff --git a/server/test/src/ServerSpec.scala b/server/test/src/ServerSpec.scala
index d086d2d..c81afa3 100644
--- a/server/test/src/ServerSpec.scala
+++ b/server/test/src/ServerSpec.scala
@@ -10,6 +10,14 @@ import akka.util.ByteString
class ServerSpec extends AnyFlatSpec with Matchers {
+ def getPath(value: String) = FileSystems.getDefault().getPath(value)
+
+ def getPath(root: String, dir: String) =
+ FileSystems
+ .getDefault()
+ .getPath(root, dir)
+ .normalize()
+
behavior of "validPath"
it should "return true for the emtpy path" in {
@@ -34,7 +42,7 @@ class ServerSpec extends AnyFlatSpec with Matchers {
it should "resolve a known MIME type" in {
Server(TestData.conf)
.guessMimeType(
- FileSystems.getDefault().getPath("file.html"),
+ getPath("file.html"),
None
) shouldBe "text/html"
}
@@ -42,7 +50,7 @@ class ServerSpec extends AnyFlatSpec with Matchers {
it should "resolve de default MIME type for unknown types" in {
Server(TestData.conf)
.guessMimeType(
- FileSystems.getDefault().getPath("unknow"),
+ getPath("unknow"),
None
) shouldBe TestData.conf.defaultMimeType
}
@@ -50,12 +58,12 @@ class ServerSpec extends AnyFlatSpec with Matchers {
it should "resolve gemini MIME type" in {
Server(TestData.conf)
.guessMimeType(
- FileSystems.getDefault().getPath("file.gmi"),
+ getPath("file.gmi"),
None
) shouldBe "text/gemini"
Server(TestData.conf)
.guessMimeType(
- FileSystems.getDefault().getPath("file.gemini"),
+ getPath("file.gemini"),
None
) shouldBe "text/gemini"
}
@@ -63,12 +71,12 @@ class ServerSpec extends AnyFlatSpec with Matchers {
it should "resolve gemini MIME type, including parameters" in {
Server(TestData.conf)
.guessMimeType(
- FileSystems.getDefault().getPath("file.gmi"),
+ getPath("file.gmi"),
Some("param")
) shouldBe "text/gemini; param"
Server(TestData.conf)
.guessMimeType(
- FileSystems.getDefault().getPath("file.gemini"),
+ getPath("file.gemini"),
Some("param")
) shouldBe "text/gemini; param"
}
@@ -76,7 +84,7 @@ class ServerSpec extends AnyFlatSpec with Matchers {
it should "gemini MIME type parameters are sanitized" in {
Server(TestData.conf)
.guessMimeType(
- FileSystems.getDefault().getPath("file.gmi"),
+ getPath("file.gmi"),
Some(" ; param")
) shouldBe "text/gemini; param"
}
@@ -86,7 +94,7 @@ class ServerSpec extends AnyFlatSpec with Matchers {
it should "resolve a known MIME type" in {
Server(TestData.conf.copy(mimeTypes = TestData.mimeTypes))
.guessMimeType(
- FileSystems.getDefault().getPath("file.gmi"),
+ getPath("file.gmi"),
None
) shouldBe "config"
}
@@ -95,7 +103,7 @@ class ServerSpec extends AnyFlatSpec with Matchers {
Server(
TestData.conf.copy(mimeTypes = Some(Map("text/gemini" -> List(".gmi"))))
).guessMimeType(
- FileSystems.getDefault().getPath("file.gmi"),
+ getPath("file.gmi"),
Some("param")
) shouldBe "text/gemini; param"
}
@@ -103,7 +111,7 @@ class ServerSpec extends AnyFlatSpec with Matchers {
it should "resolve de default MIME type for unknown types" in {
Server(TestData.conf.copy(mimeTypes = TestData.mimeTypes))
.guessMimeType(
- FileSystems.getDefault().getPath("unknow"),
+ getPath("unknow"),
None
) shouldBe TestData.conf.defaultMimeType
}
@@ -230,7 +238,53 @@ class ServerSpec extends AnyFlatSpec with Matchers {
}
}
- it should "return not found if directory listing is nt enabled and no index" in {
+ it should "return a directory listing, directory listing flags: vhost flag false, directories flag true" in {
+ Server(
+ TestData.conf.copy(virtualHosts =
+ List(
+ TestData.conf
+ .virtualHosts(0)
+ .copy(
+ directoryListing = false,
+ directories = List(
+ Directory(
+ getPath(getClass.getResource("/").getPath(), "dir/")
+ .toString(),
+ directoryListing = Some(true)
+ )
+ )
+ )
+ )
+ )
+ ).handleReq("gemini://localhost/dir/") should matchPattern {
+ case _: DirListing =>
+ }
+ }
+
+ it should "return not found with no index, directory listing flags: vhost flag true, directories flag false" in {
+ Server(
+ TestData.conf.copy(virtualHosts =
+ List(
+ TestData.conf
+ .virtualHosts(0)
+ .copy(
+ directoryListing = true,
+ directories = List(
+ Directory(
+ getPath(getClass.getResource("/").getPath(), "dir/")
+ .toString(),
+ directoryListing = Some(false)
+ )
+ )
+ )
+ )
+ )
+ ).handleReq("gemini://localhost/dir/") should matchPattern {
+ case _: NotFound =>
+ }
+ }
+
+ it should "return not found if directory listing is not enabled and no index" in {
Server(
TestData.conf.copy(virtualHosts =
List(TestData.conf.virtualHosts(0).copy(directoryListing = false))
@@ -266,7 +320,8 @@ class ServerSpec extends AnyFlatSpec with Matchers {
virtualHosts = List(
VirtualHost(
host = "localhost",
- root = getClass.getResource("/").getPath()
+ root = getClass.getResource("/").getPath(),
+ directories = Nil
)
),
genCertValidFor = 1.day,