node.jsでライブドアブログに記事投稿する方法です。
MEANスタックアプリ制作で一番時間かかったんじゃないの、これ…
まず公式サイトの説明を読む。
API のルートエンドポイントは、この API における「サービス文書」を提供する URL です。これはブログの設定>API Keyに表示されている URL になります。
具体的には以下のような URL です。https://livedoor.blogcms.jp/atompub/<blog_id>
ふむ。GET/POSTでこのエンドポイント使えばいいのね。
現在以下の認証方法が提供されています。
Basic 認証
WSSE 認証
ふむふむ。WSSE認証のほうがパスワードが平文で送られないからセキュリティ的に安全っぽい。こっちを採用かな。
で、Perlでの書き方がコレ。
1 2 3 4 5 6 |
my $wsse = sprintf('UsernameToken Username="%s", PasswordDigest="%s", Nonce="%s", Created="%s"', $username, encode_base64($digest, ''), encode_base64($nonce, ''), $time ); |
うん、全然伝わってこないわwPerl読めねぇしw
で、「ライブドア API 投稿」でググる。
以下のサイトがわかりやすかった。ありがとうございます。
猫力「LivedoorブログへAtomPubとPHPで外部投稿」
WSSE認証のことはわからなかったけど、PHPではこんな風に書くみたい。
1 2 3 4 5 6 7 8 9 10 11 12 |
$url= 'https://livedoor.blogcms.jp/atompub/ブログID/article'; $title = 'テスト'; $text = '<p>テスト投稿です。</p>'; $cat = 'カテゴリ'; $body = '<?xml version="1.0"?>'. '<entry xmlns="http://www.w3.org/2007/app" xmlns:atom="http://www.w3.org/2005/Atom">'. '<title type="text/html" mode="escaped">'.$title.'</title>'. '<content type="application/xhtml+xml">'.$text.'</content>'. '<category term="'.$cat.'"/>'. '</entry>'; |
ほー、記事を投稿する場合は「/article」がエンドポイントになるのかー。
いい感じに情報収集できた。
本題のnode.jsで目的のソースコード探す。→ヒットせず。→想定内(泣)
で、ここからトライ・アンド・エラーで頑張ってみることに。
まずはWSSE認証のモジュールを探す。
あった!
bouzuya/node-wsse
日本人だ!多分天才。
以下の様な書き方をすればいいと。ふむ。
1 2 3 4 5 |
var token = wsse({ username: 'bob', password: 'taadtaadpstcsm' }); // you can use `nonceBase64` option. it encodes the nonce to base64 in header. // 'UsernameToken Username="bob", PasswordDigest="quR/EWLAV4xLf9Zqyw4pDmfV9OY=", Nonce="ZDM2ZTMxNjI4Mjk1OWE5ZWQ0Yzg5ODUxNDk3YTcxN2Y=", Created="2003-12-15T14:43:07Z"' console.log(token.getWSSEHeader({ nonceBase64: true })); |
スゴイ、超便利。
WSSE認証のやり方がわかったところで、GETできるか試す。
ここから最初の泥沼。
泥沼の詳細を書きなぐりたかったが我慢した。
いろいろやった結果、以下のスクリプトを試す。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
var request = require('request'); var wsse = require('wsse'); var token = wsse({ username: 'ID', password: 'APIKEY' }); var options = { url: 'https://livedoor.blogcms.jp/atompub/ブログID/article', method: 'GET', headers: { 'Authorization': 'WSSE profile="UsernameToken"', 'X-WSSE': token.getWSSEHeader({nonceBase64:true}) } }; request(options, function(error, response, body) { console.log(body); }); |
記事が取れた〜。そしたら次はPOSTで投稿してみるか。
で、書いたのが以下のスクリプト。
XMLでPOSTしたいので、ヘッダーに「Content-Type」を追加。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
var request = require('request'); var wsse = require('wsse'); var token = wsse({ username: 'ID', password: 'APIKEY' }); var title = 'タイトル'; var text = '本文<br />や<img />みたいにタグはしっかりと閉じる'; var rawData = '<?xml version="1.0" encoding="UTF-8"?>' + '<entry xmlns="http://www.w3.org/2007/app" xmlns:atom="http://www.w3.org/2005/Atom">' + '<title>'+ title + '</title>' + '<content type="application/xhtml+xml">' + text + '</content>' + '</entry>'; var options = { url: 'https://livedoor.blogcms.jp/atompub/ブログID/article', method: 'POST', body : rawData, headers: { 'Authorization': 'WSSE profile="UsernameToken"', 'X-WSSE': token.getWSSEHeader({nonceBase64:true}), 'Content-Type': 'application/xml' } }; request(options, function(error, response, body) { console.log(response.statusMessage); }); |
「Bad Request」
え?なんで?
仕様通りに書いてんじゃん。うーむ…
ここから2回目の泥沼。
「Content-Type」の変更、「node-request」のGitとにらめっこして、記述をいろいろと変えてみるもNG。何やってもダメ。
こりゃアカンと思い、一度寝かせて別機能の実装をしました。
で、別機能の実装も一段落したので、こちらに復帰。
原点に戻って、もう一度APIの仕様を確認するため、ライブドアの公式サイトへ。
スクロールしようと思ったが、目がとまる。
こちらは2013年12月にリリースされた新しいAtomPub APIについての技術文書です。
※旧AtomPub APIについてはこちら
※旧AtomPub APIについてはこちら
「※旧AtomPub APIについてはこちら」
…もちろん、最初のときも読みましたよ、リンク先(サラッとですが)
でも「旧AtomPUBでしょ?新しい方がいいに決まってんじゃん。これ使わないよね。」とスルーしていました。
ただ……状況が状況だけにワラをもすがる思いでもう一度読んでみると、これが。
ユーザが使用可能なリソースURIには以下のものがあります。
(このリソースURIは、今後増減する可能性があります。)http://MEMBER_PROVIDER.blogcms.jp/atom/BLOG_PROVIDER/BLOG_NAME/article (記事のコレクションURI)
・
・
BLOG_PROVIDERは対象のブログが所属しているプロバイダ名、BLOG_NAMEは対象としているブログのblog_name(例:http://blog.livedoor.jp/staff/ の場合はstaff)です。
ただし、ユーザと対象のブログが所属するプロバイダが同じ場合、BLOG_PROVIDERはプロバイダ名ではなく「blog」になります。
例: http://livedoor.blogcms.jp/atom/blog/staff/article/000000
あれ、よく見るとエンドポイントが違う。これってまさか…
というわけでスクリプトを以下に変更。変えたのはURLの記述のみ。
https://livedoor.blogcms.jp/atompub/ブログID/article
↓
http://livedoor.blogcms.jp/atom/blog/ブログID/article
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
var request = require('request'); var wsse = require('wsse'); var token = wsse({ username: 'ID', password: 'APIKEY' }); var title = 'タイトル'; var text = '本文<br />や<img />みたいにタグはしっかりと閉じる'; var rawData = '<?xml version="1.0" encoding="UTF-8"?>' + '<entry xmlns="http://www.w3.org/2007/app" xmlns:atom="http://www.w3.org/2005/Atom">' + '<title>'+ title + '</title>' + '<content type="application/xhtml+xml">' + text + '</content>' + '</entry>'; var options = { // ここのURLを変更 url: 'http://livedoor.blogcms.jp/atom/blog/ブログID/article', method: 'POST', body : rawData, headers: { 'Authorization': 'WSSE profile="UsernameToken"', 'X-WSSE': token.getWSSEHeader({nonceBase64:true}), 'Content-Type': 'application/xml' } }; request(options, function(error, response, body) { console.log(response.statusMessage); }); |
「Created」が返ってくる!!
ブログを確認。おー投稿できてるー!
まさか旧AtomPUBで記事投稿できると思いませんでした。ひとまず、こちらの方法を採用です。
(こっちのAtomPUBは予告なく提供を終了する場合があるらしい、いつまで使えるのかなw)
あー、でも新AtomPUBの記事投稿ができてないままだー。
こっちはどうすればいいんだろう。
情報求む(´Д`υ)