LambdaでS3にアップロードされが画像をサムネイルにしてみた。

S3に画像をアップロードしたらLambdaでサムネイルを生成する(node-imagemagick)を参考にして作ってみた。
こっちはバケット2つ用意してたんだけどバケット1個でやりたかったので試行錯誤してみた。

コードは↓

S3のバケットのoriginフォルダにアップロードされたら、imagesフォルダにリサイズした画像を保存する。

手順は「Create a Lambda function」のボタンから作成。
1つもLambdaファクションがない場合は「Get Started Now」のボタンがあるからそれを押す。
そしたら予め作られてるテンプレートがあるからそれを選択するか、空の状態からやるなら下に「Skip」がある。

スクリーンショット 2015-11-12 18.23.44
関数名を決めて、説明文はあってもなくてもいい。
関数を作成するときの言語を決める。
スクリーンショット 2015-11-12 18.26.03
関数はエディタでその場で作成するか、ファイルをアップロードするか、S3にあるファイルを使うか選べる。
とりあえず今回はエディタで作ってみた。

スクリーンショット 2015-11-12 18.26.18
Handerの設定は基本的にテンプレートを使うなら変更しないでも良い。
Roleは作ってないならcreate new roleからlambda_s3_exec_roleを選択するとIAM Management Consoleに飛ばされる。
基本このままで作成。
そしたら自動的に作成したRoleが割り当てられる。
メモリはアップロードする画像サイズにもよると思うけど、スマホの画像とかをアップロードするなら192MBぐらいはほしいかな。
実行時間も画像サイズに影響するのでサイズによって調整する。
後でメモリと実行時間の変更も可能なのでとりあえず適当に設定しても大丈夫。

Nextボタンおしたらプレビューが表示されるのでそのまま作成ボタン押せば完成。

あとは、Event sourcesタブでAdd event sourceからS3の条件を指定すればアップロードされた時にLambda関数が実行されてサムネイルが作成される。

Event sourcesは別関数作っても同じ条件だと設定できないらしく、リサイズするサイズを変えた複数のlambda関数を作ってもダメだった。
一個の関数内で複数のリサイズを実行するか、リサイズごとにフォルダ分けしたらいけるかもしれない。
まぁそのへんはまたやってみようと思う。

技術ネタ書くなんて久しぶりじゃないんだろうか

node.jsでIPアドレスを取得する(2)

もう半年以上前にNode.jsでクライアントのIPアドレスを取得するを書いた。
まぁ別にあれでもちゃんと動いてるんだけど、もうちょっとコードがコンパクトにならないかなぁっとちょっとだけ頑張ってみた。

三項演算子のネストでコードをコンパクトにしてみた。
人によっては、大嫌いな書き方なんだろうけど、ある程度可読性があるようにちゃんと改行してワンライナーにはしてない。

ブログ内にコード書いてもいいんだけど、改変したりとかするんだったらGitHubにコード載せたほうがいいかと思ってGistに書いた。

node.jsでプロセス分割

ちょっと1プロセスで使用できるメモリサイズの限界を超えてしまったので、
マルチプロセスで使用するメモリサイズを分割しようと思っていろいろとドキュメント読んだりしたけどイマイチよくわからなかった。

最初ははじめてのNode.js:マルチプロセスアプリケーションを作成するを見たんだけども、書いてる内容はリクエストの負荷分散の内容だったので殆ど参考にならず。

処理を分割したいだけでリクエストを割り振りたいわけじゃなかったので、
参考サイトのようにnet.createServer()を使う必要がなかった。
とりあえずchild_processモジュールをロードしてfork()することは分かった。

node本家のドキュメントを見て、いろいろとごにょごにょしてみたもののさっぱりうまくいかなかった。

親プロセスでリクエストに対して呼び出す子プロセスを切り替えたかったので
子プロセスにリクエストとレスポンスのオブジェクトをsend経由で渡したら動かないし…

そして、エラーをよくよく見たら、messageはオブジェクトでもいけるけど
なぜか一旦json形式のテキストデータに変換されるため、
functionを持つオブジェクトをmessageで受け渡しできない。

パフォーマンス優先で行きたかったので、子プロセスでレスポンスを返せるのが一番だったのだが…
仕方ないので、子プロセス側から親プロセスに実行結果を戻すようにして何とか完成。
プロセス間のデータはそれほど大きくないからオーバーヘッドもそれほど気にならない感じ。

そうはいっても大量のアクセスが来た場合にどうなるかはまだ不明だしなぁ。
とりあえずはこれでうまく行ってくれればと願うばかり。

Node.jsでクライアントのIPアドレスを取得する

最近Node.jsをまじめにやり始めました。

クライアントのIPアドレスが取りたかったので、ググったり聞いたりして
結局行き着く先はStackOverflowのQ&A
How can I get the user’s IP address using Node.js?

リクエストオブジェクトのheaders[‘x-forwarded-for’]に入ってるらしいんだけども
ブラウザによっては入ってない感じだったので、回答の2つ目をそのままつかってみることに

var ip = req.headers['x-forwarded-for'] || 
     req.connection.remoteAddress || 
     req.socket.remoteAddress ||
     req.connection.socket.remoteAddress;

これである程度取れるようになったんだけど、特定のアクセスの場合
req.socket.remoteAddressでエラーで止まっちゃう。
そもそも、リクエストオブジェクトにsocketプロパティなんてない場合もあるようで(´・ω・`)
javascriptの性質上、オブジェクト直下のプロパティにアクセスするだけなら
undefinedが返ってくるのでエラーにはならないんだけど
undefinedに対してプロパティアクセスしたら例外エラーになってしまう。
サーバーが止まってしまうのも困るのでこれじゃあ使いものにならないのでエラーハンドリングちゃんとするように変更してみた。

    if(request.headers['x-forwarded-for']) {
        return request.headers['x-forwarded-for'];
    }
    
    if(request.connection && request.connection.remoteAddress) {
        return request.connection.remoteAddress;
    }
    
    if(request.connection.socket && request.connection.socket.remoteAddress) {
        return request.connection.socket.remoteAddress;
    }
    
    if(request.socket && request.socket.remoteAddress) {
        return request.socket.remoteAddress;
    }
    return '0.0.0.0';

プロパティが存在するか確認してあったら返すように変更。
4つのプロパティのどれもなかったらどうしようもないので’0.0.0.0’を返して、エラーでサーバーが止まらないように
try-catchしてもいいんだけど、順番的にconnection.socketが評価されずに終わったりするのも切ないし
1こずつtry-catchをネストするのも深くて読みにくくなるしこれでいいんじゃないかな。

他のプロパティに入ってるって知ってる人はこっそり教えて下さい。

追記:
もう少しちゃんと書いた記事はこちら

Node.jsの勉強会に行ってきた。

今日は知り合いが主催するNode.jsの勉強会に行ってきた。

Node.jsのインストールから
Node.jsのフレームワークのことまで。

基本使い方の勉強会だったけど
ユースケースを知りたいなぁ。

何に使うならNode.jsがいいんだろうか。
勉強会で聞いた話ならRESTfulなもので大量のリクエストをさばく必要があるときは
Apache+PHPとかよりも有利なのかな。

使い方の勉強よりも長所短所が知りたい気持ちが大きくなった