Skip to content

Instantly share code, notes, and snippets.

@windymelt
Last active August 29, 2015 14:17
Show Gist options
  • Save windymelt/df49e4a8c093c7816f17 to your computer and use it in GitHub Desktop.
Save windymelt/df49e4a8c093c7816f17 to your computer and use it in GitHub Desktop.
Play 2.3.x でShift_JISのパーセントエンコーディングされたデータを受け取る
package controllers
import play.api._
import play.api.mvc._
import play.api.data._
object Application extends Controller {
def hoge = Action(parse.tolerantText) { request ⇒ // 生の文字列で受け取る。
// 修正したリクエストでimplicit宣言する。
// あたかも最初からパースされたフォームデータが渡されたような状態にする。
// Formを使う部分はこのRequestを使うようになる。
implicit val newRequest = PercentEncoding.extractSJISRequest(request)
/* ... */
}
}
/* パーセントエンコードされたフォームデータをパースするためのライブラリ */
libraryDependencies += "org.apache.httpcomponents" % "httpclient" % "4.4"
package controllers
import play.api.mvc.{ Headers, Request }
object PercentEncoding {
import java.net.URI
import scala.collection.JavaConversions._
import org.apache.http.client.utils.URLEncodedUtils
import org.apache.http.NameValuePair
def extractSJISRequest(request: Request[String]) = {
// パーセントエンコードされたStringが格納されているbodyを取得する。
val body = request.body
// ライブラリ独自のクラスであるNameValuePairのSeqに変換する。
// URLEncodedUtils.parseはList<NameValuePair>を返すが、
// scala.collection.JavaConversions._ をimportしているのでList(Java) -> Seq(Scala)に暗黙変換される。
// URLEncodedUtilsは、本来はbodyではなくURL内でのパーセントエンコーディングを想定しているので、
// ダミーURLを作成してそのクエリという体でパースさせる。
val parsed: Seq[NameValuePair] = URLEncodedUtils.parse(new URI("http://example.com/?" + body), "Shift_JIS")
// Seq[NameValuePair]をPlayでフォームデータの表現として使用されるMap[String, Seq[String]]に変換する。
// 通常、application/x-www-form-urlencodedで渡ってきたデータはMap[String, Seq[String]]となるが、
// ここで本来のデータ形式を再現する。
val newBody = parsed.map { pair ⇒ (pair.getName, Seq(pair.getValue)) }.toMap
// あたかも最初からフォームとしてパースされていたようなリクエストを用意する。
// bodyだけが変更されており、その他のパラメータはオリジナルのまま。
// 型もRequest[String]ではなくRequest[Map[String, Seq[String]]]になっている。
new Request[Map[String, Seq[String]]] {
override def body: Map[String, Seq[String]] = newBody // すげかえる
override def uri: String = request.uri
override def remoteAddress: String = request.remoteAddress
override def queryString: Map[String, Seq[String]] = request.queryString
override def method: String = request.method
override def headers: Headers = request.headers
override def path: String = request.path
override def version: String = request.version
override def tags: Map[String, String] = request.tags
override def id: Long = request.id
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment