Building a desktop app with HTTP::Engine, SQLite & jQuery Tatsuhiko Miyagawa YAPC::NA 2009 Pittsburgh Wednesday, June 24, 2009
Jan 20, 2015
Building a desktop app with HTTP::Engine, SQLite & jQuery
Tatsuhiko MiyagawaYAPC::NA 2009 Pittsburgh
Wednesday, June 24, 2009
Tatsuhiko Miyagawa
Wednesday, June 24, 2009
Wednesday, June 24, 2009
Software Engineer, TypePad
Wednesday, June 24, 2009
cpan: MIYAGAWA
Wednesday, June 24, 2009
Acme-DateTime-Duration-Numeric Acme-Module-Authors Acme-Sneeze Acme-Sneeze-JP Apache-ACEProxy Apache-AntiSpam Apache-Clickable Apache-CustomKeywords Apache-DefaultCharset Apache-GuessCharset Apache-JavaScript-
DocumentWrite Apache-No404Proxy Apache-Profiler Apache-Session-CacheAny Apache-Session-Generate-ModUniqueId Apache-Session-Generate-ModUsertrack Apache-Session-PHP Apache-Session-Serialize-YAML Apache-Singleton Apache-StickyQuery Archive-Any-Create Attribute-Profiled Attribute-Protected Attribute-Unimplemented Bundle-Sledge CGI-
Untaint-email CPAN-Mini-Growl Catalyst-Plugin-Authentication-Credential-AOL Catalyst-Plugin-Authentication-Credential-OpenID Catalyst-Plugin-JSONRPC Catalyst-View-JSON Catalyst-View-Jemplate Class-DBI-AbstractSearch Class-DBI-
Extension Class-DBI-Pager Class-DBI-Replication Class-DBI-SQLite Class-DBI-View Class-Trigger Convert-Base32 Convert-DUDE Convert-RACE Data-YUID Date-Japanese-Era Date-Range-Birth DateTime-Span-Birthdate Device-KeyStroke-Mobile Dunce-time Email-Find Email-Valid-Loose Encode-DoubleEncodedUTF8 Encode-First Encode-JP-Mobile Encode-JavaScript-
UCS Encode-Punycode File-Find-Rule-Digest File-Spotlight Geo-Coder-Google HTML-AutoPagerize HTML-Entities-ImodePictogram HTML-RelExtor HTML-ResolveLink HTML-Selector-XPath HTML-XSSLint HTTP-MobileAgent HTTP-ProxyPAC HTTP-Server-Simple-Authen HTTP-Server-Simple-Bonjour IDNA-Punycode Inline-Basic Inline-TT JSON-Syck
Kwiki-Emoticon Kwiki-Export Kwiki-Footnote Kwiki-OpenSearch Kwiki-OpenSearch-Service Kwiki-TypeKey Kwiki-URLBL LWP-UserAgent-Keychain Lingua-JA-Hepburn-Passport Log-Dispatch-Config Log-Dispatch-DBI MSIE-MenuExt Mac-
Macbinary Mail-Address-MobileJp Mail-ListDetector-Detector-Fml Module-Install-Repository Net-DAAP-Server-AAC Net-IDN-Nameprep Net-IPAddr-Find Net-Twitter-OAuth Net-YahooMessenger NetAddr-IP-Find P2P-Transmission-Remote PHP-Session POE-Component-Client-AirTunes POE-Component-Client-Lingr POE-Component-YahooMessenger Path-
Class-URI Plagger RPC-XML-Parser-LibXML Template-Plugin-Clickable Template-Plugin-Comma Template-Plugin-FillInForm Template-Plugin-HTML-Template Template-Plugin-JavaScript Template-Plugin-MobileAgent Template-Plugin-ResolveLink
Template-Plugin-Shuffle Template-Provider-Encoding Term-Encoding Term-TtyRec Test-Synopsis Text-Emoticon Text-Emoticon-GoogleTalk Text-Emoticon-MSN Text-Emoticon-Yahoo Text-MessageFormat TheSchwartz-Simple Time-Duration-Parse Time-Duration-ja URI-Find-UTF8 URI-git URI-tag URI-urn-uuid Video-Subtitle-SRT WWW-Baseball-NPB WWW-Blog-Metadata-MobileLinkDiscovery WWW-Blog-Metadata-OpenID WWW-Blog-Metadata-OpenSearch WWW-Cache-Google
WWW-Mechanize-AutoPager WWW-Mechanize-DecodedContent WWW-NicoVideo-Download WWW-OpenSearch WWW-Shorten-RevCanonical WWW-Shorten-Simple Web-Scraper Web-oEmbed WebService-Bloglines WebService-ChangesXml WebService-Google-Suggest WebService-Lingr XML-Atom XML-Atom-Lifeblog XML-Atom-Stream XML-
Liberal XML-OPML-LibXML abbreviation autobox-DateTime-Duration capitalization plagger
Wednesday, June 24, 2009
twitter.com/miyagawa(Slides will be linked. Follow me!)
Wednesday, June 24, 2009
Remedie
Wednesday, June 24, 2009
remediecode.orgSlides/Video in OSDC.TW
Wednesday, June 24, 2009
Building a desktop app with HTTP::Engine, SQLite & jQuery
Tatsuhiko MiyagawaYAPC::NA 2009 Pittsburgh
Wednesday, June 24, 2009
Desktop GUI apps
Wednesday, June 24, 2009
MFC/.NETVisual C++, VB
Wednesday, June 24, 2009
wxWidgets
Wednesday, June 24, 2009
Objective-CCocoa
(PyObjC/RubyCocoa)
Wednesday, June 24, 2009
Adobe AIR
Wednesday, June 24, 2009
I’m a Perl guywho knows JavaScript.
Wednesday, June 24, 2009
Web Developers!Wednesday, June 24, 2009
Web app!
Wednesday, June 24, 2009
“Web 2.0 iPhone App”Steve Jobs at WWDC 2007
Wednesday, June 24, 2009
Wednesday, June 24, 2009
PhoneGapWednesday, June 24, 2009
HTML5geolocation, videos
local storage
Wednesday, June 24, 2009
HTML5 = Future??? = 2009
Wednesday, June 24, 2009
micro Web app = 2009
Wednesday, June 24, 2009
(2 min Demo video)Wednesday, June 24, 2009
How I built this
Wednesday, June 24, 2009
Building a desktop app with HTTP::Engine, SQLite & jQuery
Tatsuhiko MiyagawaYAPC::NA 2009 Pittsburgh
Wednesday, June 24, 2009
“The most important project in Perl recently”
- jrockway
Wednesday, June 24, 2009
Based on Catalyst::Engine
Wednesday, June 24, 2009
Ruby’s RackPython’s WSGI
Wednesday, June 24, 2009
use HTTP::Engine;my $engine = HTTP::Engine‐>new( interface => { module => 'ServerSimple', args => { host => 'localhost', port => 9898, }, request_handler => \&handle_request,});
$engine‐>run;
Wednesday, June 24, 2009
sub handle_request { my $req = shift; return HTTP::Engine::Response‐>new( body => “Hello World”, );}
Wednesday, June 24, 2009
Standalone, ServerSimple, POE, FastCGI, mod_perl
Wednesday, June 24, 2009
Desktop app:ServerSimple
POE (non-blocking)
Wednesday, June 24, 2009
Serve static files(HTML/CSS/JS)
Wednesday, June 24, 2009
sub handle_request { my($self, $req) = @_;
my $path = $req‐>path; my $res = HTTP::Engine::Response‐>new;
if ($path =~ s!^/static/!!) { $self‐>serve_static_file($path, $req, $res); };
return $res;}
Wednesday, June 24, 2009
use Path::Class;sub serve_static_file { my($self, $path, $req, $res) = @_;
my $root = $self‐>conf‐>{root}; my $file = file($root, "static", $path);
my $size = ‐s _; my $mtime = (stat(_))[9]; my $ext = ($file =~ /\.(\w+)$/)[0]; $res‐>content_type( MIME::Types‐>new‐>mimeTypeOf($ext) || "text/plain" ); # ... open my $fh, "<:raw", $file or die "$file: $!"; $res‐>headers‐>header('Last‐Modified' => HTTP::Date::time2str($mtime)); $res‐>headers‐>header('Content‐Length' => $size); $res‐>body( join '', <$fh> );}
Wednesday, June 24, 2009
See Also:HTTP::Engine::Middleware::Static
Wednesday, June 24, 2009
Implement Ajaxbackend actions(JSON-REST)
Wednesday, June 24, 2009
sub handle_request { my($self, $req) = @_;
my $path = $req‐>path;
my $res = HTTP::Engine::Response‐>new;
if ($path =~ s!^/rpc/!!) { $self‐>dispatch_rpc($path, $req, $res); }}
Wednesday, June 24, 2009
sub dispatch_rpc { my($self, $path, $req, $res) = @_;
my @class = split '/', $path; my $method = pop @class; die "Access to non‐public methods" if $method =~ /^_/;
my $rpc_class = $self‐>load_rpc_class(\@class); my $rpc = $rpc_class‐>new( conf => $self‐>conf ); my $result = eval { $rpc‐>$method($req, $res) };
unless ( $res‐>body ) { $res‐>status(200); $res‐>content_type("application/json; charset=utf‐8"); $res‐>body( Remedie::JSON‐>encode($result) ); }}
Wednesday, June 24, 2009
Problem (1):Dirty API routing
Wednesday, June 24, 2009
Path::Router, Path::Dispatcher,HTTP::Dispatcher, JSORB
Wednesday, June 24, 2009
Problem (2):Vulnerable (CSRF)
Wednesday, June 24, 2009
AuthenticationSpecial Headers
Switch to JSONRPC
Wednesday, June 24, 2009
Bonjour(based on HTTP::Server::Simple::Bonjour)
Wednesday, June 24, 2009
Auto DiscoveryShare subscriptions
Wednesday, June 24, 2009
Wednesday, June 24, 2009
Building a desktop app with HTTP::Engine, SQLite & jQuery
Tatsuhiko MiyagawaYAPC::NA 2009 Pittsburgh
Wednesday, June 24, 2009
SQL DB choices
Wednesday, June 24, 2009
MySQL/PostgreSQLGood for Web apps.
Wednesday, June 24, 2009
SQLite:file-based, type-less
Transactional
Wednesday, June 24, 2009
SQLite:best for desktop apps
Wednesday, June 24, 2009
SQLite for desktop:Firefox, Mail.app, iCal
Wednesday, June 24, 2009
End-users don’t want to run *SQL server
Wednesday, June 24, 2009
Bonus:Easy backup,
Dropbox sync
Wednesday, June 24, 2009
DB Schema
Wednesday, June 24, 2009
You don’t need DBA.Make it simple, flexible and extensible.
Wednesday, June 24, 2009
Remedie schemaFew indexes
JSON key-values
Wednesday, June 24, 2009
CREATE TABLE channel ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, type INTEGER NOT NULL, parent INTEGER NOT NULL, ident TEXT NOT NULL, name TEXT NOT NULL, props TEXT);
CREATE UNIQUE INDEX channel_ident ON channel (ident);
Wednesday, June 24, 2009
CREATE TABLE item ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, channel_id INTEGER NOT NULL, type INTEGER NOT NULL, ident TEXT NOT NULL, name TEXT NOT NULL, status INTEGER NOT NULL, props TEXT);
CREATE INDEX item_status ON item (status)
CREATE UNIQUE INDEX item_ident ON item (channel_id, ident);
Wednesday, June 24, 2009
Key-Value is HOT
Wednesday, June 24, 2009
CouchDB, MongoDBTokyoTyrant(Need servers though)
Wednesday, June 24, 2009
SQLite for Key-Value
Wednesday, June 24, 2009
ORM?
Wednesday, June 24, 2009
Anything you like.
Wednesday, June 24, 2009
DBIx::ClassRose::DB::Object
Wednesday, June 24, 2009
Rose::DB::Object(I wanted some excuse)
Wednesday, June 24, 2009
See Also:KiokuDB
Wednesday, June 24, 2009
KiokuDBDBI / SQLite backend
Key-Value JSPON
Wednesday, June 24, 2009
Building a desktop app with HTTP::Engine, SQLite & jQuery
Tatsuhiko MiyagawaYAPC::NA 2009 Pittsburgh
Wednesday, June 24, 2009
Just use normal HTMLand CSS to design UI
Wednesday, June 24, 2009
Manipulate DOM$.ajax to do Ajax
Wednesday, June 24, 2009
DOM Manipulation sucks.
Wednesday, June 24, 2009
jQuery.flydom
Wednesday, June 24, 2009
$("#channel‐pane").createAppend( 'div', { className: 'channel‐header', id: 'channel‐header‐' + channel.id }, [ 'div', { className: 'channel‐header‐thumb' }, [ 'img', { src: "/static/images/feed.png", alt: channel.name }, null ], ]);
Wednesday, June 24, 2009
jQuery.hotkeys
Wednesday, June 24, 2009
$(document).bind(‘keydown’, ‘shift+n’, function(ev){ // ‘N’ is entered});
Wednesday, June 24, 2009
jQuery.contextMenu
Wednesday, June 24, 2009
Wednesday, June 24, 2009
jQuery.corners
Wednesday, June 24, 2009
Wednesday, June 24, 2009
$.event.trigger$(document).bind
Wednesday, June 24, 2009
jQuery UI
Wednesday, June 24, 2009
Fancy stufflike Drag & Drop
Wednesday, June 24, 2009
jQuery.blockUIjQuery.scrollTojQuery.jgrowl
Wednesday, June 24, 2009
Building a desktop app with HTTP::Engine, SQLite & jQuery
Tatsuhiko MiyagawaYAPC::NA 2009 Pittsburgh
Wednesday, June 24, 2009
More like“Desktop app”
Wednesday, June 24, 2009
Client-Server
Wednesday, June 24, 2009
Web Client as “app”
Wednesday, June 24, 2009
Site Specific Browser
Wednesday, June 24, 2009
FluidPrism
Wednesday, June 24, 2009
Wednesday, June 24, 2009
CustomizeUserscripts / Userstyles
Wednesday, June 24, 2009
Fluid hooksGrowl integration
Dock menu
Wednesday, June 24, 2009
Wednesday, June 24, 2009
Client-ServerDecoupled via APIs
Wednesday, June 24, 2009
More ClientsMore “Views”
Wednesday, June 24, 2009
iPhone
Wednesday, June 24, 2009
Wednesday, June 24, 2009
Wednesday, June 24, 2009
120 lines of HTML/JSusing iUI project
Wednesday, June 24, 2009
Server as “app”
Wednesday, June 24, 2009
Packaging a server
Wednesday, June 24, 2009
local::libbuild & install all deps
Wednesday, June 24, 2009
Also:Shipwright
Wednesday, June 24, 2009
PlatypusMake .app
Wednesday, June 24, 2009
Download .zip, copy .app to /Applications, Run it.
Wednesday, June 24, 2009
Also:github.com/miyagawa/perl-app-builder
Wednesday, June 24, 2009
Summary
• micro web server as a desktop app
• HTTP::Engine, JSONRPC and router
• SQLite to store key-value
• jQuery plugins to enable desktop UIs
• More tools to make it really “.app”
Wednesday, June 24, 2009
That’s it!Questions?
Wednesday, June 24, 2009
Thank you!twitter.com/miyagawa
Wednesday, June 24, 2009