デバッグのためのテストとして json を POST して json を返すウェブサービスを Micronaut でつくる話。
前回同様に myapp というプロジェクトの雛形を作成します。
$ mn create-app myapp --build=gradle --lang=groovy
$ cd myapp
$ mn create-controller item
ここで雛形として生成されたコントローラのクラス( src/test/groovy/myapp/ItemControllerSpec.groovy )を以下のように変更します。
package myapp
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Post
import io.micronaut.http.annotation.Body
@Controller("/item")
class ItemController {
@Post(uri="/", consumes=["application/json"], produces="application/json")
def index(@Body def contents) {
println contents
[hello:'world']
}
}
consumes で 受け取るデータの MIME Type を指定、produces で 返すデータの MIME type を指定しています。
それでは、変更を保存して、サーバを起動。
$ ./gradlew run
curl を使って作動を確かめます。
$ curl -X POST "http://localhost:8080/item/" -d '{ "name": "mac mini", "price": 128000 }' -H "Content-Type: application/json"
{"hello":"world"}
サーバを起動したコンソールの方に、POSTした json がSTDOUTされています。
{ "name": "mac mini", "price": 128000 }
サーバで受け取ったのは contents について調べてみます。 さらに ItemController を修正:
package myapp
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Post
import io.micronaut.http.annotation.Body
@Controller("/item")
class ItemController {
@Post(uri="/", consumes=["application/json"], produces="application/json")
def index(@Body def contents) {
println "${contents.getClass()} / ${contents}"
[hello:'world']
}
}
再度サーバを起動して、curl で作動確認。
$ ./gradlew run
$ curl -X POST "http://localhost:8080/item/" -d '{ "name": "mac mini", "price": 128000 }' -H "Content-Type: application/json"
{"hello":"world"}
サーバを起動したコンソールの方を確認します。
com.fasterxml.jackson.databind.node.ObjectNode / { "name": "mac mini", "price": 128000 }
となりました。
つまり、サーバ側で受け取った contents は com.fasterxml.jackson.databind.node.ObjectNode のインスタンスです。 したがって、name 値や price 値を取り出すには、以下のようにして取り出せます。
contents.name.textValue()
contents.price.intValue()
curl でうまくいったので、今度は ブラウザ上から jquery を使って意図通り作動するか試してみます。
以下のような index.html を準備.
<html>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script>
$(function() {
var contents = JSON.stringify({
name: 'MacMini',
price: 128000});
$.ajax({
url: 'http://localhost:8080/item/',
type:'post',
contentType:'application/json',
data: contents,
dataType:'json',
success: function (data) {
console.log('OK: '+JSON.stringify(data));
},
error: function (xhr) {
console.log("err: " + xhr);
}
});
});
</script>
</body>
</html>
これをブラウザ(chrome)で実行して、コンソールを見ると:
Access to XMLHttpRequest at 'http://localhost:8080/item/' from origin 'null' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
CORS がなんとか、というエラーが出ている。 サーバ側でクロスオリジンを許可する必要があるらしい。
自分の雑な理解では、サーバが返すヘッダで Access-Control-Allow-Origin: * を含めることでクロスオリジンが通るようになるはず。
Micronaut ではこの設定は src/main/resources/application.yml に cors の設定を追加すればよい。
micronaut:
application:
name: myapp
server:
cors:
enabled: true
この設定をした上で、再度 ./gradlew run を実行して、ブラウザをリロード:
今度は意図通りコンソールにサーバから来た json 表示されました。
OK: {"hello":"world"}
CORS の部分でつまづきましたが、なんとか HTML 上の javascript から Micronaut に json を POST して json を受け取る作動、できました。