Movable Type 6のData APIで再構築する
背景
- 社内のMovable Typeで複数のブログを束ねて表示するまとめサイトのウェブサイトを作りました。
- 諸事情あって上位のウェブサイトではなくブログの中にウェブページを作ってる。
- ウェブページのために、新たに専用のCSSやウィジットを作成している。
- 事情はよくわからないが、新しく作ったウェブページだけ毎日早朝に壊れる。
どうするか
- サーバに手出しできないので、Data APIを使って外部から再構築をしなおしてみることにした。
確認手順
- 再構築(Publish: entries)のEndpointは
GET https://your-host/your-mt-api.cgi/v1/publish/entries
なので以下のようなリクエストを投げる。- {entry_id}は、ブログ記事もウェブページも同じ体型のIDで、mt.cgiの表示オプションから表示項目のIDをチェックすると確認することが出来る。
- 今回は1記事だけ対象だけどカンマ区切りで複数指定することも可能
- 再構築はすぐに終わらないので、Response HeaderのX-MT-Next-Phase-URLにセットされるURLにアクセスすると最新ステータスを確認することが出来る。
- {entry_id}は、ブログ記事もウェブページも同じ体型のIDで、mt.cgiの表示オプションから表示項目のIDをチェックすると確認することが出来る。
GET https://your-host/your-mt-api.cgi/v1/publish/entries?ids={entry_id}
- ただし再構築をするためには認証が必要。
- cronで実行すること考えているので、Loginページに飛んだりしても困る。よってauthenticationを利用する。Endpointは
POST https://your-host/your-mt-api.cgi/v1/authentication
となる。- Authentication: authenticationメソッドはRequest Bodyに認証情報をセットしてPOSTする。
- ResponseでaccessTokenが返ってくるので、publishするときにヘッダにセットしてあげる。
- cronで実行すること考えているので、Loginページに飛んだりしても困る。よってauthenticationを利用する。Endpointは
- responseのstatusがCompleteになるまでX-MT-Next-Phase-URLにセットされているURLにアクセスしないと再構築が完了しない。
- とりあえずAdvanced REST clientを使って出来たので、この手順をコード化する。
ソース
- JavaScriptのライブラリがあるのだがcronで実行するつもりなので、Groovyで書いてみた。
- いやただGroovyで書きたかったんですけどね。。。
- mt_rebuild.groovy
簡単な説明
- Apache HttpClient使ってます。
@Grab('org.apache.httpcomponents:httpclient:4.3.3') import org.apache.http.* import org.apache.http.client.* import org.apache.http.client.params.* import org.apache.http.client.methods.* import org.apache.http.client.entity.* import org.apache.http.impl.client.* import org.apache.http.message.*
- HttpClientの新しいバージョンではRequest Headerの作り方が変わってた。
- .setDefaultHeaders()というのを使うらしい。
def uri = "${api_host}/${api_base}/authentication" HttpPost post = new HttpPost(uri) List<Header> headers = new ArrayList<Header>() headers.add(new BasicHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")) HttpClient httpclient = HttpClientBuilder.create().setDefaultHeaders(headers).build()
- POSTのRequest BodyはArrayListにaddしていく。
List<NameValuePair> params = new ArrayList<NameValuePair>() params.add(new BasicNameValuePair("username", "foo_uid")) params.add(new BasicNameValuePair("password", "foo_pass")) params.add(new BasicNameValuePair("remember", "0")) params.add(new BasicNameValuePair("clientId", "mt_rebuild")) post.setEntity(new UrlEncodedFormEntity(params))
- ResponseをJsonSlurper()に食わせて、accessTokenを取得。
entity = new JsonSlurper().parseText(response.getEntity().getContent().text) return entity.get("accessToken")
- publishではX-MT-Authorizationに取得したaccessTokenをセットして、GET。(GETなんで簡単)
headers.add(new BasicHeader("X-MT-Authorization", "MTAuth accessToken=${accessToken}"))
- responseのstatusがCompleteになっていない場合は、X-MT-Next-Phase-URLにセットされているURLにアクセスする。
response = httpclient.execute(get) if (response.statusLine.getStatusCode() == 200) { entity = new JsonSlurper().parseText(response.getEntity().getContent().text) response.getHeaders('X-MT-Next-Phase-URL').each { if (entity.get("status") != "Complete") { rebuild_next(accessToken, "${api_host}/${api_base}${it.value}") } } }
- statusがCompleteになるまでX-MT-Next-Phase-URLを呼び出す。
def rebuild_next(accessToken, uri) { HttpGet get = new HttpGet(uri) List<Header> headers = new ArrayList<Header>() headers.add(new BasicHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")) headers.add(new BasicHeader("X-MT-Authorization", "MTAuth accessToken=${accessToken}")) HttpClient httpclient = HttpClientBuilder.create().setDefaultHeaders(headers).build() response = httpclient.execute(get) if (response.statusLine.getStatusCode() == 200) { entity = new JsonSlurper().parseText(response.getEntity().getContent().text) response.getHeaders('X-MT-Next-Phase-URL').each { if (entity.get("status") != "Complete") { rebuild_next(accessToken, "${api_host}/${api_base}/${it.value}") } } } }
これで再構築できた。
自由にいじれるサーバばかりではないのでAPIがあるといいですね!