Martini: POST リクエストを扱う

net/http の FormValue を使う。

package main

import (
  "net/http"
  "github.com/go-martini/martini"
)

func main() {
  m := martini.Classic()
  m.Post("/", func(res http.ResponseWriter, req *http.Request) string {
  	res.Header().Add("content-type", "text/html; charset=utf8")
    return req.FormValue("foo")
  })
  m.Run()
}

Martini: Hello World

前段階としてコードを修正したときにサーバーのコードをリロードしてくれる gin を導入する。

go get github.com/codegangsta/gin

環境変数の PATH に $GOPATH/bin を追加する。

export PATH=$GOPATH/bin:$PATH

Martini を導入しよう。

go get github.com/go-martini/martini

次のコードを server.go として保存する。

package main

import (
  "net/http"
  "github.com/go-martini/martini"
)

func main() {
  m := martini.Classic()
  m.Get("/", func(res http.ResponseWriter) string {
  	res.Header().Add("content-type", "text/html; charset=utf8")
    return "Hello World"
  })
  m.Run()
}

gin を使ってサーバーを立ち上げてみよう。

gin server.go

httpie を使って localhost:3000 に GET リクエストをしてみよう。

http localhost:3000

次はミドルウェアの render を使って JSON を返してみよう。まずは render をインストールする。

go get github.com/codegangsta/martini-contrib/render

コントローラーは次のようになる。

package main

import (
  "github.com/codegangsta/martini"
  "github.com/codegangsta/martini-contrib/render"
)

func main() {
  m := martini.Classic()
  m.Use(render.Renderer())

  m.Get("/", func(r render.Render) {
    r.JSON(200, map[string]interface{}{"msg": "Hello World"})
  })

  m.Run()
}

Play 2: POST リクエストを扱う

conf/routes で POST をうけつけるアクションを指定する。

GET     /hello                      controllers.Hello.index
POST     /hello/create        controllers.Hello.create

Content-Type が「application/x-www-form-urlencoded」の場合、asFormUrlEncoded メソッドを使う。

package controllers

import play.api._
import play.api.mvc._

object Hello extends Controller {
  def index = Action {
    Ok("Hello World")
  }

  def create = Action { request =>
    val values = request.body.asFormUrlEncoded
    Ok(values.get("foo")(0))
  }
}

httpie を使って POST リクエストを送信してみよう。

http -v -f POST localhost:3000/hello/create foo=bar

次は JSON を扱えるようにしてみよう。

package controllers

import play.api._
import play.api.mvc._
import play.api.libs.json._
import play.api.libs.functional.syntax._

object Hello extends Controller {

  implicit val rds = (
    (__ \ 'name).read[String] and
    (__ \ 'age).read[Long]
  ) tupled

  def index = Action {
    Ok("Hello World")
  }

  def create = Action(parse.json) { request =>
    request.body.validate[(String, Long)].map{ 
      case (name, age) => Ok("Hello " + name + ", you're "+age)
    }.recoverTotal{
      e => BadRequest("Detected error:"+ JsError.toFlatJson(e))
    }
  }
}

httpie で試してみよう。

http -v localhost:3000/create name=Toto age:=32

Play 2: Hello World

Play Framework 2.3 を対象とする。Mac OSX の場合、homebrew でツールを導入する。

brew install typesafe-activator

プロジェクトを生成して HTTP サーバーを立ち上げ、ブラウザで localhost:3000 にアクセスしてみよう。

activator new my-first-app play-scala
cd my-first-app
activator "run 3000"

コントローラーを追加して、localhost:3000/hello にアクセスすると文字が表示されるようにしてみよう。コントローラーのパスは app/controllers/Hello.scala とする。

package controllers

import play.api._
import play.api.mvc._

object Hello extends Controller {

  def index = Action {
    Ok("Hello World")
  }

}

次にルーティングの設定ファイルの conf/routes を修正する。

GET     /                           controllers.Application.index
GET     /hello                      controllers.Hello.index

コントローラーからヘッダーを変更してみよう。

package controllers

import play.api._
import play.api.mvc._
import play.api.libs.iteratee.Enumerator

object Hello extends Controller {

  def index = Action {
    Result(
      header = ResponseHeader(200, Map(CONTENT_TYPE -> "text/plain")),
      body = Enumerator("Hello world!".getBytes())
    )
  }

}

JSON をレスポンスとして返してみよう。

package controllers

import play.api._
import play.api.mvc._
import play.api.libs.json._

object Hello extends Controller {

  def index = Action {
    Ok(Json.obj("status" ->"OK", "msg" -> "Hello World"))
  }
}

Rails 4: POST リクエストを扱う

HTTP メソッドの種類を config/routes.rb で指定する必要がある。

post 'hello' => 'hello#index'

複数の HTTP メソッドに対応するのであれば、match メソッドを使うことができる。

match 'hello' => 'hello#index', :via => [:get, :post]

POST メソッドに対応できるようにするために CSRF を無効にする。コントローラーのすべてのアクションで CSRF を無効にするには skip_before_filter を呼び出す。

class HelloController < ApplicationController
  skip_before_filter :verify_authenticity_token

  def index
    render plain: params[:foo] == 'bar' ? 'ok' : 'fail'
  end

end

CSRF を無効にするには protect_from_forgery を使うことができる。

class HelloController < ApplicationController
  protect_from_forgery except: :index
end

httpie のコマンドで POST リクエストを試してみよう。CSRF を無効にしていない場合、422 Unprocessable Entit エラーになる。

http localhost:3000/hello foo=bar

JSON リクエストも自動的に解析される。httpie で JSON を POST メソッドで投稿してみよう。

http localhost:3000/hello foo=bar baz=qux

params から想定していない値を取り出せないようにするには permit メソッドを使うことができる。

def index
  render plain: params.permit(:foo)
end

require メソッドの場合、指定した値が含まれない場合、例外が投げられる。

def index
  render plain: params.require(:foo)
end

今度は CSRF 対策のトークンを送信してみよう。トークンを得るには form_authenticity_token を使う。このメソッドを呼び出すと、セッション Cookie も発行されるので、トークンと一緒に送信する必要がある。

まずは POST を受けつけるアクションを config/routes.rb で指定しよう。

Rails.application.routes.draw do

  get 'hello/index'
  get 'hello' => 'hello#index'

  match 'hello/create' => 'hello#create', :via => [:get, :post]
end

次にコントローラーを修正する。

class HelloController < ApplicationController

  def index
   render plain: render plain: request_forgery_protection_token.to_s + ':  ' + form_authenticity_token
  end

  def create
  	render plain: 'ok'
  end

end

次の URL から CSRF 対策のトークンとセッション Cookie を発行してもらう。 次の例では httpie を使っている。

http localhost:3000/hello

POST リクエストを発行して、レスポンスの HTTP ステータスコードが 200 になるか確認してみよう。Cookie と ‘X-CSRF-Token ヘッダーに指定する値は先ほどの GET リクエストで調べたものを使う。

http --headers localhost:3000/hello/create 'Cookie: _myproject_session=NDZFUjkyOC9qMUR2UUZ6VGxWOEE3T0x2cDlmdkk3a2FIWWc2bTBBMXdoakpId3l2dTlLdnR1WWQ5SXdoQkdtSlBKWFRuTmthT1RxU3BtV0drZTRhOUxIK29DWXVYLzZQS0JXVFZsanlVWEhpanB5N1BIT0k3bVJRTDdldm5LZjU2cnBxdDFxVkdqSi8zeEFINk1tV1NnPT0tLWF4VHR2eG15eFJqVmxXSHR4eUVUbmc9PQ%3D%3D--bcdfe477cbd64a5a2eb279da229b40334f258ce9; path=/; HttpOnly' 'X-CSRF-Token: JjyGuDi2WOL4RgEhVQG3DV0IfMVYufLz8qSUkwJRGF0='

X-CSRF-Token ヘッダーの代わりにリクエストボディに含めることができる。パラメーターの名前は authenticity_token になる。

http --headers localhost:3000/hello/create 'Cookie: _myproject_session=MWRFeXRveDZaRlQ0Vm5EWFByZno5Vy8yWGxlZ2FoaGRBaEhZeFRpVnhzODkwNzhqeTQxWFNpc1dCcnZsdkM3d1g3Y3htY21mOVMySDd1NDJ4OTZHdU1ubGoyVDUzR3JQR015WHpNNCtmeHAzQ2FyR3NQN2lITlVOVlJrU2RiTEtDSlIvSmFlNVpZanA3a09kRUp6QTl3PT0tLUxyQk8zeHl6bUlFd0xJMkgyZmNGMlE9PQ%3D%3D--22689f9dfd46aa6b9f3d5a62da1d66f00dbddc0f; path=/; HttpOnly' authenticity_token=OVsarDTtFB65SeGOOrHzgSL7fvuUKR543xRC98K2+XA=
アーカイブ ランダム ホーム 次のページ ページ 1 / 373