aboutsummaryrefslogtreecommitdiff
path: root/kamon-core/src/main/scala/kamon/status/StatusPageServer.scala
blob: 4e2bf03c2d213ddab255966ed0712ff7af17ccd7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package kamon.status

import fi.iki.elonen.NanoHTTPD
import fi.iki.elonen.NanoHTTPD.Response
import fi.iki.elonen.NanoHTTPD.Response.{Status => StatusCode}

class StatusPageServer(hostname: String, port: Int, resourceLoader: ClassLoader, status: Status)
    extends NanoHTTPD(hostname, port) {

  private val RootResourceDirectory = "status"
  private val ResourceExtensionRegex = ".*\\.([a-zA-Z]*)".r


  override def serve(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response = {
    if(session.getMethod() == NanoHTTPD.Method.GET) {
      if(session.getUri().startsWith("/status")) {

        // Serve the current status data on Json.
        session.getUri() match {
          case "/status/config"       => json(status.baseInfo())
          case "/status/modules"      => json(status.moduleRegistry())
          case _                      => NotFound
        }

      } else {
        // Serve resources from the status page folder.
        val resource = if (session.getUri() == "/") "/index.html" else session.getUri()
        val resourcePath = RootResourceDirectory + resource
        val resourceStream = resourceLoader.getResourceAsStream(resourcePath)

        if (resourceStream == null) NotFound else {
          NanoHTTPD.newChunkedResponse(StatusCode.OK, mimeType(resource), resourceStream)
        }
      }

    } else NotAllowed
  }

  private def mimeType(resource: String): String = {
    val ResourceExtensionRegex(resourceExtension) = resource
    resourceExtension match {
      case "css"  => "text/css"
      case "js"   => "application/javascript"
      case "ico"  => "image/x-icon"
      case "html" => "text/html"
      case _      => "text/plain"
    }
  }

  private def json[T : JsonMarshalling](instance: T): Response = {
    val builder = new java.lang.StringBuilder()
    implicitly[JsonMarshalling[T]].toJson(instance, builder)
    NanoHTTPD.newFixedLengthResponse(StatusCode.OK, "application/json", builder.toString())
  }

  private val NotAllowed = NanoHTTPD.newFixedLengthResponse(
    StatusCode.METHOD_NOT_ALLOWED,
    NanoHTTPD.MIME_PLAINTEXT,
    "Only GET requests are allowed.")

  private val NotFound = NanoHTTPD.newFixedLengthResponse(
    StatusCode.NOT_FOUND,
    NanoHTTPD.MIME_PLAINTEXT,
    "The requested resource was not found.")
}