【Javascript】さわってみた【node.js】
2012-01-27 03:16:13 Fri
■誤解していたこと
node.js = サーバサイド javascript = サーバ機能 = 動的HTML
みたいに思っていました。
実はそれは一機能。
コードにするとこれ。
var http = require('http');
http.createServer(
function (request, response) {
}).listen(8124);
他の使い方としてはshellからnodejsを読んでそこで他サイトのHTMLをスクレイピングとか…
まあもう色々できます。
node XXXX.js
みたいなコマンドでnode.jsを実行できます。
このときXXXX.jsが上述のようなコードのjsファイルだとサーバアプリとして動くわけです。
■サーバ機能をそれなりに使うとして
node.jsといえばwebsocket的な話になりますがそちらはまだぜんぜんわかりません。
なので普通のWebサーバ的に。
上述のコードではポート8124でリクエストを待ち受けることになります。
まずやりたくなるのがURLによる処理の割り振り。
どうやってやるのか結局わからなかったのでURLを解析して…みたいな処理にしてみました。
あ、POST試していませんでした…。
// url.parseの第二引数をtrueにすることでurl.queryを連想配列で取得できる
var url_parse = require('url');
var url = url_parse.parse(request.url, true);
これでURLをパースすることができます。
マニュアル参照。http://nodejs.jp/nodejs.org_ja/api/url.html
とりあえず上のparseをするとクエリストリングのパラメータに名称でアクセスして値を取得できるようになります。
console.log(url.pathname);
console.log(url.query);
console.log(url.query['parameter']);
次に外部においたファイルを読み込む。
ついでにJSONとして。
res.writeHead(200, {'Content-Type':'application/json; charset=utf-8'});
var read = fs.createReadStream('./data/sample.json', {bufferSize: 32});
read.on('data', function (data) { res.write(data); })
.on('end', function () { res.write('\n'); res.end(); })
.on('error', function (exception) { console.log('r: error'); })
.on('close', function () { console.log('r: colse'); })
.on('fd', function (fd) { console.log('r: fd'); });
こんな感じ。
ファイルパスはこんな感じです。
※相対パス指定していますが、これってnodeプロセスを実行しているコンソールのいるパスがカレント?単に読み込まれたjsファイルのある場所をカレントとしているの?はたまた?
この処理はjsのメリットとして言われているノンブロッキング処理です。
I/Oを待ちません。イベント駆動です。
どうしてもI/Oをまつのであれば、endイベントで後続処理をコールバックするようにします。
【javascript】iframeとハッシュタグを使ってクロスドメインでデータ渡し
2011-09-30 23:52:22 Fri
概要
下記は、HTML5が利用できるのであれば、postMessageを利用すれば解決できます。
HTML4などを利用する人が対象です。
やろうとしていることは、親ウィンドウで異なるドメインのHTMLをiframeに読みこみ、
異なるドメイン内で取得した値を親ウィンドウに伝達させることです。
なお、この方法ではハッシュタグを使っているため、
javasciptでのオブジェクトなどは渡せず、
外部通信が発生しているため個人情報や機密情報も渡すことはできないと考えていて良いかと思います。
そもそもなぜこんなことをやろうとしたかというと、
GoogleAppEngine上で会員のログイン処理を作ることになり、
そのサイトは独自ドメインを割り当てています。
しかし、2011/09/30 23:18:55現在、GoogleAppEngineで独自ドメインにてSSLを使うことができません。
2011年の後半に独自ドメインでもSSLを利用できるようになるようですが、現在のところは公式にアナウンスされておらず、GoogleAppEngineのドメインであるappspot.comのみでSSLを利用できます。
という制限があるとは言えども、appspot.comのドメインが表に出るのはまずいのです。
そこで、親ウィンドウは独自ドメイン、ログイン処理を行うドメインはSSL通信でのappspot.comドメインといった形をとることにしました。
こうすれば、ブラウザのロケーションバーでは独自ドメインでのアクセスのみに見せかけることができます。
なお、独自ドメインもappspot.comドメインも同じGoogleAppEngine上のアプリケーションで処理をするにもかかわらず、
ドメインが異なるためクライアントのブラウザではクロスドメインの制限が発生してしまいます。
appspot.comのログイン処理で認証に成功して発行された認証キーを独自ドメインへ伝達し、
独自ドメインから認証キーをリクエストさせてログイン状態にさせればひとまず独自ドメインである程度のセキュリティを確保してログイン処理をすることができます。
やり方
長々と書いてしまいましたが、この記事がすごくわかりやすいです。
下記のようにHTMLがあり、
1.html内のiframeで2.htmlを読み込み、
2.html内のiframeで3.htmlを読み込む。
1.htmlと3.htmlはfooドメインで同じドメインのため、
3.html内のjavascriptからは、window.parent.parentで参照でき、
さらに同一ドメインのためwindow.parent.parent.*にアクセスすることができます。
というだけのことです。
2.htmlから1.htmlのwindow.parent.myfunctionのようにプロパティにアクセスすると
クロスドメイン間でwindowを操作しようとしたため、ブラウザ側で制御されてアクセスすることができません。
- fooドメイン 1.html
- barドメイン 2.html
- fooドメイン 3.html
なお、概要のログイン処理の例に当てはめると次のようになります。
- 独自ドメイン ログインページ
- appspot.comドメイン ログイン画面本体
- 独自ドメイン 値伝達のためのページ
簡単にHTMLを書いてみます。
HTML5の記述だからpostMessage使えっていうのはなしで。。。
あと、記述がVTLですが、HTMLにしても表示が変なだけで動くと思います。
ドメインは適宜変更して、1と3は同じ、2は異なる、ところにおいてください。
localhostで動作させるならC:\Windows\System32\drivers\etc\hostsとかを適当に変更するといいと思います。
1.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset=utf-8 />
<title>Test</title>
<script src="/common/js/jquery.js"></script>
<script type="text/javascript">
function send(arg){
alert(arg.substr(1));
}
</script>
</head>
<body>
#if($message)
$message
#end
<iframe src="http://local.isann.info:8888/second" id="parent">iframe</iframe>
</body>
</html>
2.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset=utf-8 />
<title>Test</title>
<script src="/common/js/jquery.js"></script>
<script type="text/javascript">
</script>
</head>
<body>
#if($message)
$message
#end
<iframe src="http://localhost:8888/third#$param">iframe</iframe>
</body>
</html>
3.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset=utf-8 />
<title>Test</title>
<script src="/common/js/jquery.js"></script>
<script type="text/javascript">
$(document).ready(function() {
window.parent.parent.send(location.hash);
});
</script>
</head>
<body>
#if($message)
$message
#end
</body>
</html>
2.htmlの$paramというハッシュタグの部分がクロスドメイン間を超えて1に伝達されます。
もちろん、2.htmlはiframe内なので2で処理して最後に3.htmlを持つiframeのページを生成して
データを伝達させたりもできます。
ログイン処理では、2.htmlにあたるドメインでSSLでログイン処理を行い、
ログインが成功したときに3.htmlを持つiframeのページを生成して認証キーを1.htmlに伝達し、
1.html全体をPOSTするような作りにしました。
【HTML】イベント順序【Javascript】
2011-08-06 11:46:01 Sat
今更という感じもしますが、
HTMLドキュメントがロードされるときに実行されるイベントの順序について調べてみたのでメモ。
試していないから否定できない可能性はブラウザとHTTPサーバの組み合わせによってイベントの実行順序が変わるかもしれません。
なので実行環境は次のとおりです。
windows7 ultimate
apache 2.2
chrome 13
○index.html
○eventtest.js
bodyタグに記述したonload と javascriptファイルに記述したwindow.onloadは同一プロパティのようで上書きされるようです。
ためしにbody onload を記述して window.onload も記述したとき、 window.onloadの中身はbody onloadのinit関数への参照値となっていました。
body onloadを記述しない場合、window.onloadが上記の「body onload」のタイミングで実行されます。
また別記事にするつもりですが、
document.getElementByIdで要素を操作できるようになるのは「$(document).ready」以降となります。
「js naked」のタイミングでImageファイルをnewし、onloadした際には、onloadのコールバックファンクションではdocument.getElementByIdで要素を操作できるようです。
HTMLの要素にヘッド内などでどうしてもアクセスしたいという場合、javascriptでcreateElementするというこんなやり方もあるようですが…。
HTMLドキュメントがロードされるときに実行されるイベントの順序について調べてみたのでメモ。
試していないから否定できない可能性はブラウザとHTTPサーバの組み合わせによってイベントの実行順序が変わるかもしれません。
なので実行環境は次のとおりです。
実行環境
windows7 ultimate
apache 2.2
chrome 13
HTMLとJavascript
○index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>event test</title>
<script type="text/javascript" src="./common/js/jquery.js"></script>
<script type="text/javascript" src="./common/js/eventtest.js"></script>
<script type="text/javascript">
console.log('head');
function init(){
console.log('body onload');
console.log(window.onload);
}
</script>
</head>
<!--<body>-->
<body onload="init();">
<script type="text/javascript">
console.log('body');
</script>
hoge
</body>
</html>
○eventtest.js
console.log('js naked');
window.onload = function(){ console.log('window.onload'); }
$(document).ready(function() {
console.log('$(document).ready');
});
$(function(){
console.log('$(document).ready shortcut');
});
コンソールログ
js naked
head
body
$(document).ready
$(document).ready shortcut
body onload
function onload(event) {
init();
}
bodyタグに記述したonload と javascriptファイルに記述したwindow.onloadは同一プロパティのようで上書きされるようです。
ためしにbody onload を記述して window.onload も記述したとき、 window.onloadの中身はbody onloadのinit関数への参照値となっていました。
body onloadを記述しない場合、window.onloadが上記の「body onload」のタイミングで実行されます。
また別記事にするつもりですが、
document.getElementByIdで要素を操作できるようになるのは「$(document).ready」以降となります。
「js naked」のタイミングでImageファイルをnewし、onloadした際には、onloadのコールバックファンクションではdocument.getElementByIdで要素を操作できるようです。
HTMLの要素にヘッド内などでどうしてもアクセスしたいという場合、javascriptでcreateElementするというこんなやり方もあるようですが…。
【Javascript】JavascriptSDKを利用してFacebookにアクセスする
2011-06-24 01:23:02 Fri
追記2012/01/30 18:28:00
今更ですが、この記事の内容はもう古くなっております。
2011年10月頃にFacebookの認証API仕様が大幅に変更されました。
その対応を行っていないため、下記の内容はもう価値がない内容となっております。
他の方の記事を参考にしてください。
http://oauth.jp/facebook-oauth-migration
http://mbdb.jp/hacks/facebook/facebook-dev-change-20120101.html
こんなに互換性のない仕様変更が多いサービスはお金もらってないと互換性アップのための開発なんてやってられないですね。
twitterはなんだかんだいってAPIのレスポンスや振る舞いが変わっていても互換性を持ったバージョンアップなんですよね。
・JavascriptSDKを利用してFacebookにアクセスする
・Facebookへ外部サイトからアクセスする際の基本的知識について
・【Java】JavaでFacebookにアクセスする方法
・【Facebook】携帯電話でのアカウント認証をやり直す
1.初期化
→初期化はBODYタグの中でする。
HEADだとドキュメントの描画とは別スレッドで走ってしまい、
fb-rootのエレメントが生成されていない可能性があるため。
2.ログインでOAuth認証
※1
使用する権限を列挙しておく。
権限によって読めない書けないということがあるため、
やりたいことを実現するためにどんな権限が必要なのか事前に知っておく必要がある。
権限一覧はこちらを参照。
必要な権限を知るためにはhttp://developers.facebook.com/docs/reference/api/album/などobjectsのそれぞれを参照。
3.OAuth認証したアカウントのウォールに投稿してみる
こんな感じ。
urlで指定している「me/feed」はOAuth認証しているユーザのフィードを意味している。
methodの「post」で投稿を意味し、dataでパラメータを与えている。
他にも「user_id/feed」とかでもいける。
もちろん、ユーザーネーム(ユニークURL)でも大丈夫です。
なお、POSTできるメソッドは下記。(Publishingを参照)
http://developers.facebook.com/docs/reference/api/
PublishingのMethodは上記ソースのurl、Argumentsがdataになります。
権限に関してはDescriptionのリンクを参考にし、足りない場合はログイン時の権限を追加します。
常に決まったアカウントから投稿などする場合、事前にOAuth認証をしておいて、
アクセストークンを取得しておきます。
当然、そのアクセストークンはずっと使える必要があるので有効期限が必要ないように
次の権限をアプリケーションとして許可してもらう必要があります。
「publish_stream」「offline_access」
これでアクセストークンは無期限になるのですが、
(実質的には長期間であり無期限ではないのですが、便宜上無期限としておきます。アクセストークンが無効になった際を考えて、このアクセストークンは設定ファイルやデータベースなどにもっておいたほうが良いと思います。)
このアカウントがOAuth認証したFacebookアプリケーションを削除するとアクセストークンは無効になって
もう一度Facebookアプリケーションを登録しなおし、アクセストークンを取得しなおす必要があることに注意しないといけないです。
なお、アカウントではなく特定のアプリケーションやページから投稿などする場合は下記のApp LoginやPage Loginを参考にしてアクセストークンを取得します。
http://developers.facebook.com/docs/authentication/
しかし、、、無期限のアクセストークンをJavascriptなどクライアント側に埋め込むと誰でもそのアクセストークンを利用してそのアカウント情報を読み込んだり書き込んだりできるため、これらはサーバ側から行わないといけないです。
PHPやPythonなどは公式のSDKがあるので楽だと思います。
Javaでは、【Java】JavaでFacebookにアクセスする方法を参考にしてください。
JavascriptSDKとJavaライブラリのRestFBを組み合わせることでSSLなしの状態でも現在実現できました。
「●Facebookのセッションキーをもとにしてサーバ側でアクセストークンを取得する場合」を参照してください。
単純にユーザにログインしてもらってフィードに投稿するなどの処理であればJavascriptSDKのみで良いと思います。
JavascriptSDKを利用せずにFacebookのOAuth認証やるのはこちらがよくまとまっています。
このアクセストークンがあれば、サーバ側からでもFacebookにアクセスできます。
ただ、セキュリティ的なところが色々と気になってきますので、セッションキーをサーバに送信して、サーバ側でアプリIDとアプリシークレット(アプリの秘訣)をもとにしてアクセストークンを取得する上述のリンク先のやり方が良いと思います。
今更ですが、この記事の内容はもう古くなっております。
2011年10月頃にFacebookの認証API仕様が大幅に変更されました。
その対応を行っていないため、下記の内容はもう価値がない内容となっております。
他の方の記事を参考にしてください。
http://oauth.jp/facebook-oauth-migration
http://mbdb.jp/hacks/facebook/facebook-dev-change-20120101.html
こんなに互換性のない仕様変更が多いサービスはお金もらってないと互換性アップのための開発なんてやってられないですね。
twitterはなんだかんだいってAPIのレスポンスや振る舞いが変わっていても互換性を持ったバージョンアップなんですよね。
Facebookの関連記事
・JavascriptSDKを利用してFacebookにアクセスする
・Facebookへ外部サイトからアクセスする際の基本的知識について
・【Java】JavaでFacebookにアクセスする方法
・【Facebook】携帯電話でのアカウント認証をやり直す
JavascriptSDKを利用してFacebookにアクセスする
1.初期化
<body> <script type="text/javascript" src="http://connect.facebook.net/ja_JP/all.js"></script> <div id="fb-root"></div> <script type="text/javascript"> // Facebook JavaScript SDK の初期化。 FB.init({ appId : 'YOUR_APP_ID', status : true, // check login status cookie : true, // enable cookies to allow the server to access the session xfbml : true // parse XFBML }); ・ ・ ・ </script> </body>
→初期化はBODYタグの中でする。
HEADだとドキュメントの描画とは別スレッドで走ってしまい、
fb-rootのエレメントが生成されていない可能性があるため。
2.ログインでOAuth認証
$(document).ready(function() { loginCheck(init); }); function init(login){ if(login){ //ログインしている } else { //ログインしていない //ログインしてもらう FB.login(function(response) { if (response.session) { //ログイン成功 if (response.perms) { //パーミッションもOK // user is logged in and granted some permissions. // perms is a comma separated list of granted permissions alert('ログインOKで権限もOK'); } else { //パーミッションはNG // user is logged in, but did not grant any permissions alert('ログインOKで権限はNG'); } } else { //ログイン失敗 // user is not logged in alert('ログインNG'); } }, {perms:'manage_friendlists,publish_stream,offline_access'}); // 使用する権限を列挙しておく。※1 } } function loginCheck(fnk){ return FB.getLoginStatus(function(response) { if (response.session) { return fnk(true); } else { return fnk(false); } }); }
※1
使用する権限を列挙しておく。
権限によって読めない書けないということがあるため、
やりたいことを実現するためにどんな権限が必要なのか事前に知っておく必要がある。
権限一覧はこちらを参照。
必要な権限を知るためにはhttp://developers.facebook.com/docs/reference/api/album/などobjectsのそれぞれを参照。
3.OAuth認証したアカウントのウォールに投稿してみる
function post(){ var url = 'me/feed'; var method = 'post'; var data = { message: 'message' ,name: 'Name area' ,link: 'http://isann.blog2.fc2.com/' ,picture: 'http://hoge.com/hoge.jpg' ,caption: 'Caption area' ,description: 'Description area' }; var cbFnk = postNext; FB.api(url, method, data, cbFnk); }
こんな感じ。
urlで指定している「me/feed」はOAuth認証しているユーザのフィードを意味している。
methodの「post」で投稿を意味し、dataでパラメータを与えている。
他にも「user_id/feed」とかでもいける。
もちろん、ユーザーネーム(ユニークURL)でも大丈夫です。
なお、POSTできるメソッドは下記。(Publishingを参照)
http://developers.facebook.com/docs/reference/api/
PublishingのMethodは上記ソースのurl、Argumentsがdataになります。
権限に関してはDescriptionのリンクを参考にし、足りない場合はログイン時の権限を追加します。
常に決まったアカウントから投稿などする場合、事前にOAuth認証をしておいて、
アクセストークンを取得しておきます。
当然、そのアクセストークンはずっと使える必要があるので有効期限が必要ないように
次の権限をアプリケーションとして許可してもらう必要があります。
「publish_stream」「offline_access」
これでアクセストークンは無期限になるのですが、
(実質的には長期間であり無期限ではないのですが、便宜上無期限としておきます。アクセストークンが無効になった際を考えて、このアクセストークンは設定ファイルやデータベースなどにもっておいたほうが良いと思います。)
このアカウントがOAuth認証したFacebookアプリケーションを削除するとアクセストークンは無効になって
もう一度Facebookアプリケーションを登録しなおし、アクセストークンを取得しなおす必要があることに注意しないといけないです。
なお、アカウントではなく特定のアプリケーションやページから投稿などする場合は下記のApp LoginやPage Loginを参考にしてアクセストークンを取得します。
http://developers.facebook.com/docs/authentication/
しかし、、、無期限のアクセストークンをJavascriptなどクライアント側に埋め込むと誰でもそのアクセストークンを利用してそのアカウント情報を読み込んだり書き込んだりできるため、これらはサーバ側から行わないといけないです。
PHPやPythonなどは公式のSDKがあるので楽だと思います。
Javaでは、【Java】JavaでFacebookにアクセスする方法を参考にしてください。
JavascriptSDKとJavaライブラリのRestFBを組み合わせることでSSLなしの状態でも現在実現できました。
「●Facebookのセッションキーをもとにしてサーバ側でアクセストークンを取得する場合」を参照してください。
単純にユーザにログインしてもらってフィードに投稿するなどの処理であればJavascriptSDKのみで良いと思います。
おまけ
JavascriptSDKを利用せずにFacebookのOAuth認証やるのはこちらがよくまとまっています。
このアクセストークンがあれば、サーバ側からでもFacebookにアクセスできます。
ただ、セキュリティ的なところが色々と気になってきますので、セッションキーをサーバに送信して、サーバ側でアプリIDとアプリシークレット(アプリの秘訣)をもとにしてアクセストークンを取得する上述のリンク先のやり方が良いと思います。
【Javascript】formをsubmitする
2011-06-23 23:17:57 Thu
下記コードは次のURLのものを流用させてもらいっています。
http://harmonic.me/blog/?p=139
http://harmonic.me/blog/?p=139
function postForm(value){ var form = document.createElement( 'form' ); document.body.appendChild( form ); var input = document.createElement( 'input' ); input.setAttribute( 'type' , 'hidden' ); input.setAttribute( 'name' , 'paramName' ); input.setAttribute( 'value' , value ); form.appendChild( input ); form.setAttribute( 'action' , 'action.do' ); form.setAttribute( 'method' , 'post' ); form.submit(); }