4

I'm learning Scalatra and am wondering how I can make the default Content-Type of my responses application/json. The current default appears to be text/html. Neat, but not really useful to my application.

The current default is text/html.

$ curl -i -X GET 'http://localhost:8080/v1/example'
HTTP/1.1 200 OK
Date: Fri, 19 Apr 2019 07:21:21 GMT
Content-Type: text/html;charset=utf-8
Content-Length: 23
Server: Jetty(9.4.8.v20171121)

HelloWorld(hello,world)

I can get application-json explicitly through the Accepted: application/json header.

$ curl -i -X GET 'http://localhost:8080/v1/example' -H 'Accept: application/json'
HTTP/1.1 200 OK
Date: Fri, 19 Apr 2019 07:22:09 GMT
Content-Type: application/json;charset=utf-8
Transfer-Encoding: chunked
Server: Jetty(9.4.8.v20171121)

{"hello":"hello","world":"world"}

How do I set the default to be application/json.

Bob Kuhar
  • 10,838
  • 11
  • 62
  • 115
  • How do you generate the response? Simply by returning a string that contains a json? If you would be using proper types then it scalatra should be able to figure out the content type as here: https://github.com/swagger-api/scalatra-sample-app/blob/master/src/main/scala/com/wordnik/swagger/sample/PetServlet.scala – michaJlS Apr 19 '19 at 20:43
  • @michaJlS Scalatra is bright enough to know how to deal with a case class. It is already doing that, if the client requests `-H Accept: application/json` scalatra takes the case class and make the JSON string. That works great. The problem is, I want the default to just be `Content-Type: application/json`. Scalatra doesn't make that so convenient. There has to be a way. – Bob Kuhar Apr 20 '19 at 23:17
  • So this link then should be helpful: http://scalatra.org/guides/2.3/formats/json.html – michaJlS Apr 22 '19 at 13:29
  • @michaJlS Thanks, but I'm way past that. The `before() { contentType = formats("json") }` indeed sets the contentType for the Servlet as constant `application/json`, so if someone requests `text/html`, they don't get it. All I'm trying to do is override the default in the absence of an `Accepts` header. It is surprising that it is so difficult to do that. – Bob Kuhar Apr 22 '19 at 14:02

1 Answers1

3

defaultFormat could be overridden to make application/json the default case. For example,

import java.io.File
import org.scalatra._
import org.scalatra.util.MimeTypes
import org.json4s.{DefaultFormats, Formats}
import org.scalatra.json._

case class HelloWorld(hello: String, world: String)

class MyScalatraServlet extends ScalatraServlet with JacksonJsonSupport {
  protected implicit lazy val jsonFormats: Formats = DefaultFormats

  override def defaultFormat: Symbol = 'json

  get("/v1/example") {
    HelloWorld("hello", "world")
  }

}

without specifying Accept header should respond with

curl -i -X GET 'http://localhost:8080/v1/example'
HTTP/1.1 200 OK
Date: Thu, 25 Apr 2019 22:28:37 GMT
Content-Type: application/json;charset=utf-8
Content-Length: 33
Server: Jetty(9.4.8.v20171121)

{"hello":"hello","world":"world"}

whilst explicitly requesting Accept: text/html also works

curl -i -X GET 'http://localhost:8080/v1/example' -H 'Accept: text/html'
HTTP/1.1 200 OK
Date: Fri, 26 Apr 2019 15:45:22 GMT
Content-Type: text/html;charset=utf-8
Content-Length: 23
Server: Jetty(9.4.8.v20171121)

HelloWorld(hello,world)
Mario Galic
  • 47,285
  • 6
  • 56
  • 98
  • @"Mario Galic". Cool, but....obscure? I was kind-of expecting something more along the lines of `override def defaultFormat = formats("json")` or something. How did you figure this out? I'm newish to Scala and completely new to Scalatra and am trying to find my way in this "ecosystem". – Bob Kuhar Apr 27 '19 at 00:15
  • 1
    I searched for term `Accept` in Scalatra Github repo to see how the header gets used which led me to `ApiFormats.scala`. – Mario Galic Apr 27 '19 at 00:27