仕組み
ソースを追ってみると、StatefulSnippet.linkはコールバック時に第2引数で指定した関数の前に、registerThisSnippet()を呼ぶようなブロックに差し替えて、SHtml.linkと同じ処理をしているだけです。
// StatefulSnippet.scala def link(to: String, func: () => Any, body: NodeSeq): Elem = SHtml.link(to, () => {registerThisSnippet(); func()}, body)
SHtml.linkは何をやっているかというと、fmapFuncでコールバック関数を登録し、そのキーをクエリ文字列としてURLに付加しています。
// SHtml.scala def link(to: String, func: () => Any, body: NodeSeq, attrs: (String, String)*): Elem = { fmapFunc((a: List[String]) => {func(); true})(key => attrs.foldLeft(<a href={to + (if (to.indexOf("?") >= 0) "&" else "?") + key + "=_"}>{body}</a>)(_ % _)) }
ここで、既にクエリ文字列がある(="?"が含まれる)場合には"&"でつなげてることに気づき、問題解決。
問題解決
問題となったは、AU携帯で位置情報を付加してリクエストを送るための、以下の様なaタグを出力しようとした部分。<a href="device:location?url=http://www.mb4sq.jp/search"/>
def search(in: NodeSeq): NodeSeq = bind("f", in, "link" -> link("device:location?url=http://localhost/search", ()=>"", Text("search")))こんなコードを書いてみたところ、本来欲しいURLは
device:location?url=http://localhost/search?F869982852207GSN=_ の様なものなんですが、元のURLに"?"が入ってしまっているので、"?"の代わりに"&"が付加されてしまい、
device:location?url=http://localhost/search&F869982852207GSN=_ になってしまってるわけですね…。これではクエリ文字列として取得できず、ステートを維持するためのregisterThiSnippet()のコールバックが呼ばれずに、ステートが切れてしまっていたと。
結局、StatefulSnippet.linkをオーバーライドして、GPSのリンクの場合はハードコードで"?"を付けるようにして回避しました。
override def link(to: String, func: () => Any, body: NodeSeq): Elem = { def insert(s: String, i: String, p: Int) = List(s take p, i, s drop p).mkString if (to.startsWith("device:")) S.fmapFunc((a: List[String]) => {registerThisSnippet(); func()})(key => { val u = if (to.indexOf("&ver=1") > 0) insert(to, ("?" + key + "=_"), to.indexOf("&ver=1")) else to + ("?" + key + "=_") <a href={u}>{body}</a> }) else super.link(to, func, body) }
0 件のコメント:
コメントを投稿