Building a desktop app with HTTP::Engine, SQLite and jQuery

Tatsuhiko Miyagawa
Tatsuhiko MiyagawaSoftware Engineer
Building a desktop app with
                   HTTP::Engine, SQLite & jQuery
                              Tatsuhiko Miyagawa
                           YAPC::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.org
                           Slides/Video in OSDC.TW




Wednesday, June 24, 2009
Building a desktop app with
                   HTTP::Engine, SQLite & jQuery
                              Tatsuhiko Miyagawa
                           YAPC::NA 2009 Pittsburgh




Wednesday, June 24, 2009
Desktop GUI apps



Wednesday, June 24, 2009
MFC/.NET
                           Visual C++,VB


Wednesday, June 24, 2009
wxWidgets



Wednesday, June 24, 2009
Objective-C
                               Cocoa
                           (PyObjC/RubyCocoa)



Wednesday, June 24, 2009
Adobe AIR



Wednesday, June 24, 2009
I’m a Perl guy
                    who 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
PhoneGap
Wednesday, June 24, 2009
HTML5
                           geolocation, 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 Miyagawa
                           YAPC::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 Rack
                           Python’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 Ajax
                           backend 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
Authentication
                             Special Headers
                           Switch to JSONRPC


Wednesday, June 24, 2009
Bonjour
               (based on HTTP::Server::Simple::Bonjour)




Wednesday, June 24, 2009
Auto Discovery
                           Share subscriptions


Wednesday, June 24, 2009
Wednesday, June 24, 2009
Building a desktop app with
                   HTTP::Engine, SQLite & jQuery
                              Tatsuhiko Miyagawa
                           YAPC::NA 2009 Pittsburgh




Wednesday, June 24, 2009
SQL DB choices



Wednesday, June 24, 2009
MySQL/PostgreSQL
                           Good 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 schema
                              Few 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, MongoDB
                          TokyoTyrant
                           (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::Class
                           Rose::DB::Object


Wednesday, June 24, 2009
Rose::DB::Object
                            (I wanted some excuse)




Wednesday, June 24, 2009
See Also:
                           KiokuDB


Wednesday, June 24, 2009
KiokuDB
                           DBI / SQLite backend
                            Key-Value JSPON



Wednesday, June 24, 2009
Building a desktop app with
                   HTTP::Engine, SQLite & jQuery
                              Tatsuhiko Miyagawa
                           YAPC::NA 2009 Pittsburgh




Wednesday, June 24, 2009
Just use normal HTML
                    and 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 stuff
                           like Drag & Drop


Wednesday, June 24, 2009
jQuery.blockUI
                           jQuery.scrollTo
                            jQuery.jgrowl


Wednesday, June 24, 2009
Building a desktop app with
                   HTTP::Engine, SQLite & jQuery
                              Tatsuhiko Miyagawa
                           YAPC::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
Fluid
                           Prism


Wednesday, June 24, 2009
Wednesday, June 24, 2009
Customize
               Userscripts / Userstyles


Wednesday, June 24, 2009
Fluid hooks
                           Growl integration
                             Dock menu


Wednesday, June 24, 2009
Wednesday, June 24, 2009
Client-Server
                           Decoupled via APIs


Wednesday, June 24, 2009
More Clients
                           More “Views”


Wednesday, June 24, 2009
iPhone



Wednesday, June 24, 2009
Wednesday, June 24, 2009
Wednesday, June 24, 2009
120 lines of HTML/JS
                         using iUI project


Wednesday, June 24, 2009
Server as “app”



Wednesday, June 24, 2009
Packaging a server



Wednesday, June 24, 2009
local::lib
                      build & install all deps


Wednesday, June 24, 2009
Also:
                           Shipwright


Wednesday, June 24, 2009
Platypus
                           Make .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
1 of 112

More Related Content

What's hot(20)

Deploying Plack Web Applications: OSCON 2011Deploying Plack Web Applications: OSCON 2011
Deploying Plack Web Applications: OSCON 2011
Tatsuhiko Miyagawa8.2K views
Modern PerlModern Perl
Modern Perl
Dave Cross6.6K views
Psgi Plack SfpmPsgi Plack Sfpm
Psgi Plack Sfpm
som_nangia1.8K views
Web frameworks don't matterWeb frameworks don't matter
Web frameworks don't matter
Tomas Doran593 views
A reviravolta do desenvolvimento webA reviravolta do desenvolvimento web
A reviravolta do desenvolvimento web
Wallace Reis932 views
Sinatra for REST servicesSinatra for REST services
Sinatra for REST services
Emanuele DelBono12.1K views
Web Development in PerlWeb Development in Perl
Web Development in Perl
Naveen Gupta15.5K views
MojoliciousMojolicious
Mojolicious
Marcus Ramberg4.4K views
How to test code with mrubyHow to test code with mruby
How to test code with mruby
Hiroshi SHIBATA10K views
Ruby HTTP clients comparisonRuby HTTP clients comparison
Ruby HTTP clients comparison
Hiroshi Nakamura26.3K views
Modern Web Development with PerlModern Web Development with Perl
Modern Web Development with Perl
Dave Cross15.8K views
Deploying Symfony | symfony.catDeploying Symfony | symfony.cat
Deploying Symfony | symfony.cat
Pablo Godel2.8K views
Speed up web APIs with Expressive and Swoole (PHP Day 2018) Speed up web APIs with Expressive and Swoole (PHP Day 2018)
Speed up web APIs with Expressive and Swoole (PHP Day 2018)
Zend by Rogue Wave Software1.1K views

Similar to Building a desktop app with HTTP::Engine, SQLite and jQuery(20)

Xopus Application FrameworkXopus Application Framework
Xopus Application Framework
Jady Yang753 views
Charla EHU Noviembre 2014 - Desarrollo WebCharla EHU Noviembre 2014 - Desarrollo Web
Charla EHU Noviembre 2014 - Desarrollo Web
Mikel Torres Ugarte3.7K views
Intro to PHP TestingIntro to PHP Testing
Intro to PHP Testing
Ran Mizrahi4.9K views
Node js实践Node js实践
Node js实践
jay li9.8K views
HTML 5 - OverviewHTML 5 - Overview
HTML 5 - Overview
Marcelio Leal666 views
Web Crawling with NodeJSWeb Crawling with NodeJS
Web Crawling with NodeJS
Sylvain Zimmer119.1K views
Socket applicationsSocket applications
Socket applications
João Moura601 views
SprocketsSprockets
Sprockets
Christophe Porteneuve12.2K views
Building Smart Workflows - Dan DieboltBuilding Smart Workflows - Dan Diebolt
Building Smart Workflows - Dan Diebolt
QuickBase, Inc.2.2K views
ZendCon2010 The Doctrine ProjectZendCon2010 The Doctrine Project
ZendCon2010 The Doctrine Project
Jonathan Wage1.8K views
soft-shake.ch - Hands on Node.jssoft-shake.ch - Hands on Node.js
soft-shake.ch - Hands on Node.js
soft-shake.ch2.3K views

More from Tatsuhiko Miyagawa(17)

Carton CPAN dependency managerCarton CPAN dependency manager
Carton CPAN dependency manager
Tatsuhiko Miyagawa4.1K views
cpanminus at YAPC::NA 2010cpanminus at YAPC::NA 2010
cpanminus at YAPC::NA 2010
Tatsuhiko Miyagawa1.6K views
CPAN Realtime feedCPAN Realtime feed
CPAN Realtime feed
Tatsuhiko Miyagawa7.1K views
Asynchronous programming with AnyEventAsynchronous programming with AnyEvent
Asynchronous programming with AnyEvent
Tatsuhiko Miyagawa6.5K views
Remedie OSDC.TWRemedie OSDC.TW
Remedie OSDC.TW
Tatsuhiko Miyagawa7.8K views
Why Open Matters It Pro Challenge 2008Why Open Matters It Pro Challenge 2008
Why Open Matters It Pro Challenge 2008
Tatsuhiko Miyagawa7.9K views
20 modules i haven't yet talked about20 modules i haven't yet talked about
20 modules i haven't yet talked about
Tatsuhiko Miyagawa4.9K views
Web::Scraper for SF.pm LTWeb::Scraper for SF.pm LT
Web::Scraper for SF.pm LT
Tatsuhiko Miyagawa3.2K views
Web Scraper Shibuya.pm tech talk #8Web Scraper Shibuya.pm tech talk #8
Web Scraper Shibuya.pm tech talk #8
Tatsuhiko Miyagawa17K views
Web::ScraperWeb::Scraper
Web::Scraper
Tatsuhiko Miyagawa18.4K views
XML::LiberalXML::Liberal
XML::Liberal
Tatsuhiko Miyagawa1.4K views
Test::BaseTest::Base
Test::Base
Tatsuhiko Miyagawa1.5K views
Hacking Vox and PlaggerHacking Vox and Plagger
Hacking Vox and Plagger
Tatsuhiko Miyagawa2.7K views
Plagger the duct tape of internetPlagger the duct tape of internet
Plagger the duct tape of internet
Tatsuhiko Miyagawa2.7K views
Tilting Google Maps and MissileLauncherTilting Google Maps and MissileLauncher
Tilting Google Maps and MissileLauncher
Tatsuhiko Miyagawa2.8K views
Writing Pluggable SoftwareWriting Pluggable Software
Writing Pluggable Software
Tatsuhiko Miyagawa3.9K views
How we build VoxHow we build Vox
How we build Vox
Tatsuhiko Miyagawa19.2K views

Building a desktop app with HTTP::Engine, SQLite and jQuery

  • 1. Building a desktop app with HTTP::Engine, SQLite & jQuery Tatsuhiko Miyagawa YAPC::NA 2009 Pittsburgh Wednesday, June 24, 2009
  • 6. 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
  • 7. twitter.com/miyagawa (Slides will be linked. Follow me!) Wednesday, June 24, 2009
  • 9. remediecode.org Slides/Video in OSDC.TW Wednesday, June 24, 2009
  • 10. Building a desktop app with HTTP::Engine, SQLite & jQuery Tatsuhiko Miyagawa YAPC::NA 2009 Pittsburgh Wednesday, June 24, 2009
  • 12. MFC/.NET Visual C++,VB Wednesday, June 24, 2009
  • 14. Objective-C Cocoa (PyObjC/RubyCocoa) Wednesday, June 24, 2009
  • 16. I’m a Perl guy who knows JavaScript. Wednesday, June 24, 2009
  • 19. “Web 2.0 iPhone App” Steve Jobs at WWDC 2007 Wednesday, June 24, 2009
  • 22. HTML5 geolocation, videos local storage Wednesday, June 24, 2009
  • 23. HTML5 = Future ??? = 2009 Wednesday, June 24, 2009
  • 24. micro Web app = 2009 Wednesday, June 24, 2009
  • 25. (2 min Demo video) Wednesday, June 24, 2009
  • 26. How I built this Wednesday, June 24, 2009
  • 27. Building a desktop app with HTTP::Engine, SQLite & jQuery Tatsuhiko Miyagawa YAPC::NA 2009 Pittsburgh Wednesday, June 24, 2009
  • 28. “The most important project in Perl recently” - jrockway Wednesday, June 24, 2009
  • 29. Based on Catalyst::Engine Wednesday, June 24, 2009
  • 30. Ruby’s Rack Python’s WSGI Wednesday, June 24, 2009
  • 31. 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
  • 32. sub handle_request {     my $req = shift;     return HTTP::Engine::Response‐>new(         body => “Hello World”,     ); } Wednesday, June 24, 2009
  • 33. Standalone, ServerSimple, POE, FastCGI, mod_perl Wednesday, June 24, 2009
  • 34. Desktop app: ServerSimple POE (non-blocking) Wednesday, June 24, 2009
  • 35. Serve static files (HTML/CSS/JS) Wednesday, June 24, 2009
  • 36. 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
  • 37. 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
  • 38. See Also: HTTP::Engine::Middleware::Static Wednesday, June 24, 2009
  • 39. Implement Ajax backend actions (JSON-REST) Wednesday, June 24, 2009
  • 40. 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
  • 41. 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
  • 42. Problem (1): Dirty API routing Wednesday, June 24, 2009
  • 43. Path::Router, Path::Dispatcher, HTTP::Dispatcher, JSORB Wednesday, June 24, 2009
  • 44. Problem (2): Vulnerable (CSRF) Wednesday, June 24, 2009
  • 45. Authentication Special Headers Switch to JSONRPC Wednesday, June 24, 2009
  • 46. Bonjour (based on HTTP::Server::Simple::Bonjour) Wednesday, June 24, 2009
  • 47. Auto Discovery Share subscriptions Wednesday, June 24, 2009
  • 49. Building a desktop app with HTTP::Engine, SQLite & jQuery Tatsuhiko Miyagawa YAPC::NA 2009 Pittsburgh Wednesday, June 24, 2009
  • 50. SQL DB choices Wednesday, June 24, 2009
  • 51. MySQL/PostgreSQL Good for Web apps. Wednesday, June 24, 2009
  • 52. SQLite: file-based, type-less Transactional Wednesday, June 24, 2009
  • 53. SQLite: best for desktop apps Wednesday, June 24, 2009
  • 54. SQLite for desktop: Firefox, Mail.app, iCal Wednesday, June 24, 2009
  • 55. End-users don’t want to run *SQL server Wednesday, June 24, 2009
  • 56. Bonus: Easy backup, Dropbox sync Wednesday, June 24, 2009
  • 58. You don’t need DBA. Make it simple, flexible and extensible. Wednesday, June 24, 2009
  • 59. Remedie schema Few indexes JSON key-values Wednesday, June 24, 2009
  • 60. 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
  • 61. 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
  • 63. CouchDB, MongoDB TokyoTyrant (Need servers though) Wednesday, June 24, 2009
  • 67. DBIx::Class Rose::DB::Object Wednesday, June 24, 2009
  • 68. Rose::DB::Object (I wanted some excuse) Wednesday, June 24, 2009
  • 69. See Also: KiokuDB Wednesday, June 24, 2009
  • 70. KiokuDB DBI / SQLite backend Key-Value JSPON Wednesday, June 24, 2009
  • 71. Building a desktop app with HTTP::Engine, SQLite & jQuery Tatsuhiko Miyagawa YAPC::NA 2009 Pittsburgh Wednesday, June 24, 2009
  • 72. Just use normal HTML and CSS to design UI Wednesday, June 24, 2009
  • 73. Manipulate DOM $.ajax to do Ajax Wednesday, June 24, 2009
  • 76. $("#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
  • 78. $(document).bind(‘keydown’, ‘shift+n’, function(ev){    // ‘N’ is entered }); Wednesday, June 24, 2009
  • 83. $.event.trigger $(document).bind Wednesday, June 24, 2009
  • 85. Fancy stuff like Drag & Drop Wednesday, June 24, 2009
  • 86. jQuery.blockUI jQuery.scrollTo jQuery.jgrowl Wednesday, June 24, 2009
  • 87. Building a desktop app with HTTP::Engine, SQLite & jQuery Tatsuhiko Miyagawa YAPC::NA 2009 Pittsburgh Wednesday, June 24, 2009
  • 88. More like “Desktop app” Wednesday, June 24, 2009
  • 90. Web Client as “app” Wednesday, June 24, 2009
  • 92. Fluid Prism Wednesday, June 24, 2009
  • 94. Customize Userscripts / Userstyles Wednesday, June 24, 2009
  • 95. Fluid hooks Growl integration Dock menu Wednesday, June 24, 2009
  • 97. Client-Server Decoupled via APIs Wednesday, June 24, 2009
  • 98. More Clients More “Views” Wednesday, June 24, 2009
  • 102. 120 lines of HTML/JS using iUI project Wednesday, June 24, 2009
  • 105. local::lib build & install all deps Wednesday, June 24, 2009
  • 106. Also: Shipwright Wednesday, June 24, 2009
  • 107. Platypus Make .app Wednesday, June 24, 2009
  • 108. Download .zip, copy .app to /Applications, Run it. Wednesday, June 24, 2009
  • 109. Also: github.com/miyagawa/perl-app-builder Wednesday, June 24, 2009
  • 110. 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
  • 111. That’s it! Questions? Wednesday, June 24, 2009
  • 112. Thank you! twitter.com/miyagawa Wednesday, June 24, 2009