Freewind @ Thoughtworks scala java javascript dart 工具 编程实践 月结 math python english [comments admin] [feed]

(2013-01-01) 05. Http正文解析器

广告: 云梯:翻墙vpn (省10元) 土行孙:科研用户翻墙http proxy (有优惠)

(本文译者是爱国者)

什么是Http正文解析器(Http Body Parser)

我们知道Http的PUT请求和POST请求能包含正文(或叫主体). Http正文能携带任何信息,通过Content-Type标明正文的类型。Play使用正文解析器(Body parser)将Http正文转换成某种Scala类型的数据。

一个Http正文解析器用play.api.mvc.BodyParser[A]表示,它将接收到的字节流转换成类型为A的目标对象.

然而,http正文可能很大, 如果等所有的正文内容传输完再一次性放到内存进行解析,这样的做法是不高效的。 某些目标对象,比如字符串和文件,完全可以一边接收字节流一边进行构建。

另外,在开始解析正文之前,Http正文解析器可以获取请求头的内容,从而可以对正文先执行一些检查. 比如客户端上传的文件是否过大,正文类型(Content-Type)是否符合要求等等。

注意:你可以将BodyParser[A]看成Iteratee[Array[Byte], A],但准确来说应该要看成Iteratee[Array[Byte], Either[Result,A]]。这样设计的目的在于,当无法正确解析Http正文时可以直接返回诸如400 BAD_REQUEST,412 PRECONDITION_FAILED或者413 REQUEST_ENTITY_TOO_LARGE等响应。想了解更多流式处理的内容,请点击 [[这里 | Iteratees]]

完成Http正文的解析之后会返回一个类型为A的对象并保存在request对象里,然后执行Action函数

关于Actions

前面提到,Action是一个Request => Result的函数,但不完全正确。我们先来看看Action特质的定义:

trait Action[A] extends (Request[A] => Result) {
  def parser: BodyParser[A]
}

首先我们看到`Request`带有一个泛型`A`,并在`Action`中定义了一个象函数`parser`,`parser`的返回类型是`BodyParser[A]`

我们再来看看`Request`特质的定义:

trait Request[+A] extends RequestHeader {
  def body: A
}

这里的`A`类型就是Http正文解析后的类型。我们定义任何我们想要的类型,常见的有`String`,`NodeSeq`,`Array[Byte]`,`JsonValue`和`java.io.File`等,只要提供相应的body parser

总的来说,`Action[A]`使用`BodyParser[A]`将Http正文解析成类型为`A`的对象,然后创建`Request[A]`对象并传递给action代码块

#### 默认的Http正文解析器

如果不指定Http正文解析器,那么Play会使用一个将Http正文解析成`play.api.mvc.AnyContent`的默认解析器(`play.api.mvc.BodyParsers.parser`)。这个解析器会根据`Content-Type`的值决定解析成那种类型的对象;

原文:https://github.com/playframework/Play20/wiki/ScalaBodyParsers

comments powered by Disqus