Redmine の wiki を、HTTP のクライアントプログラムで更新する方法を考えてみた。言語は何でもいいが、ここでは Groovy を使ってみた。
====
例えば、以下のようなコードで、
class Test { def static content = """\ h1. 大見出し なんとかこんとか ${ new Date().toString() } """ public static void main(args) { new RedmineWikiRewriter() .login("user001", "password") .startEdit("project001", "Http_post_test") .saveEdit(content) } }下の画像のように、wiki ページが更新されるような クラス RedmineWikiRewriter を考えてみる。
- login() では、与えられたユーザ名とパスワードでログインして、Redmine から返されるクッキーを保持する。
- startEdit()は、指定のプロジェクトの指定の wiki ページを開く。これはページのバージョンを得るために必要
- saveEdit()は、wiki コンテンツをマルチパートの HTTP POST で送信する
class RedmineWikiRewriter { def static UTF8 = Charset.forName("UTF-8") def HTTPBuilder http = new HTTPBuilder('http://localhost:3000/') def redmineSession def authenticityToken def contentVersion def project def wikiEntry public RedmineWikiRewriter login(String username, String password) { http.get(path : '/login', query : [q:'Groovy'] ) { resp, reader -> authenticityToken = reader.BODY.DIV.DIV .findAll { it.id="login-form" }.depthFirst() .grep { "authenticity_token"== it.@name.toString() }[0] .@value.toString() } http.request(POST) { uri.path = '/login' send URLENC, [ username:username, password:password, authenticity_token:authenticityToken] response.success = { resp -> redmineSession = resp.getAllHeaders() .find {"Set-Cookie"==it.name.toString()} .value.split(";") .find {it.toString().startsWith("_redmine_session")} } } this } RedmineWikiRewriter startEdit(String project, String wikiEntry) { this.project = project this.wikiEntry = wikiEntry http.request(GET) { resp -> uri.path = "/projects/"+project+"/wiki/" + wikiEntry + "/edit" headers.'Cookie' = redmineSession response.success = { res, reader -> contentVersion = reader .depthFirst() .grep{"content_version"==it.@id.toString() }[0] .@value.toString() } } this } void saveEdit(String content) { DefaultHttpClient httpclient = new DefaultHttpClient(); def uri = "http://localhost:3000/projects/"+ project +"/wiki/" + wikiEntry HttpPost httppost = new HttpPost(uri) httppost.addHeader('Cookie', redmineSession) MultipartEntity mpe = new MultipartEntity( HttpMultipartMode.BROWSER_COMPATIBLE, "----WebKitFormBoundaryfmexSJQ5daIXdA04", UTF8); addPart(mpe, "commit", "Save"); addPart(mpe, "project_id", project); addPart(mpe, "action", "update"); addPart(mpe, "_method", "put"); addPart(mpe, "authenticity_token", authenticityToken) addPart(mpe, "id", wikiEntry) addPart(mpe, "content[text]", content) addPart(mpe, "content[version]", contentVersion) addPart(mpe, "controller", "wiki") httppost.setEntity(mpe); httpclient.execute(httppost); } static void addPart(MultipartEntity entity, String name, String value) { entity.addPart(name, new StringBody(value, UTF8)); } }■ 振り返り
- saveEdit() でも HttpBuilder を使いたかったが、なぜか思うように動かない。仕方なく、DefaultHttpClient を使用
- wiki エントリの新規作成でも動くかどうかは未確認
- たかだかこれくらいのコードでも、やってみると予想外に難しい。Redmine の Rubyコードを読んだり、HTTP の Header を調べたりいろいろ手間がかかった。あと multipart の POST も意外と難しい
- 仕組みはだいたい分かったので、他の言語でも試してみたい。もともとやりたかったのは、Excel 上の VBA からデータを整形して wiki に載せるというのを自動化すると言う事だった。
0 件のコメント:
コメントを投稿