【问题标题】:Request Content-Type in Play! Framework for REST webservices在 Play 中请求 Content-Type! REST Web 服务框架
【发布时间】:2012-03-29 08:37:39
【问题描述】:

我正在尝试使用 Play 实现 REST Web 服务!框架。我知道如何通过指定多个模板以不同格式(JSON、XML、HTML 等)返回响应。但是,我没有找到任何有关如何处理(例如 POST)请求(表单编码、JSON、XML 等)中不同内容类型的信息。

是否可以注释方法以仅匹配某些内容类型(例如@Consumes)?我是否必须在控制器方法中使用if-clause 区分不同的请求内容类型?

【问题讨论】:

    标签: rest playframework content-type


    【解决方案1】:

    查看 Play 文档以了解组合正文解析器:

    http://www.playframework.com/documentation/2.2.0/ScalaBodyParsers

    如果您想将帖子正文限制为仅 xml 或 json,您可以按照以下方式编写一些内容:

    val xmlOrJson = parse.using {
      request =>
        request.contentType.map(_.toLowerCase(Locale.ENGLISH)) match {
          case Some("application/json") | Some("text/json") => play.api.mvc.BodyParsers.parse.json
          case Some("application/xml") | Some("text/xml") => play.api.mvc.BodyParsers.parse.xml
          case _ => play.api.mvc.BodyParsers.parse.error(Future.successful(UnsupportedMediaType("Invalid content type specified")))
        }
    }
    
    def test = Action(xmlOrJson) {
      request =>
        request.body match {
          case json: JsObject => Ok(json) //echo back posted json
          case xml: NodeSeq => Ok(xml) //echo back posted XML
        }
    }
    

    xmlOrJson 函数查看内容类型请求标头以确定正文解析器。如果它不是 xml 或 json,则它返回带有 UnsupportedMediaType 响应 (HTTP 415) 的错误正文解析器。

    然后,您将此函数作为您想要限制为 xml 或 json 内容的任何操作的主体解析器传递。在操作中,您可以查看正文以确定是否已解析 xml 或 json 并进行相应处理。

    【讨论】:

      【解决方案2】:

      您不是通过注释来执行此操作,而是通过您的路由文件或通过您的操作中的 if 语句来执行此操作。取决于您的用例,哪个最适合。

      以下 URL 为您提供了有关用于内容协商的路由文件的一些信息。 http://www.playframework.org/documentation/1.2.4/routes#content-types

      例子

      GET    /index.xml         Application.index(format:'xml')  
      GET    /index.json        Application.indexJson(format:'json')  
      

      上面调用了不同的动作,但如果你愿意,你可以用不同的格式值调用相同的动作。

      【讨论】:

      • 据我了解,您引用的文档部分是关于结果(响应)的内容类型。但是,我的问题是关于请求的内容类型(例如,包含表单或 JSON 数据的 POST 请求的正文)。
      • 我猜不同格式的处理是一样的,只是最后的响应不同?如果是这样,如何让 1 个控制器方法消耗每个请求,进行一般处理(保持 DRY),然后根据 request.contentType.equals("application/json OR whatever") 决定如何渲染它?
      • @Geert-Jan 当你调用 render 方法时,它会根据格式渲染视图,所以如果 index.xml 它会渲染 index.xml 文件,但是对于 index.json,它将调用 index.json 文件。两者都将由 Groovy 正常评估,但它允许控制器共享相同的代码,但附加两个或多个不同的视图。
      【解决方案3】:

      您可以在 Play 2 with Scala 中使用默认解析器和模式匹配。像这样的:

        def myAction() = Action { req =>
          req.body match {
            case AnyContentAsFormUrlEncoded(m) =>
              val f1 = m.get("field1").flatMap(_.headOption)
              ...
            case AnyContentAsJson(j) =>        
              val f1 = (j \ "field1").asOpt[String]
              ...
            case _ => //handle content types you don't support
              ...
      }
      

      【讨论】:

        猜你喜欢
        • 2011-09-16
        • 2012-02-28
        • 1970-01-01
        • 1970-01-01
        • 2011-01-30
        • 2014-12-14
        • 1970-01-01
        • 1970-01-01
        • 2014-07-19
        相关资源
        最近更新 更多