SlideShare uma empresa Scribd logo
1 de 20
Baixar para ler offline
⽤用Tornado开发RESTful
                  API运⽤用
                 ⻜飞⻰龙⾮非⻰龙 (http://feilong.me)
                        2012/10/20




12年10月14⽇日星期⽇日
议程

                 • RESTful API简介
                 • ⽤用Tornado开发RESTful API应⽤用
                 • D3status demo APP


12年10月14⽇日星期⽇日
12年10月14⽇日星期⽇日
Service

         Resource   Service   API   Clients




12年10月14⽇日星期⽇日
RESTful API

                           OAuth




                       HTTPS GET/POST

                 App                    Platform
                         JSON/JSONP




12年10月14⽇日星期⽇日
RESTful and HTTP Verbs


            Level 0   GET   POST   PUT   DELETE   PATCH

            Level 1   GET   POST   PUT   DELETE   PATCH

            Level 2   GET   POST   PUT   DELETE   PATCH




12年10月14⽇日星期⽇日
RESTful in Tornado
                 class RequestHandler(object):
                     """Subclass this class and define get() or post() to make a handler.

                     If you want to support more methods than the standard GET/HEAD/POST, you
                     should override the class variable SUPPORTED_METHODS in your
                     RequestHandler class.
                     """
                     SUPPORTED_METHODS = ("GET", "HEAD", "POST", "DELETE", "PATCH", "PUT",
                                           "OPTIONS")

                    def head(self, *args, **kwargs):
                        raise HTTPError(405)

                    def get(self, *args, **kwargs):
                        raise HTTPError(405)

                    def post(self, *args, **kwargs):
                        raise HTTPError(405)

                    def delete(self, *args, **kwargs):
                        raise HTTPError(405)

                    def patch(self, *args, **kwargs):
                        raise HTTPError(405)

                    def put(self, *args, **kwargs):
                        raise HTTPError(405)

                    def options(self, *args, **kwargs):
                        raise HTTPError(405)

12年10月14⽇日星期⽇日
JSON & JSONP
                 class APIHandler(BaseHandler):

                     def finish(self, chunk=None, notification=None):
                         if chunk is None:
                             chunk = {}

                         if isinstance(chunk, dict):
                             chunk = {"meta": {"code": 200}, "response": chunk}

                             if notification:
                                 chunk["notification"] = {"message": notification}

                         callback = escape.utf8(self.get_argument("callback", None))
                         if callback:
                             self.set_header("Content-Type", "application/x-javascript")

                             if isinstance(chunk, dict):
                                 chunk = escape.json_encode(chunk)

                             self._write_buffer = [callback, "(", chunk, ")"] if chunk else []
                             super(APIHandler, self).finish()
                         else:
                             self.set_header("Content-Type", "application/json; charset=UTF-8")
                             super(APIHandler, self).finish(chunk)




12年10月14⽇日星期⽇日
Exception
                 def write_error(self, status_code, **kwargs):
                     """Override to implement custom error pages."""
                     debug = self.settings.get("debug", False)
                     try:
                          exc_info = kwargs.pop('exc_info')
                          e = exc_info[1]

                        if isinstance(e, exceptions.HTTPAPIError):
                            pass
                        elif isinstance(e, HTTPError):
                            e = exceptions.HTTPAPIError(e.status_code)
                        else:
                            e = exceptions.HTTPAPIError(500)

                         exception = "".join([ln for ln in traceback.format_exception(*exc_info)])

                        if status_code == 500 and not debug:
                            self._send_error_email(exception)

                        if debug:
                            e.response["exception"] = exception

                        self.clear()
                        self.set_status(200) # always return 200 OK for API errors
                        self.set_header("Content-Type", "application/json; charset=UTF-8")
                        self.finish(str(e))
                    except Exception:
                        logging.error(traceback.format_exc())
                        return super(APIHandler, self).write_error(status_code, **kwargs)
12年10月14⽇日星期⽇日
Exception
                 class HTTPAPIError(HTTPError):
                     """API error handling exception

                     API server always returns formatted JSON to client even there is
                     an internal server error.
                     """
                     def __init__(self, status_code=400, error_detail="", error_type="",
                                  notification="", response="", log_message=None, *args):

                         super(HTTPAPIError, self).__init__(int(status_code), log_message, *args)

                         self.error_type = error_type if error_type else 
                             _error_types.get(self.status_code, "unknow_error")
                         self.error_detail = error_detail
                         self.notification = {"message": notification} if notification else {}
                         self.response = response if response else {}

                     def __str__(self):
                         err = {"meta": {"code": self.status_code, "errorType": self.error_type}}
                         self._set_err(err, ["notification", "response"])

                         if self.error_detail:
                             err["meta"]["errorDetail"] = self.error_detail

                         return escape.json_encode(err)



12年10月14⽇日星期⽇日
12年10月14⽇日星期⽇日
12年10月14⽇日星期⽇日
12年10月14⽇日星期⽇日
12年10月14⽇日星期⽇日
⺴⽹网⻚页抓取

                 def update_server_status():
                     url = options.d3_server_status_url
                     req = HTTPRequest(url=url)

                     client = HTTPClient()
                     response = client.fetch(req)
                     if response.code == 200:
                         status = _parse_server_status(response.body)




12年10月14⽇日星期⽇日
⺴⽹网⻚页解析
                 def _parse_server_status(body):
                     status = {}

                     q = pq(etree.fromstring(body))
                     boxes = q(".box") # category box
                     for box in boxes:
                         box_q = pq(etree.fromstring(etree.tostring(box)))
                         category = box_q(".category")[0].text.strip()
                         status[category] = {}
                         servers = box_q(".server")
                         for server in servers:
                             server_q = pq(etree.fromstring(etree.tostring(server)))
                             server_name = server_q(".server-name")[0].text.strip().replace(" ", "")
                             if server_name:
                                 status_icon = server_q(".status-icon")[0]
                                 class_ = status_icon.get("class")
                                 if class_:
                                     st = 0
                                     if "up" in class_:
                                         st = 1
                                     status[category][server_name] = st

                     return status




12年10月14⽇日星期⽇日
@task
                                        任务队列
        def status_notification_task(changed_status):
            status_notifciation(changed_status)



        def status_notifciation(changed_status):
            notifications = {}
            for category, services in changed_status.iteritems():
                for name, st in services.iteritems():
                    # just push notification about game server now
                    if name == "GameServer":
                        notifications[category] = st

            for category, st in notifications.iteritems():
                status = "Available" if st else "Unavailable"

                 offset = 0
                 limit = 200
                 while True:
                     subscribers = load_model("subscribers").get_subscribers(limit, offset)
                     if not subscribers:
                         break

                     for subscribe in subscribers:
                         if category in subscribe.categorys:
                             alert = _trans_alert("Diablo3 %s server status has changed to %s",
                                                   category, status, subscribe.locale)
                             apns_tasks.apns_push_task.delay(subscribe.token, {},
                                                              alert=alert, badge=1,
                                                              sound="default")
                     offset += len(subscribers)

12年10月14⽇日星期⽇日
其它

                 • Apple push notification
                 • i18n
                 • crontab


12年10月14⽇日星期⽇日
相关资源
                 • https://github.com/felinx/d3status
                 • http://www.tornadoweb.org
                 • http://www.tornadoweb.cn
                 • http://tornado.poweredsites.org
                 • http://tornadogists.org
                 • http://en.wikipedia.org/wiki/
                   Representational_state_transfer
12年10月14⽇日星期⽇日
Q&A

                    @⻜飞⻰龙⾮非⻰龙

                 http://feilong.me/




12年10月14⽇日星期⽇日

Mais conteúdo relacionado

Mais procurados

Webrtc mojo
Webrtc mojoWebrtc mojo
Webrtc mojobpmedley
 
Tornado web
Tornado webTornado web
Tornado webkurtiss
 
Tornado - different Web programming
Tornado - different Web programmingTornado - different Web programming
Tornado - different Web programmingDima Malenko
 
Perl web frameworks
Perl web frameworksPerl web frameworks
Perl web frameworksdiego_k
 
Python, async web frameworks, and MongoDB
Python, async web frameworks, and MongoDBPython, async web frameworks, and MongoDB
Python, async web frameworks, and MongoDBemptysquare
 
Doctrine MongoDB ODM (PDXPHP)
Doctrine MongoDB ODM (PDXPHP)Doctrine MongoDB ODM (PDXPHP)
Doctrine MongoDB ODM (PDXPHP)Kris Wallsmith
 
Building Web Services with Zend Framework (PHP Benelux meeting 20100713 Vliss...
Building Web Services with Zend Framework (PHP Benelux meeting 20100713 Vliss...Building Web Services with Zend Framework (PHP Benelux meeting 20100713 Vliss...
Building Web Services with Zend Framework (PHP Benelux meeting 20100713 Vliss...King Foo
 
Nginx + Tornado = 17k req/s
Nginx + Tornado = 17k req/sNginx + Tornado = 17k req/s
Nginx + Tornado = 17k req/smoret1979
 
An Introduction to Tornado
An Introduction to TornadoAn Introduction to Tornado
An Introduction to TornadoGavin Roy
 
News of the Symfony2 World
News of the Symfony2 WorldNews of the Symfony2 World
News of the Symfony2 WorldFabien Potencier
 
Building Web Apps with Express
Building Web Apps with ExpressBuilding Web Apps with Express
Building Web Apps with ExpressAaron Stannard
 
Introducing Assetic: Asset Management for PHP 5.3
Introducing Assetic: Asset Management for PHP 5.3Introducing Assetic: Asset Management for PHP 5.3
Introducing Assetic: Asset Management for PHP 5.3Kris Wallsmith
 
Keeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro frameworkKeeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro frameworkJeremy Kendall
 
Tornado Web Server Internals
Tornado Web Server InternalsTornado Web Server Internals
Tornado Web Server InternalsPraveen Gollakota
 
Phl mongo-philly-tornado-2011
Phl mongo-philly-tornado-2011Phl mongo-philly-tornado-2011
Phl mongo-philly-tornado-2011hangxin1940
 
Trading with opensource tools, two years later
Trading with opensource tools, two years laterTrading with opensource tools, two years later
Trading with opensource tools, two years laterclkao
 
HTTP Caching and PHP
HTTP Caching and PHPHTTP Caching and PHP
HTTP Caching and PHPDavid de Boer
 

Mais procurados (20)

Webrtc mojo
Webrtc mojoWebrtc mojo
Webrtc mojo
 
Symfony 2.0 on PHP 5.3
Symfony 2.0 on PHP 5.3Symfony 2.0 on PHP 5.3
Symfony 2.0 on PHP 5.3
 
Tornado web
Tornado webTornado web
Tornado web
 
Tornado - different Web programming
Tornado - different Web programmingTornado - different Web programming
Tornado - different Web programming
 
Perl web frameworks
Perl web frameworksPerl web frameworks
Perl web frameworks
 
Python, async web frameworks, and MongoDB
Python, async web frameworks, and MongoDBPython, async web frameworks, and MongoDB
Python, async web frameworks, and MongoDB
 
Doctrine MongoDB ODM (PDXPHP)
Doctrine MongoDB ODM (PDXPHP)Doctrine MongoDB ODM (PDXPHP)
Doctrine MongoDB ODM (PDXPHP)
 
Building Web Services with Zend Framework (PHP Benelux meeting 20100713 Vliss...
Building Web Services with Zend Framework (PHP Benelux meeting 20100713 Vliss...Building Web Services with Zend Framework (PHP Benelux meeting 20100713 Vliss...
Building Web Services with Zend Framework (PHP Benelux meeting 20100713 Vliss...
 
Mojo as a_client
Mojo as a_clientMojo as a_client
Mojo as a_client
 
Nginx + Tornado = 17k req/s
Nginx + Tornado = 17k req/sNginx + Tornado = 17k req/s
Nginx + Tornado = 17k req/s
 
An Introduction to Tornado
An Introduction to TornadoAn Introduction to Tornado
An Introduction to Tornado
 
News of the Symfony2 World
News of the Symfony2 WorldNews of the Symfony2 World
News of the Symfony2 World
 
Building Web Apps with Express
Building Web Apps with ExpressBuilding Web Apps with Express
Building Web Apps with Express
 
Tornadoweb
TornadowebTornadoweb
Tornadoweb
 
Introducing Assetic: Asset Management for PHP 5.3
Introducing Assetic: Asset Management for PHP 5.3Introducing Assetic: Asset Management for PHP 5.3
Introducing Assetic: Asset Management for PHP 5.3
 
Keeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro frameworkKeeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro framework
 
Tornado Web Server Internals
Tornado Web Server InternalsTornado Web Server Internals
Tornado Web Server Internals
 
Phl mongo-philly-tornado-2011
Phl mongo-philly-tornado-2011Phl mongo-philly-tornado-2011
Phl mongo-philly-tornado-2011
 
Trading with opensource tools, two years later
Trading with opensource tools, two years laterTrading with opensource tools, two years later
Trading with opensource tools, two years later
 
HTTP Caching and PHP
HTTP Caching and PHPHTTP Caching and PHP
HTTP Caching and PHP
 

Semelhante a 用Tornado开发RESTful API运用

Python magicmethods
Python magicmethodsPython magicmethods
Python magicmethodsdreampuf
 
Tools for Making Machine Learning more Reactive
Tools for Making Machine Learning more ReactiveTools for Making Machine Learning more Reactive
Tools for Making Machine Learning more ReactiveJeff Smith
 
Pruebas unitarias con django
Pruebas unitarias con djangoPruebas unitarias con django
Pruebas unitarias con djangoTomás Henríquez
 
PhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsPhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsBastian Feder
 
Flask patterns
Flask patternsFlask patterns
Flask patternsit-people
 
The Rule of 10,000 Spark Jobs: Learning From Exceptions and Serializing Your ...
The Rule of 10,000 Spark Jobs: Learning From Exceptions and Serializing Your ...The Rule of 10,000 Spark Jobs: Learning From Exceptions and Serializing Your ...
The Rule of 10,000 Spark Jobs: Learning From Exceptions and Serializing Your ...Databricks
 
The Rule of 10,000 Spark Jobs - Learning from Exceptions and Serializing Your...
The Rule of 10,000 Spark Jobs - Learning from Exceptions and Serializing Your...The Rule of 10,000 Spark Jobs - Learning from Exceptions and Serializing Your...
The Rule of 10,000 Spark Jobs - Learning from Exceptions and Serializing Your...Matthew Tovbin
 
Alexey Tsoy Meta Programming in C++ 16.11.17
Alexey Tsoy Meta Programming in C++ 16.11.17Alexey Tsoy Meta Programming in C++ 16.11.17
Alexey Tsoy Meta Programming in C++ 16.11.17LogeekNightUkraine
 
Jython: Python para la plataforma Java (EL2009)
Jython: Python para la plataforma Java (EL2009)Jython: Python para la plataforma Java (EL2009)
Jython: Python para la plataforma Java (EL2009)Leonardo Soto
 
Web осень 2012 лекция 6
Web осень 2012 лекция 6Web осень 2012 лекция 6
Web осень 2012 лекция 6Technopark
 
Web注入+http漏洞等描述
Web注入+http漏洞等描述Web注入+http漏洞等描述
Web注入+http漏洞等描述fangjiafu
 
Web весна 2013 лекция 6
Web весна 2013 лекция 6Web весна 2013 лекция 6
Web весна 2013 лекция 6Technopark
 
CouchDB on Android
CouchDB on AndroidCouchDB on Android
CouchDB on AndroidSven Haiges
 
international PHP2011_Bastian Feder_jQuery's Secrets
international PHP2011_Bastian Feder_jQuery's Secretsinternational PHP2011_Bastian Feder_jQuery's Secrets
international PHP2011_Bastian Feder_jQuery's Secretssmueller_sandsmedia
 
Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Elena Kolevska
 
Jython: Python para la plataforma Java (JRSL 09)
Jython: Python para la plataforma Java (JRSL 09)Jython: Python para la plataforma Java (JRSL 09)
Jython: Python para la plataforma Java (JRSL 09)Leonardo Soto
 
Testing My Patience
Testing My PatienceTesting My Patience
Testing My PatienceAdam Lowry
 
And the Greatest of These Is ... Rack Support
And the Greatest of These Is ... Rack SupportAnd the Greatest of These Is ... Rack Support
And the Greatest of These Is ... Rack SupportBen Scofield
 

Semelhante a 用Tornado开发RESTful API运用 (20)

Python magicmethods
Python magicmethodsPython magicmethods
Python magicmethods
 
Tools for Making Machine Learning more Reactive
Tools for Making Machine Learning more ReactiveTools for Making Machine Learning more Reactive
Tools for Making Machine Learning more Reactive
 
Pruebas unitarias con django
Pruebas unitarias con djangoPruebas unitarias con django
Pruebas unitarias con django
 
PhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsPhpUnit - The most unknown Parts
PhpUnit - The most unknown Parts
 
Flask patterns
Flask patternsFlask patterns
Flask patterns
 
The Rule of 10,000 Spark Jobs: Learning From Exceptions and Serializing Your ...
The Rule of 10,000 Spark Jobs: Learning From Exceptions and Serializing Your ...The Rule of 10,000 Spark Jobs: Learning From Exceptions and Serializing Your ...
The Rule of 10,000 Spark Jobs: Learning From Exceptions and Serializing Your ...
 
The Rule of 10,000 Spark Jobs - Learning from Exceptions and Serializing Your...
The Rule of 10,000 Spark Jobs - Learning from Exceptions and Serializing Your...The Rule of 10,000 Spark Jobs - Learning from Exceptions and Serializing Your...
The Rule of 10,000 Spark Jobs - Learning from Exceptions and Serializing Your...
 
Alexey Tsoy Meta Programming in C++ 16.11.17
Alexey Tsoy Meta Programming in C++ 16.11.17Alexey Tsoy Meta Programming in C++ 16.11.17
Alexey Tsoy Meta Programming in C++ 16.11.17
 
Jython: Python para la plataforma Java (EL2009)
Jython: Python para la plataforma Java (EL2009)Jython: Python para la plataforma Java (EL2009)
Jython: Python para la plataforma Java (EL2009)
 
Web осень 2012 лекция 6
Web осень 2012 лекция 6Web осень 2012 лекция 6
Web осень 2012 лекция 6
 
Web注入+http漏洞等描述
Web注入+http漏洞等描述Web注入+http漏洞等描述
Web注入+http漏洞等描述
 
Web весна 2013 лекция 6
Web весна 2013 лекция 6Web весна 2013 лекция 6
Web весна 2013 лекция 6
 
SDC - Einführung in Scala
SDC - Einführung in ScalaSDC - Einführung in Scala
SDC - Einführung in Scala
 
CouchDB on Android
CouchDB on AndroidCouchDB on Android
CouchDB on Android
 
international PHP2011_Bastian Feder_jQuery's Secrets
international PHP2011_Bastian Feder_jQuery's Secretsinternational PHP2011_Bastian Feder_jQuery's Secrets
international PHP2011_Bastian Feder_jQuery's Secrets
 
Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5
 
Nantes Jug - Java 7
Nantes Jug - Java 7Nantes Jug - Java 7
Nantes Jug - Java 7
 
Jython: Python para la plataforma Java (JRSL 09)
Jython: Python para la plataforma Java (JRSL 09)Jython: Python para la plataforma Java (JRSL 09)
Jython: Python para la plataforma Java (JRSL 09)
 
Testing My Patience
Testing My PatienceTesting My Patience
Testing My Patience
 
And the Greatest of These Is ... Rack Support
And the Greatest of These Is ... Rack SupportAnd the Greatest of These Is ... Rack Support
And the Greatest of These Is ... Rack Support
 

Último

Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...gurkirankumar98700
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 

Último (20)

Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 

用Tornado开发RESTful API运用

  • 1. ⽤用Tornado开发RESTful API运⽤用 ⻜飞⻰龙⾮非⻰龙 (http://feilong.me) 2012/10/20 12年10月14⽇日星期⽇日
  • 2. 议程 • RESTful API简介 • ⽤用Tornado开发RESTful API应⽤用 • D3status demo APP 12年10月14⽇日星期⽇日
  • 4. Service Resource Service API Clients 12年10月14⽇日星期⽇日
  • 5. RESTful API OAuth HTTPS GET/POST App Platform JSON/JSONP 12年10月14⽇日星期⽇日
  • 6. RESTful and HTTP Verbs Level 0 GET POST PUT DELETE PATCH Level 1 GET POST PUT DELETE PATCH Level 2 GET POST PUT DELETE PATCH 12年10月14⽇日星期⽇日
  • 7. RESTful in Tornado class RequestHandler(object): """Subclass this class and define get() or post() to make a handler. If you want to support more methods than the standard GET/HEAD/POST, you should override the class variable SUPPORTED_METHODS in your RequestHandler class. """ SUPPORTED_METHODS = ("GET", "HEAD", "POST", "DELETE", "PATCH", "PUT", "OPTIONS") def head(self, *args, **kwargs): raise HTTPError(405) def get(self, *args, **kwargs): raise HTTPError(405) def post(self, *args, **kwargs): raise HTTPError(405) def delete(self, *args, **kwargs): raise HTTPError(405) def patch(self, *args, **kwargs): raise HTTPError(405) def put(self, *args, **kwargs): raise HTTPError(405) def options(self, *args, **kwargs): raise HTTPError(405) 12年10月14⽇日星期⽇日
  • 8. JSON & JSONP class APIHandler(BaseHandler): def finish(self, chunk=None, notification=None): if chunk is None: chunk = {} if isinstance(chunk, dict): chunk = {"meta": {"code": 200}, "response": chunk} if notification: chunk["notification"] = {"message": notification} callback = escape.utf8(self.get_argument("callback", None)) if callback: self.set_header("Content-Type", "application/x-javascript") if isinstance(chunk, dict): chunk = escape.json_encode(chunk) self._write_buffer = [callback, "(", chunk, ")"] if chunk else [] super(APIHandler, self).finish() else: self.set_header("Content-Type", "application/json; charset=UTF-8") super(APIHandler, self).finish(chunk) 12年10月14⽇日星期⽇日
  • 9. Exception def write_error(self, status_code, **kwargs): """Override to implement custom error pages.""" debug = self.settings.get("debug", False) try: exc_info = kwargs.pop('exc_info') e = exc_info[1] if isinstance(e, exceptions.HTTPAPIError): pass elif isinstance(e, HTTPError): e = exceptions.HTTPAPIError(e.status_code) else: e = exceptions.HTTPAPIError(500) exception = "".join([ln for ln in traceback.format_exception(*exc_info)]) if status_code == 500 and not debug: self._send_error_email(exception) if debug: e.response["exception"] = exception self.clear() self.set_status(200) # always return 200 OK for API errors self.set_header("Content-Type", "application/json; charset=UTF-8") self.finish(str(e)) except Exception: logging.error(traceback.format_exc()) return super(APIHandler, self).write_error(status_code, **kwargs) 12年10月14⽇日星期⽇日
  • 10. Exception class HTTPAPIError(HTTPError): """API error handling exception API server always returns formatted JSON to client even there is an internal server error. """ def __init__(self, status_code=400, error_detail="", error_type="", notification="", response="", log_message=None, *args): super(HTTPAPIError, self).__init__(int(status_code), log_message, *args) self.error_type = error_type if error_type else _error_types.get(self.status_code, "unknow_error") self.error_detail = error_detail self.notification = {"message": notification} if notification else {} self.response = response if response else {} def __str__(self): err = {"meta": {"code": self.status_code, "errorType": self.error_type}} self._set_err(err, ["notification", "response"]) if self.error_detail: err["meta"]["errorDetail"] = self.error_detail return escape.json_encode(err) 12年10月14⽇日星期⽇日
  • 15. ⺴⽹网⻚页抓取 def update_server_status(): url = options.d3_server_status_url req = HTTPRequest(url=url) client = HTTPClient() response = client.fetch(req) if response.code == 200: status = _parse_server_status(response.body) 12年10月14⽇日星期⽇日
  • 16. ⺴⽹网⻚页解析 def _parse_server_status(body): status = {} q = pq(etree.fromstring(body)) boxes = q(".box") # category box for box in boxes: box_q = pq(etree.fromstring(etree.tostring(box))) category = box_q(".category")[0].text.strip() status[category] = {} servers = box_q(".server") for server in servers: server_q = pq(etree.fromstring(etree.tostring(server))) server_name = server_q(".server-name")[0].text.strip().replace(" ", "") if server_name: status_icon = server_q(".status-icon")[0] class_ = status_icon.get("class") if class_: st = 0 if "up" in class_: st = 1 status[category][server_name] = st return status 12年10月14⽇日星期⽇日
  • 17. @task 任务队列 def status_notification_task(changed_status): status_notifciation(changed_status) def status_notifciation(changed_status): notifications = {} for category, services in changed_status.iteritems(): for name, st in services.iteritems(): # just push notification about game server now if name == "GameServer": notifications[category] = st for category, st in notifications.iteritems(): status = "Available" if st else "Unavailable" offset = 0 limit = 200 while True: subscribers = load_model("subscribers").get_subscribers(limit, offset) if not subscribers: break for subscribe in subscribers: if category in subscribe.categorys: alert = _trans_alert("Diablo3 %s server status has changed to %s", category, status, subscribe.locale) apns_tasks.apns_push_task.delay(subscribe.token, {}, alert=alert, badge=1, sound="default") offset += len(subscribers) 12年10月14⽇日星期⽇日
  • 18. 其它 • Apple push notification • i18n • crontab 12年10月14⽇日星期⽇日
  • 19. 相关资源 • https://github.com/felinx/d3status • http://www.tornadoweb.org • http://www.tornadoweb.cn • http://tornado.poweredsites.org • http://tornadogists.org • http://en.wikipedia.org/wiki/ Representational_state_transfer 12年10月14⽇日星期⽇日
  • 20. Q&A @⻜飞⻰龙⾮非⻰龙 http://feilong.me/ 12年10月14⽇日星期⽇日