読者です 読者をやめる 読者になる 読者になる

謎言語使いの徒然

適当に気になった技術や言語を流すブログ。

Play2.2.1のWSがもう少しどうにかならんかと思って解析してみた

勉強 Scala Playframework

経緯:試しに書いたらこんなことになり、フォーラムでは対応してないとか言ってて、じゃぁテストとかどうすんだろう?とか思ったらこの辺

テストで「WS.url で multipart 飛ばせないの?」→「FakeRequest作りこんでテストして」とかそういう話があったので、「そんなこつおいが知るか!なら最初から根っこ読んだら良か」てなことで解析したメモ。

まず事前準備

Download Play Framework

ここから Zip 版を落として解凍する。

中にコードが入ってる。

まぁ早速というか、、、、WS使って、namespace 見ればおおよそ位置がわかるよね。

play-2.2.1/framework/src/play/src/main/scala/play/api/libs/ws

中を軽く見ればわかるけど、com.ning.http.client.AsyncHttpClient を Future でラップしたものが正体なわけだ。

AsyncHttpClient/async-http-client · GitHub

極論これの AsyncHttpClient.executeRequest を呼んでると。

で、これで multipart 出来ないの?と思うと、何かおあつらえ向きな処理がいくつか見つかる。

Platframework2.2.1 のテスト上下記を実行してみた。

    val fakeApplication = FakeApplication(withRoutes = {
      case ("POST", "/") => Action(BodyParsers.parse.multipartFormData) { request =>
        val dataParts = request.body.dataParts
        val fileParts = request.body.files
        val files = fileParts.length
        val fileNames = fileParts.map(v => s"  ${v.key}:${v.filename}").mkString(",")

        Results.Ok(s"DataParts: ${dataParts.toString()}\nFiles: $files\n$fileNames")
          .withHeaders(CONTENT_TYPE -> "plain/text")
      }
    })

    "POST multipart" in new WithServer(app = fakeApplication, port = 6000) {
      import com.ning.http.client.{StringPart, FilePart}
      import javax.activation.MimetypesFileTypeMap
      import java.io.File

      val fileTypeMap = new MimetypesFileTypeMap()
      val sendFile    = new File("D:\\MyDocuments\\Pctures\\images\\3EDD9734-D004-424A-B5BC-9A125556A45B.jpg")
      val builder     = WS.client.preparePost("http://localhost:6000")

      builder.setHeader("Content-Type", "multipart/form-data")
      builder.addBodyPart(new StringPart("a", "test1"))
      builder.addBodyPart(new StringPart("b", "test1"))
      builder.addBodyPart(new FilePart("file1", sendFile, fileTypeMap.getContentType(sendFile), "UTF-8"))

      val response = builder.execute().get()

      println(response.getResponseBody)
      response.getStatusCode mustEqual OK
    }

外部アプリケーションのテストが随分楽になったなーとか思いつつ。

で、実行結果が下記。

DataParts: Map(b -> List(test1), a -> List(test1))
Files: 1
  file1:3EDD9734-D004-424A-B5BC-9A125556A45B.jpg
[info] ApplicationSpec
[info] Application should
[info] + send 404 on a bad request
[info] + render the index page
[info] + POST multipart
[info] Total for specification ApplicationSpec
[info] Finished in 1 second, 30 ms
[info] 3 examples, 0 failure, 0 error
[info] Passed: Total 4, Failed 0, Errors 0, Passed 4

予定通り(ニヤソ