diff --git a/src/tink/http/Cookie.hx b/src/tink/http/Cookie.hx new file mode 100644 index 0000000..e00fbf7 --- /dev/null +++ b/src/tink/http/Cookie.hx @@ -0,0 +1,97 @@ +package tink.http; + +using DateTools; +using StringTools; +using Std; + +@:forward +abstract Cookie(CookieObject) from CookieObject { + + public inline function new(name:String, value:String, ?expires:Date, ?domain:String, ?path:String, secure = false, httpOnly = false) + this = { + name: name, + value: value, + expires: expires, + domain: domain, + path: path, + secure: secure, + httpOnly: httpOnly, + } + + public static function parse(s:String):Array { + return [ + for(pair in s.split('; ')) { + var v = pair.split('='); + { + name: v[0], + value: v[1], + } + } + ]; + } + + @:to + public function toString():String { + var buf = new StringBuf(); + buf.add(this.name); + if(this.value != null) buf.add('=${this.value}'); + if(this.expires != null) buf.add('; expires=${formatDate(this.expires)}'); + if(this.domain != null) buf.add('; domain=${this.domain}'); + if(this.path != null) buf.add('; path=${this.path}'); + if(this.secure) buf.add('; secure'); + if(this.httpOnly) buf.add('; httponly'); + return buf.toString(); + } + + function formatDate(date:Date) { + var timezoneOffset = + #if php + untyped __php__("intval(date('Z', {0}->__t));", date); + #else + Date.fromString('1970-01-01 00:00:00').getTime(); + #end + var d = date.delta(timezoneOffset); + + var day = switch d.getDay() { + case 0: 'Sun'; + case 1: 'Mon'; + case 2: 'Tue'; + case 3: 'Wed'; + case 4: 'Thu'; + case 5: 'Fri'; + case 6: 'Sat'; + default: throw 'assert'; + } + var date = d.getDate().string().lpad('0', 2); + var month = switch d.getMonth() { + case 0: 'Jan'; + case 1: 'Feb'; + case 2: 'Mar'; + case 3: 'Apr'; + case 4: 'May'; + case 5: 'Jun'; + case 6: 'Jul'; + case 7: 'Aug'; + case 8: 'Sep'; + case 9: 'Oct'; + case 10: 'Nov'; + case 11: 'Dec'; + default: throw 'assert'; + } + var year = d.getFullYear(); + var hour = d.getHours().string().lpad('0', 2); + var minute = d.getMinutes().string().lpad('0', 2); + var second = d.getSeconds().string().lpad('0', 2); + return '$day, $date-$month-$year $hour:$minute:$second GMT'; + } +} + +typedef CookieObject = { + name:String, + value:String, + ?expires:Date, + ?domain:String, + ?path:String, + ?secure:Bool, + ?httpOnly:Bool, +} \ No newline at end of file diff --git a/tests/RunTests.hx b/tests/RunTests.hx index 247737e..e38f4e4 100644 --- a/tests/RunTests.hx +++ b/tests/RunTests.hx @@ -3,6 +3,7 @@ package; import tink.http.Container; import tink.http.Client; import tink.http.Multipart; +import haxe.unit.TestRunner; class RunTests { @@ -16,6 +17,12 @@ class RunTests { var c = new NodeClient(); var s = new NodeContainer(2000); #end + + var t = new TestRunner(); + t.add(new TestCookie()); + if(!t.run()) { + #if sys Sys.exit(500); #end + } } } \ No newline at end of file diff --git a/tests/TestCookie.hx b/tests/TestCookie.hx new file mode 100644 index 0000000..7510d33 --- /dev/null +++ b/tests/TestCookie.hx @@ -0,0 +1,32 @@ +package; + +import haxe.unit.TestCase; +import tink.http.Cookie; + +class TestCookie extends TestCase { + function testCookie() { + var cookies = Cookie.parse('name=value'); + assertEquals(1, cookies.length); + assertEquals('name', cookies[0].name); + assertEquals('value', cookies[0].value); + + var cookies = Cookie.parse('name=value; name1=value1'); + assertEquals(2, cookies.length); + assertEquals('name', cookies[0].name); + assertEquals('value', cookies[0].value); + assertEquals('name1', cookies[1].name); + assertEquals('value1', cookies[1].value); + + var cookie = new Cookie('name', 'value'); + assertEquals('name=value', cookie); + + var cookie = new Cookie('name', 'value', DateTools.delta(Date.now(), 1000)); + trace((cookie:String)); // TODO: assert time zone + + var cookie = new Cookie('name', 'value', 'domain.com', '/path'); + assertEquals('name=value; domain=domain.com; path=/path', cookie); + + var cookie = new Cookie('name', 'value', 'domain.com', '/path', true, true); + assertEquals('name=value; domain=domain.com; path=/path; secure; httponly', cookie); + } +} \ No newline at end of file