Home About
Micronaut , JQuery , JavaScript

Part 2: テスト用に json を POST して json を返す ウェブサービスをつくる

デバッグのためのテストとして json を POST して json を返すウェブサービスを Micronaut でつくる話。

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="/", produces="application/json")
    def index(@Body String jsonContents) {
        println jsonContents
        [hello:'world']
    }
}

変更を保存して、サーバを起動。

$ ./gradlew run

curl を使って作動を確かめます。

$ curl -X POST "http://localhost:8080/item/" -d '{ "name": "mac mini", "price": 12800 }' -H "Content-Type: application/json"
{"hello":"world"}

サーバを起動したコンソールの方に、POSTした json がSTDOUTされています。

{ "name": "mac mini", "price": 12800 }

とはいえ、サーバで受け取ったのは json 文字列なので、これをサーバ側 オブジェクトに変換しましょう。 それでは、さらに ItemController を修正:

package myapp

import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Post
import io.micronaut.http.annotation.Body
import org.json.JSONObject

@Controller("/item")
class ItemController {
    @Post(uri="/", produces="application/json")
    def index(@Body String jsonContents) {
        def obj = new JSONObject(jsonContents)
        println "- name=${obj.name}"
        println "- price=${obj.price}"
        [hello:'world']
    }
}

org.json.JSONObject を import したので、build.gradle の dependencies に以下を追加

implementation group: 'org.json', name: 'json', version: '20210307'

再度サーバを起動して、curl で作動確認。

$ ./gradlew run
$ curl -X POST "http://localhost:8080/item/" -d '{ "name": "mac mini", "price": 12800 }' -H "Content-Type: application/json"
{"hello":"world"}

サーバを起動したコンソールの方を確認して、意図通りオブジェクト化されたか確認しましょう。

- name=mac mini
- price=12800

うまくいきました。

jquery で試す

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 を受け取る作動、できました。