[ JavaScript | TypeScript ] Cookieを使いたい

2014/05/13

こんにちは。きんくまです。

Cookieをあんまり使ったことがなかったので、使い方など調べてみました。

Cookieって?

・クライアント側(ブラウザ)に文字列情報を保存することができる
・プロパティ名=値 の形式で保存
・値は,や;などの記号を含められないので、escapeする
・各プロパティには有効期限を設定できる

ブラウザに情報を保存できるのは知ってたんですが、各プロパティごとに有効期限を設定できるのは知らなかったです。サイトかディレクトリ単位で一律かと思った。

>> document.cookie – DOM | MDN

あ、あとそういえば、ドメインとかディレクトリパスによって、cookieの値が読める読めないとかって、前にどこかで見たような。
同じドメインなら見られるけど、別ドメインはNGとか、親から子ディレクトリに保存しているcookieは読めるけど、その逆はNGとかだっけ?
その辺は必要だったら調べます。

有効期限の設定方法って?

それで、有効期限はMozillaさんのドキュメントによると

・max-age=寿命(秒数)
・expires=GMTString

の2種類設定できるみたいです。でもこれってどう違うのよ?どう使い分けるのよ?っていう疑問がわきました。
調べてみますと、わかりやすい記事がありました。

>> HTTP Cookies: What’s the difference between Max-age and Expires? – Peter Coles

どうやら、

・expiresは全てのブラウザで有効
・max-ageはieを除いたブラウザで有効(ブログによるとie6,7,8はだめ。で、ie9以上は調べてません、、)
・expiresはHTTP1.1だと非推奨になっていて、max-ageを使うべき
・だけどieだと使えないからexpiresとうまく使い分けてね!
・expiresとmax-ageを両方設定したら、ie以外はexpiresを無視してmax-ageを使う。ieはexpiresのみ理解できるのでそちらを使う

ということみたいです。

あとは注意する点としては、Cookieの利用可能かそうでないかは、実際に値を書き込んで、それを読み取って読めればOKとすると確実みたいです。

>> JavaScriptでCookieを扱いたい時のメモ | くろひつじのメモ帳

Cookieライブラリ

さきほどのMozillaさんの記事にのってたライブラリが使いやすそうだったので、TypeScript化させてもらいました。

・型を追加
・オリジナルでtoGMTString()という関数が使われていたけど、調べたら非推奨とかってなってたんで、toUTCString()に変更
・cookieが有効かチェックの関数checkEnabledを追加
・有効期限のDateオブジェクトを作るユーティリティクラス(FutureDate)もくっつけて、1枚にしてみました。

module kk{
	//コンパイル通すために追加
	declare function escape(arg?:any):any;
	declare function unescape(arg?:any):any;

	//original code from document.cookie in MDN
	//https://developer.mozilla.org/ja/docs/DOM/document.cookie
	export class CookieUtil{

		static getItem(sKey:string):any {
			if (!sKey || !this.hasItem(sKey)) { return null; }
			return unescape(document.cookie.replace(new RegExp("(?:^|.*;\\s*)" + escape(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*((?:[^;](?!;))*[^;]?).*"), "$1"));
		}

		static setItem(sKey:string, sValue:string, vEnd?:any, sPath?:string, sDomain?:string, bSecure:boolean = false):void {
			if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) { return; }
			var sExpires = "";
			if (vEnd) {
				switch (vEnd.constructor) {
					case Number:
						sExpires = vEnd === Infinity ? "; expires=Tue, 19 Jan 2038 03:14:07 GMT" : "; max-age=" + vEnd;
						break;
					case String:
						sExpires = "; expires=" + vEnd;
						break;
					case Date:
						sExpires = "; expires=" + vEnd.toUTCString();
						break;
				}
			}
			document.cookie = escape(sKey) + "=" + escape(sValue) + sExpires + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "") + (bSecure ? "; secure" : "");
		}

		static removeItem(sKey:string, sPath?:string):void {
			if (!sKey || !this.hasItem(sKey)) { return; }
			document.cookie = escape(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT" + (sPath ? "; path=" + sPath : "");
		}
		static hasItem(sKey:string):boolean {
			return (new RegExp("(?:^|;\\s*)" + escape(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=")).test(document.cookie);
		}

		static keys():string[] {
			var aKeys = document.cookie.replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, "").split(/\s*(?:\=[^;]*)?;\s*/);
			for (var nIdx = 0; nIdx < aKeys.length; nIdx++) { aKeys[nIdx] = unescape(aKeys[nIdx]); }
			return aKeys;
		}

		static checkEnabled():boolean{
			var result:boolean = false;
			try{
				var propName:string = 'testEnabled';
				CookieUtil.setItem(propName, "test");
				result = !(CookieUtil.getItem(propName) === null);
				if(result){
					CookieUtil.removeItem(propName);
				}
			}catch(err){
				return false;
			}
			return result;
		}
	}

	//有効期限のDateをつくるためのユーティリティ
	export class FutureDate{
		static getNow():Date{
			return new Date();
		}

		// n 秒後
		static afterSeconds(seconds:number):Date{
			var d:Date = FutureDate.getNow();
			d.setTime(d.getTime() + seconds * 1000);
			return d;
		}

		// n 分後
		static afterMinutes(minutes:number):Date{
			var d:Date = FutureDate.getNow();
			d.setTime(d.getTime() + minutes * 60 * 1000);
			return d;
		}

		// n 時間後
		static afterHours(hours:number):Date{
			var d:Date = FutureDate.getNow();
			d.setTime(d.getTime() + hours * 60 * 60 * 1000);
			return d;
		}

		// n 日後
		static afterDays(days:number):Date{
			var d:Date = FutureDate.getNow();
			d.setTime(d.getTime() + days * 24 * 60 * 60 * 1000);
			return d;
		}
	}
}

上のだと、正規表現のところがもしかするとうまく表示できてないかもしれないので、オリジナルのtsファイルもアップしました。

>> CookieUtil.ts

使い方

$(function(){
	//使えるかチェック
	if(!kk.CookieUtil.checkEnabled()){
		console.log('Cookieが使えないよ! ブラウザの設定を確認してね');
		return;
	}

	//15秒後に有効期限
	var expireDate = kk.FutureDate.afterSeconds(15);
	console.log(expireDate);

	//追加
	kk.CookieUtil.setItem('animal', 'dog', expireDate);

	//あるか確認 => true
	console.log(kk.CookieUtil.hasItem('animal'));

	//取得 => dog
	console.log(kk.CookieUtil.getItem('animal'));

	//削除
	kk.CookieUtil.removeItem('animal');

	//あるか確認 => false
	console.log(kk.CookieUtil.hasItem('animal'));
});
LINEで送る
Pocket

自作iPhoneアプリ 好評発売中!
フォルメモ - シンプルなフォルダつきメモ帳
ジッピー電卓 - 消費税や割引もサクサク計算!

ページトップへ戻る