SlideShare a Scribd company logo
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

More Related Content

KEY
Plack at OSCON 2010
KEY
Plack at YAPC::NA 2010
KEY
Intro to PSGI and Plack
KEY
Plack - LPW 2009
KEY
KEY
Plack perl superglue for web frameworks and servers
KEY
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
KEY
PSGI/Plack OSDC.TW
Plack at OSCON 2010
Plack at YAPC::NA 2010
Intro to PSGI and Plack
Plack - LPW 2009
Plack perl superglue for web frameworks and servers
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
PSGI/Plack OSDC.TW

What's hot (20)

KEY
Deploying Plack Web Applications: OSCON 2011
PDF
Plack basics for Perl websites - YAPC::EU 2011
PPTX
No callbacks, No Threads - Cooperative web servers in Ruby 1.9
PPTX
PSGI and Plack from first principles
ODP
Modern Perl
KEY
Psgi Plack Sfpm
KEY
Web frameworks don't matter
PDF
A reviravolta do desenvolvimento web
KEY
Sinatra for REST services
PPS
Web Development in Perl
ZIP
Mojolicious
PDF
"Swoole: double troubles in c", Alexandr Vronskiy
PDF
How to test code with mruby
PDF
DevOps tools for everyone - Vagrant, Puppet and Webmin
PDF
Ruby HTTP clients comparison
PDF
Modern Web Development with Perl
PDF
Deploying Symfony | symfony.cat
PPTX
Webinar: Building Your First App in Node.js
PDF
Speed up web APIs with Expressive and Swoole (PHP Day 2018)
PDF
Using Sinatra to Build REST APIs in Ruby
Deploying Plack Web Applications: OSCON 2011
Plack basics for Perl websites - YAPC::EU 2011
No callbacks, No Threads - Cooperative web servers in Ruby 1.9
PSGI and Plack from first principles
Modern Perl
Psgi Plack Sfpm
Web frameworks don't matter
A reviravolta do desenvolvimento web
Sinatra for REST services
Web Development in Perl
Mojolicious
"Swoole: double troubles in c", Alexandr Vronskiy
How to test code with mruby
DevOps tools for everyone - Vagrant, Puppet and Webmin
Ruby HTTP clients comparison
Modern Web Development with Perl
Deploying Symfony | symfony.cat
Webinar: Building Your First App in Node.js
Speed up web APIs with Expressive and Swoole (PHP Day 2018)
Using Sinatra to Build REST APIs in Ruby
Ad

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

PDF
Lone StarPHP 2013 - Building Web Apps from a New Angle
PDF
And the Greatest of These Is ... Space
PDF
Xopus Application Framework
PDF
Charla EHU Noviembre 2014 - Desarrollo Web
KEY
関西アンカンファレンス PHP ではじめるテストコード
PDF
Intro to PHP Testing
PDF
Node js实践
PDF
The symfony platform: Create your very own framework (PHP Quebec 2008)
PDF
HTML 5 - Overview
PDF
Web Crawling with NodeJS
PDF
Consegi 2010 - Dicas de Desenvolvimento Web com Ruby
KEY
Socket applications
KEY
PPT
Building Smart Workflows - Dan Diebolt
PDF
ZendCon2010 The Doctrine Project
PDF
AFUP Lorraine - Symfony Webpack Encore
PDF
Selenium & PHPUnit made easy with Steward (Berlin, April 2017)
PDF
symfony on action - WebTech 207
PDF
soft-shake.ch - Hands on Node.js
PDF
WebGUI Developers Workshop
Lone StarPHP 2013 - Building Web Apps from a New Angle
And the Greatest of These Is ... Space
Xopus Application Framework
Charla EHU Noviembre 2014 - Desarrollo Web
関西アンカンファレンス PHP ではじめるテストコード
Intro to PHP Testing
Node js实践
The symfony platform: Create your very own framework (PHP Quebec 2008)
HTML 5 - Overview
Web Crawling with NodeJS
Consegi 2010 - Dicas de Desenvolvimento Web com Ruby
Socket applications
Building Smart Workflows - Dan Diebolt
ZendCon2010 The Doctrine Project
AFUP Lorraine - Symfony Webpack Encore
Selenium & PHPUnit made easy with Steward (Berlin, April 2017)
symfony on action - WebTech 207
soft-shake.ch - Hands on Node.js
WebGUI Developers Workshop
Ad

More from Tatsuhiko Miyagawa (17)

PDF
Carton CPAN dependency manager
KEY
cpanminus at YAPC::NA 2010
KEY
CPAN Realtime feed
PDF
Asynchronous programming with AnyEvent
PPT
Remedie OSDC.TW
PDF
Why Open Matters It Pro Challenge 2008
PDF
20 modules i haven't yet talked about
PPT
Web::Scraper for SF.pm LT
PPT
Web Scraper Shibuya.pm tech talk #8
PPT
Web::Scraper
PPT
XML::Liberal
PPT
Test::Base
PPT
Hacking Vox and Plagger
PPT
Plagger the duct tape of internet
PPT
Tilting Google Maps and MissileLauncher
PPT
Writing Pluggable Software
PPT
How we build Vox
Carton CPAN dependency manager
cpanminus at YAPC::NA 2010
CPAN Realtime feed
Asynchronous programming with AnyEvent
Remedie OSDC.TW
Why Open Matters It Pro Challenge 2008
20 modules i haven't yet talked about
Web::Scraper for SF.pm LT
Web Scraper Shibuya.pm tech talk #8
Web::Scraper
XML::Liberal
Test::Base
Hacking Vox and Plagger
Plagger the duct tape of internet
Tilting Google Maps and MissileLauncher
Writing Pluggable Software
How we build Vox

Recently uploaded (20)

PDF
COST SHEET- Tender and Quotation unit 2.pdf
PPTX
Dragon_Fruit_Cultivation_in Nepal ppt.pptx
PDF
TriStar Gold Corporate Presentation August 2025
PDF
Power and position in leadershipDOC-20250808-WA0011..pdf
PPTX
Lecture (1)-Introduction.pptx business communication
PPTX
Presentation model for business presentations
PPTX
5 Stages of group development guide.pptx
PPTX
Mastering Odoo ERP Implementation: Key Strategies for Business Success
PPT
Chapter four Project-Preparation material
PPTX
Helicopters in the Brazilian Oil Industry – Executive Summary
PPTX
Belch_12e_PPT_Ch18_Accessible_university.pptx
PDF
Leading with Vision_ How Mohit Bansal Is Shaping Chandigarh’s Real Estate Ren...
PDF
A Brief Introduction About Julia Allison
PDF
Lecture 3 - Risk Management and Compliance.pdf
PPTX
ICG2025_ICG 6th steering committee 30-8-24.pptx
PPTX
How to best Address your professional Training Program - August 2025.pptx
PPTX
Amazon (Business Studies) management studies
PDF
DOC-20250806-WA0002._20250806_112011_0000.pdf
PPTX
Untitled presentation (2).quiz presention
PDF
Reconciliation AND MEMORANDUM RECONCILATION
COST SHEET- Tender and Quotation unit 2.pdf
Dragon_Fruit_Cultivation_in Nepal ppt.pptx
TriStar Gold Corporate Presentation August 2025
Power and position in leadershipDOC-20250808-WA0011..pdf
Lecture (1)-Introduction.pptx business communication
Presentation model for business presentations
5 Stages of group development guide.pptx
Mastering Odoo ERP Implementation: Key Strategies for Business Success
Chapter four Project-Preparation material
Helicopters in the Brazilian Oil Industry – Executive Summary
Belch_12e_PPT_Ch18_Accessible_university.pptx
Leading with Vision_ How Mohit Bansal Is Shaping Chandigarh’s Real Estate Ren...
A Brief Introduction About Julia Allison
Lecture 3 - Risk Management and Compliance.pdf
ICG2025_ICG 6th steering committee 30-8-24.pptx
How to best Address your professional Training Program - August 2025.pptx
Amazon (Business Studies) management studies
DOC-20250806-WA0002._20250806_112011_0000.pdf
Untitled presentation (2).quiz presention
Reconciliation AND MEMORANDUM RECONCILATION

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