読み書きプログラミング

日常のプログラミングで気づいたことを綴っています

MeteorのHTTPはcontentにBufferも受け付ける。

Meteor.methodsでTwitterに写真付きstatusの投稿をするコードを書きました。
最初非同期で書いたのですが、そしたらクライアント側で投稿が成功したかどうか確認するタイミングが得られませんでした。
で、Meteorのhttpパッケージを使って書き直したのですが、contentの仕様がドキュメントではStringだったので色々変換してみたもののうまくいきませんでした。
Meteorはgithubオープンソースになっているので、httpパッケージの中身を見たところ、npmのrequestパッケージを同期化していて、contentにはStringだけじゃなくBufferも使えることがわかりました。
multipartを文字列とBufferの配列で構成し、Buffer.concatしてcontentに渡すとうまくいきました。

OAuth = Meteor.require('oauth').OAuth

updateWithMedia = (keys, params, fileExtension) ->
    boundary = "--#{Math.random().toString().slice 2}"
    url = 'https://api.twitter.com/1.1/statuses/update_with_media.json'
    oauth = new OAuth 'https://api.twitter.com/oauth/request_token', 'https://api.twitter.com/oauth/access_token', keys.consumer_key, keys.consumer_secret, '1.0', null, 'HMAC-SHA1'
        
    content = ("--#{boundary}\r\nContent-Disposition: form-data; name=\"#{key}\"\r\n\r\n#{value}\r\n" for key, value of params when key isnt 'media[]').join ''
    if params['media[]']?
        content += "--#{boundary}\r\nContent-Disposition: file; name=\"media[]\"; filename=\"media.#{fileExtension}\"\r\nContent-Type: image/#{fileExtension}\r\n\r\n"
        buffers = [new Buffer content]
        buffers.push params['media[]']
    else
        buffers = [new Buffer content]
    buffers.push new Buffer "\r\n--#{boundary}--\r\n"
    buffer = Buffer.concat(buffers)

    headers =
        'Accept': '*/*'
        'Connection': 'close'
        'User-Agent': 'mimiaka/0.1'
        'Authorization': oauth.authHeader(url, keys.access_token_key, keys.access_token_secret, 'POST')
        'Content-Type': "multipart/form-data; boundary=#{boundary}"
        'Host': 'api.twitter.com'
        'Content-Length': buffer.length
    try
        HTTP.post url,
            content: buffer
            headers: headers
    catch e
        e.response