ASGI(非同期サーバゲートウェイインターフェース)の概要

D3be793aaf76ed1915295001712ce0f1?s=47 jrfk
August 31, 2020

 ASGI(非同期サーバゲートウェイインターフェース)の概要

PyCon JP 2020 カンファレンス 資料です。ASGIサーバのソースの公開についてはお待ちください。

D3be793aaf76ed1915295001712ce0f1?s=128

jrfk

August 31, 2020
Tweet

Transcript

  1. "4(*ʢඇಉظαʔόήʔτ΢ΣΠ ΠϯλʔϑΣʔεʣͷ֓ཁ Junya Fukuda

  2. 썡쎕썟썷쎣쎟 •෱ా ൏໵ʢJunya Fukudaʣʢ@JunyaFffʣ •גࣜձࣾ೔ຊγεςϜٕݚʢJSLʣॴଐ •PyCon JP 2020 Gold Sponser

    ʢΦϯϥΠϯϒʔεʹ΋༡ͼʹ͖ͯͶʣ •GEEKLAB.NAGANO •࠷ۙϚΠϯΫϥϑτͰখֶੜ޲͚Youtube഑৴࢝ΊΔ ΪʔΫϥϘ௕໺ϚΠΫϥ
  3. ຊ쏅쏍쏁쏱쏽쎅ྲྀ쎣 •HTTPͷྺ࢙Λ؆୯ʹৼΓฦΓ •WSGIͷྺ࢙ •ASGIͷ࢓༷ͷ͸ͳ͠ʢΫϥΠΞϯτͱαʔόͷίʔυΛަ͑ͯʣ •ASGIΛऔΓר͘ঢ়گ

  4. 쏬쏋쏣썗쏁쏱쏽썿쎾썗쏵 •ͪΐͬͱؾʹͳΔ͚ͲΑ͘෼͔Βͳ͍ଘࡏͷASGI

  5. •ͪΐͬͱؾʹͳΔ͚ͲΑ͘෼͔Βͳ͍ଘࡏͷASGI 쏬쏋쏣썗쏁쏱쏽썿쎾썗쏵

  6. 쏬쏋쏣썗쏁쏱쏽썿쎾썗쏵 •ͪΐͬͱؾʹͳΔ͚ͲΑ͘෼͔Βͳ͍ଘࡏͷASGI

  7. 쏬쏋쏣썗쏁쏱쏽썿쎾썗쏵 •ASGI४ڌͷαʔό΍ϑϨʔϜϫʔΫʹ;Εͯ΋Β͏͖͔͚ͬʹͳΕ͹ʂ •ͪΐͬͱؾʹͳΔ͚ͲΑ͘෼͔Βͳ͍ଘࡏͷASGI

  8. Ωʔϫʔυ

  9. Ωʔϫʔυ ໰͍

  10. 쎷썗쏹썗쏓

  11. 쎷썗쏹썗쏓 ಉظ

  12. ಉظ ඇಉظ 쎷썗쏹썗쏓

  13. ಉظ ඇಉظ 쎷썗쏹썗쏓 ඇಉظαʔόήʔτ΢ΣΠΠϯλʔϑΣʔε "TZODISPOPVT4FSWFS(BUFXBZ*OUFSGBDF

  14. 쎷썗쏹썗쏓 ಉظ ඇಉظ PEP

  15. 쎷썗쏹썗쏓 ಉظ ඇಉظ PEP 1ZUIPO&OIBODFNFOU1SPQPTBM 1ZUIPOͷػೳڧԽͷఏҊ

  16. ໰썛

  17. ໰썛 ඇಉظαʔόͱ͸ʁ ඇಉظαʔόήʔτ΢ΣΠΠϯλʔϑΣʔε "TZODISPOPVT4FSWFS(BUFXBZ*OUFSGBDF

  18. ·ͣ͸͡Ίʹ

  19. )551쎂썻썛썽쎅썡썬쎠썛 •ࠓن֨Խ͞Ε͍ͯΔͷ͸HTTPͷόʔδϣϯ͸ʁ

  20. )551쎂썻썛썽쎅썡썬쎠썛 •ࠓن֨Խ͞Ε͍ͯΔͷ͸HTTPͷόʔδϣϯ͸ʁ •HTTP/1.1 •HTTP/2 •HTTP/3

  21. )551쎂썻썛썽쎅썡썬쎠썛 •ࠓن֨Խ͞Ε͍ͯΔͷ͸HTTPͷόʔδϣϯ͸ʁ •HTTP/1.1 •HTTP/2 •HTTP/3

  22. )551쎂썻썛썽쎅썡썬쎠썛 •HTTPͷඪ४ԽΛ࣌ܥྻʹ •HTTP/1.0 •HTTP/2 •HTTP/3 1990 2000 2010 2020 •HTTP/0.9

    •HTTP/1.1
  23. )551쎂썻썛썽쎅썡썬쎠썛 •HTTP/1.0 •HTTP/2 •HTTP/3 1990 2000 2010 2020 •HTTP/0.9 •HTTP/1.1

    •HTTPͷඪ४ԽΛ࣌ܥྻʹ
  24. )551쎂썻썛썽쎅썡썬쎠썛 •HTTP/1.0 •HTTP/2 •HTTP/3 1990 2000 2010 2020 •HTTP/0.9 •HTTP/1.1

    1997 •HTTPͷඪ४ԽΛ࣌ܥྻʹ
  25. )551쎂썻썛썽쎅썡썬쎠썛 •HTTP/1.0 •HTTP/2 •HTTP/3 1990 2000 2010 2020 •HTTP/0.9 •HTTP/1.1

    1997 1999 •HTTPͷඪ४ԽΛ࣌ܥྻʹ
  26. )551쎂썻썛썽쎅썡썬쎠썛 •HTTP/1.0 •HTTP/2 •HTTP/3 1990 2000 2010 2020 •HTTP/0.9 •HTTP/1.1

    1997 1999 2015 •HTTPͷඪ४ԽΛ࣌ܥྻʹ
  27. )551쎂썻썛썽쎅썡썬쎠썛 •HTTP/1.0 •HTTP/2 •HTTP/3 1990 2000 2010 2020 •HTTP/0.9 •HTTP/1.1

    1997 1999 2015 •HTTPͷඪ४ԽΛ࣌ܥྻʹ ύϑΥʔϚεͷ޲্ʹϑΥʔΧε
  28. )551쎂썻썛썽쎅썡썬쎠썛 •HTTP/1.0 •HTTP/2 •HTTP/3 1990 2000 2010 2020 •HTTP/0.9 •HTTP/1.1

    1997 1999 2015 2020೥ϒϥ΢βͰରԠ࢝·Γͩ͢ •HTTPͷඪ४ԽΛ࣌ܥྻʹ
  29. )551쎂썻썛썽쎅썡썬쎠썛 •HTTP/1.0 •HTTP/2 •HTTP/3 1990 2000 2010 2020 •HTTP/0.9 •HTTP/1.1

    1997 1999 2015 •WebSocket •֦ுػೳ
  30. )551쎂썻썛썽쎅썡썬쎠썛 •HTTP/1.0 •HTTP/2 •HTTP/3 1990 2000 2010 2020 •HTTP/0.9 •HTTP/1.1

    1997 1999 2015 •WebSocket 2011 •WebSocketͷొ৔ʢRFC6455ʣ
  31. 84(* •WSGIͷొ৔ •HTTP/2 2000 2010 2020 •HTTP/1.1 1999 2015 •WebSocket

    2011 2016
  32. 84(* •WSGIͷొ৔ •HTTP/2 2000 2010 2020 •HTTP/1.1 1999 2015 •WebSocket

    2011 WSGI 2003 2016
  33. "4(* •ASGIͷొ৔ •HTTP/2 2000 2010 2020 •HTTP/1.1 1999 2015 •WebSocket

    2011 WSGI 2003 2016
  34. "4(* •ASGIͷొ৔ •HTTP/2 2000 2010 2020 •HTTP/1.1 1999 2015 •WebSocket

    2011 WSGI 2003 2016 ASGI
  35. 84(*"4(*쎅쎿쏧썗쏒 •WSGI͸HTTP1.1Λαϙʔτ •ASGI͸HTTP/1.1͔ΒWebSocketɺHTTP/2 •HTTP/2 2000 2010 2020 •HTTP/1.1 1999 2015

    •WebSocket 2011 WSGI 2003 2016 ASGI
  36. Ͱ͸·ͣ͸84(*ͷ࿩

  37. ಉظ

  38. 84(* •WSGIʢWeb Server Gateway Interfaceʣͷུ

  39. 84(* •WSGIʢWeb Server Gateway Interfaceʣͷུ ΫϥΠΞϯτ

  40. 84(* •WSGIʢWeb Server Gateway Interfaceʣͷུ ΫϥΠΞϯτ 8FCαʔό

  41. 84(* •WSGIʢWeb Server Gateway Interfaceʣͷུ ΫϥΠΞϯτ 8FCαʔό ΞϓϦέʔγϣϯ ϑϨʔϜϫʔΫ

  42. 84(* •WSGIʢWeb Server Gateway Interfaceʣͷུ ΫϥΠΞϯτ 8FCαʔό ΞϓϦέʔγϣϯ ϑϨʔϜϫʔΫ

  43. 84(* •WSGIʢWeb Server Gateway Interfaceʣͷུ ΫϥΠΞϯτ 8FCαʔό ΞϓϦέʔγϣϯ ϑϨʔϜϫʔΫ

  44. 84(* •WSGIʢWeb Server Gateway Interfaceʣͷུ •2003೥ʹPEP 333 ʢ 2010೥ PEP

    3333 Python3ରԠʣ
  45. 84(* •WSGIʢWeb Server Gateway Interfaceʣͷུ •2003೥ʹPEP 333 ʢ 2010೥ PEP

    3333 Python3ରԠʣ IUUQTXXXQZUIPOPSHEFWQFQTQFQ
  46. 84(* •WSGIʢWeb Server Gateway Interfaceʣͷུ •2003೥ʹPEP 333 ʢ 2010೥ PEP

    3333 Python3ରԠʣ IUUQTXXXQZUIPOPSHEFWQFQTQFQ
  47. 84(* •WSGIʢWeb Server Gateway Interfaceʣͷུ •Type͸ʮInformationalʯ •2003೥ʹPEP 333 ʢ 2010೥

    PEP 3333 Python3ରԠʣ ΫϥΠΞϯτ 8FCαʔό ΞϓϦέʔγϣϯ ϑϨʔϜϫʔΫ
  48. 썴쎙썴쎙쎁쎪쎅썶쎘쎂84(*썣썾썤썶쎅썢 •౰࣌ɺWeb Framework͕ᷓΕ͍ͯͨ •Zope, Quixote, Webware, SkunkWeb, PSO, and Twisted

    Web
  49. 84(*쎅໨ࢦ썮썶쎾썗쏵 “Python͸ݱࡏɺZope, Quixote, Webware, SkunkWeb, PSO, Twisted WebͳͲɺଟछଟ༷ͳWebΞϓϦέʔγϣϯϑϨʔϜ ϫʔΫΛތ͍ͬͯ·͢ɻWebϑϨʔϜϫʔΫͷબ୒͸࢖༻Մೳͳ Webαʔόʔͷબ୒Λ੍ݶ͠ɺͦͷٯ΋ಉ༷Ͱ͋ΔͨΊɺ͜ͷ෯

    ޿͍બ୒ࢶ͸৽͍͠PythonϢʔβʔʹͱͬͯ໰୊ʹͳΔՄೳੑ͕ ͋Γ·͢ɻ” - PEP 333 https://www.python.org/dev/peps/pep-0333/#rationale-and-goals
  50. 썴쎙썴쎙쎁쎪쎅썶쎘쎂84(*썣썾썤썶쎅썢 WebαʔόA ϑϨʔϜϫʔΫA ϑϨʔϜϫʔΫB ϑϨʔϜϫʔΫC ϑϨʔϜϫʔΫD WebαʔόB WebαʔόC WebαʔόD

  51. 썴쎙썴쎙쎁쎪쎅썶쎘쎂84(*썣썾썤썶쎅썢 84(* WebαʔόA WebαʔόB WebαʔόC WebαʔόD ϑϨʔϜϫʔΫA ϑϨʔϜϫʔΫB ϑϨʔϜϫʔΫC ϑϨʔϜϫʔΫD

  52. Server Application 84(*ॲཧ쎅ྲྀ쎣

  53. Server Application 84(*ॲཧ쎅ྲྀ쎣 84(*؀ڥม਺

  54. Server Application 쎽썗쏵쏚쏍쎹ม਺ 84(*ॲཧ쎅ྲྀ쎣 84(*؀ڥม਺

  55. Server Application 쎽썗쏵쏚쏍쎹ม਺ 84(*ॲཧ쎅ྲྀ쎣 84(*؀ڥม਺

  56. Server Application 쎽썗쏵쏚쏍쎹ม਺ 84(*ॲཧ쎅ྲྀ쎣 84(*؀ڥม਺

  57. Server Application 쎽썗쏵쏚쏍쎹ม਺ 84(*ॲཧ쎅ྲྀ쎣 84(*؀ڥม਺ )FMMP 8PSME

  58. Server Application 쎽썗쏵쏚쏍쎹ม਺ 84(*ॲཧ쎅ྲྀ쎣 84(*؀ڥม਺ )FMMP 8PSME

  59. Server Application 쎽썗쏵쏚쏍쎹ม਺ 84(*ॲཧ쎅ྲྀ쎣 84(*؀ڥม਺ )FMMP 8PSME ཁٻΛड͚औͬͯԠ౴Λฦ͢୯Ұͷಉظݺͼग़͠

  60. 84(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ def application(environ, start_response): start_response( '200, OK', [('Content-Type', 'text/plain')] )

    return [b'Hello, World']
  61. 84(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ def application(environ, start_response): start_response( '200, OK', [('Content-Type', 'text/plain')] )

    return [b'Hello, World']
  62. 84(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ environ = { "REQUEST_METHOD": "GET", "SCRIPT_NAME": "", "PATH_INFO": "/",

    "QUERY_STRING":"search=red+blue&maximum_price=20", "SERVER_NAME": "www.example.org", "SERVER_PORT": 443, "REMOTE_HOST": "134.56.78.4", "REMOTE_PORT": 1453, "SERVER_PROTOCOL": "HTTP/1.1", "HTTP_HOST": "www.example.org", "HTTP_ACCEPT": "application/json", }
  63. 84(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ def application(environ, start_response): start_response( '200, OK', [('Content-Type', 'text/plain')] )

    return [b'Hello, World']
  64. 84(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ def application(environ, start_response): start_response( '200, OK', [('Content-Type', 'text/plain')] )

    return [b'Hello, World']
  65. 84(*쎿썗쏚 def application(environ, start_response): start_response( '200, OK', [('Content-Type', 'text/plain')] )

    return [b'Hello, World'] 84(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ
  66. 84(*쎿썗쏚 def application(environ, start_response): start_response( '200, OK', [('Content-Type', 'text/plain')] )

    return [b'Hello, World'] 84(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ
  67. 84(*쎿썗쏚 def application(environ, start_response): start_response( '200, OK', [('Content-Type', 'text/plain')] )

    return [b'Hello, World'] 84(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ •WSGI؀ڥม਺ͷ࡞੒
  68. 84(*쎿썗쏚 def application(environ, start_response): start_response( '200, OK', [('Content-Type', 'text/plain')] )

    return [b'Hello, World'] 84(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ •WSGI؀ڥม਺ͷ࡞੒ •WSGIΞϓϦέʔγϣϯ͔Βݺͼग़͞ΕΔίʔϧόοΫؔ਺ͷ࡞੒
  69. 84(*쎿썗쏚 84(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ •WSGI؀ڥม਺ͷ࡞੒ •WSGIΞϓϦέʔγϣϯ͔Βݺͼग़͞ΕΔίʔϧόοΫؔ਺ͷ࡞੒ •WSGIΞϓϦέʔγϣϯͷݺͼग़͠ def application(environ, start_response): start_response( '200,

    OK', [('Content-Type', 'text/plain')] ) return [b'Hello, World']
  70. •WSGI؀ڥม਺ͷ࡞੒ env = {} env['wsgi.version'] = (1, 0) # WSGIͷόʔδϣϯɿܾΊଧͪ

    env['wsgi.url_scheme'] = 'http' # urlͷεΩʔϜ(http/https) # HTTP ϦΫΤετຊମͷόΠτྻΛಡΈग़͢͜ͱ͕Ͱ͖ΔೖྗετϦʔϜ env['wsgi.input'] = io.BytesIO(byte_request) env['wsgi.errors'] = sys.stderr env['wsgi.multithread'] = False env['wsgi.multiprocess'] = False env['wsgi.run_once'] = False env['REQUEST_METHOD'] = request_method # GET env['PATH_INFO'] = path # / env['SERVER_NAME'] = server_name # FQDN env['SERVER_PORT'] = str(port) # 8888 IUUQTXXXQZUIPOPSHEFWQFQTQFQFOWJSPOWBSJBCMFT 84(*쎿썗쏚
  71. •WSGIΞϓϦέʔγϣϯ͔Βݺͼग़͞ΕΔίʔϧόοΫؔ਺ͷ࡞੒ IUUQTXXXQZUIPOPSHEFWQFQTQFQUIFTUBSUSFTQPOTFDBMMBCMF def start_response(status, response_headers, exc_info=None): # ೚ҙͷ಺༰ͷɺWSGIαʔόͰ௥Ճ͢ΔϨεϙϯεϔομ server_headers =

    [ ('Date', 'Sat, 16 Jul 2016 00:00:00 JST'), ('Server', 'HenaWSGIServer 0.1'), ] global headers_set headers_set = [status, response_headers + server_headers] 84(*쎿썗쏚
  72. 84(*쎿썗쏚 •WSGI؀ڥม਺ͱίʔϧόοΫؔ਺ΛҾ਺ͱͨ͠ɺWSGIΞϓϦέʔγϣϯͷݺͼग़͠ byte_response_body = application(env, start_response)

  73. 84(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ def application(environ, start_response): start_response( '200, OK', [('Content-Type', 'text/plain')] )

    return [b'Hello, World'] 84(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ
  74. 84(*쎿썗쏚 •WSGI؀ڥม਺ͱίʔϧόοΫؔ਺ΛҾ਺ͱͨ͠ɺWSGIΞϓϦέʔγϣϯͷݺͼग़͠ byte_response_body = application(env, start_response)

  75. Server Application 84(*ॲཧ쎅ྲྀ쎣

  76. Server Application 84(*ॲཧ쎅ྲྀ쎣 84(*؀ڥม਺

  77. Server Application 쎽썗쏵쏚쏍쎹ม਺ 84(*ॲཧ쎅ྲྀ쎣 84(*؀ڥม਺

  78. Server Application 쎽썗쏵쏚쏍쎹ม਺ 84(*ॲཧ쎅ྲྀ쎣 84(*؀ڥม਺

  79. Server Application 쎽썗쏵쏚쏍쎹ม਺ 84(*ॲཧ쎅ྲྀ쎣 84(*؀ڥม਺

  80. Server Application 쎽썗쏵쏚쏍쎹ม਺ 84(*ॲཧ쎅ྲྀ쎣 84(*؀ڥม਺ )FMMP 8PSME

  81. Server Application 쎽썗쏵쏚쏍쎹ม਺ 84(*ॲཧ쎅ྲྀ쎣 84(*؀ڥม਺ )FMMP 8PSME

  82. Server Application 쎽썗쏵쏚쏍쎹ม਺ 84(*ॲཧ쎅ྲྀ쎣 84(*؀ڥม਺ )FMMP 8PSME ཁٻΛड͚औͬͯԠ౴Λฦ͢୯Ұͷಉظݺͼग़͠

  83. 84(*쎕썿쎘 •WSGI͸ɺαʔόͱϑϨʔϜϫʔΫͷڮ౉͠Λ͢Δڞ௨࢓༷ •WSGI͸ɺཁٻΛड͚औͬͯԠ౴Λฦ͢୯Ұͷಉظݺͼग़͠

  84. 84(*'SBNFXPSL

  85. 84(*4FSWFS mod_wsgi

  86. 84(*쎅՝୊ •asyncio async / await ͷԸܙ •WebSocket HTTP/2.0ରԠ

  87. தؒँࣙ •ϝϞతͳࢥߟతͳ IUUQTUIJOLBNJIBUFOBCMPHDPNFOUSZ •ιʔείʔυ IUUQTHJUIVCDPNUIJOL"NJTBOECPYXTHJ@XFCTFSWFSTBNQMF PythonͰWSGI४ڌͷWebαʔόΛࣗ࡞͠ɺͦͷ্ͰBottleΛಈ͔ͯ͠Έͨ

  88. ͯ͜͜͞Ͱຊηογϣϯͷओ໾ "4(*

  89. ͢΂ͯ͸BTZODBXBJU͔Β࢝·ͬͨ

  90.  IUUQTqPSJNPOEEFWCMPHBSUJDMFTJOUSPEVDUJPOUPBTHJBTZODQZUIPOXFC ͢΂ͯ͸BTZODBXBJU͔Β࢝·ͬͨ

  91. 썰쎐썽쎆BTZODBXBJU썢쎠࢝쎕썺썶 •ඇಉظIOͷͨΊͷڞ௨ίϯϙʔωϯτ͕Pythonʹ௥Ճ •Pyhton 3.4 ʢ2014೥ʣ ΑΓ asyncio Ϟδϡʔϧ •Pyhton 3.5

    ʢ2015೥ʣΑΓ async/await ͕ར༻Մೳʹͳͬͨ
  92. 썰쎐썽쎆BTZODBXBJU썢쎠࢝쎕썺썶 •asyncioɺasync/await ొ৔ޙɺඇಉظͳ Web Framework͕ᷓΕ͍ͯͨ •SANICɺTornadoɺaiohttpɺViboraɺJapronto Japronto!

  93. ͷɺͰ͠ΐ͏͔

  94. 썴쎙썴쎙쎁쎪쎅썶쎘쎂84(*썣썾썤썶쎅썢 ϑϨʔϜϫʔΫA WebαʔόA WebαʔόB WebαʔόC WebαʔόD ϑϨʔϜϫʔΫB ϑϨʔϜϫʔΫC ϑϨʔϜϫʔΫD

  95. 썴쎙썴쎙쎁쎪쎅썶쎘쎂"4(*썣썾썤썶쎅썢 ϑϨʔϜϫʔΫA WebαʔόA WebαʔόB WebαʔόC WebαʔόD ϑϨʔϜϫʔΫB ϑϨʔϜϫʔΫC ϑϨʔϜϫʔΫD "4(*

  96. "4(*쎅ొ৔ •ASGIʢAsynchronous Server Gateway Interfaceʣͷུ

  97. "4(*쎅ొ৔ •ASGIʢAsynchronous Server Gateway Interfaceʣͷུ •2016೥ʹRead the Docs͕ొ৔ - 1,2Λܦͯݱࡏ

    3 Ͱ ࠷৽൛ͷ҆ఆ൛
  98. "4(*쎅ొ৔ •ASGIʢAsynchronous Server Gateway Interfaceʣͷུ •2016೥ʹRead the Docs͕ొ৔ - 1,2Λܦͯݱࡏ

    3 Ͱ ࠷৽൛ͷ҆ఆ൛ •WSGIͷਫ਼ਆతʢεϐϦνϡΞϧʁʣͳޙܧऀʢa spiritual successorʣ
  99. "4(*쎅ొ৔ •ASGIʢAsynchronous Server Gateway Interfaceʣͷུ •HTTP/1.1ɺWebsocketɺHTTP/2ʹରԠ •2016೥ʹRead the Docs͕ొ৔ -

    1,2Λܦͯݱࡏ 3 Ͱ ࠷৽൛ͷ҆ఆ൛ •WSGIͷਫ਼ਆతʢεϐϦνϡΞϧʁʣͳޙܧऀʢa spiritual successorʣ
  100. "4(*쎅ొ৔ •ASGIʢAsynchronous Server Gateway Interfaceʣͷུ •HTTP/1.1ɺWebsocketɺHTTP/2ʹରԠ •2016೥ʹRead the Docs͕ొ৔ -

    1,2Λܦͯݱࡏ 3 Ͱ ࠷৽൛ͷ҆ఆ൛ •WSGIͷਫ਼ਆతʢεϐϦνϡΞϧʁʣͳޙܧऀʢa spiritual successorʣ •·ͩPEPʹ͸ͳ͍ͬͯͳ͍
  101. "4(*쎅ొ৔ •ASGIʢAsynchronous Server Gateway Interfaceʣͷུ •HTTP/1.1ɺWebsocketɺHTTP/2ʹରԠ •2016೥ʹRead the Docs͕ొ৔ -

    1,2Λܦͯݱࡏ 3 Ͱ ࠷৽൛ͷ҆ఆ൛ •WSGIͷਫ਼ਆతʢεϐϦνϡΞϧʁʣͳޙܧऀʢa spiritual successorʣ •·ͩPEPʹ͸ͳ͍ͬͯͳ͍
  102. "4(*쎂썻썛썽3FBEUIF%PDT •WSGIͱޓ׵ͷ͋Δઃܭʹͳ͍ͬͯΔʢasgirefͰWsgiToAsgiͱ͍͏Ξμϓλʔʣ https://asgi.readthedocs.io/en/latest/

  103. "4(*쎂썻썛썽3FBEUIF%PDT •WSGIͱޓ׵ͷ͋Δઃܭʹͳ͍ͬͯΔʢasgirefͰWsgiToAsgiͱ͍͏Ξμϓλʔʣ https://asgi.readthedocs.io/en/latest/ •ASGI ΞϓϦέʔγϣϯ͸ɺasync/await ޓ׵ੑͷ͋ΔίϧʔνϯΛ଴ػ࣮ͯ͠ߦ

  104. "4(*쎂썻썛썽3FBEUIF%PDT •WSGIͱޓ׵ͷ͋Δઃܭʹͳ͍ͬͯΔʢasgirefͰWsgiToAsgiͱ͍͏Ξμϓλʔʣ https://asgi.readthedocs.io/en/latest/ •ASGI ΞϓϦέʔγϣϯ͸ɺasync/await ޓ׵ੑͷ͋ΔίϧʔνϯΛ଴ػ࣮ͯ͠ߦ

  105. "4(*쎂썻썛썽3FBEUIF%PDT •WSGIͱޓ׵ͷ͋Δઃܭʹͳ͍ͬͯΔʢasgirefͰWsgiToAsgiͱ͍͏Ξμϓλʔʣ https://asgi.readthedocs.io/en/latest/ •ASGIΞϓϦέʔγϣϯ͸ɺ୯Ұͷඇಉظݺͼग़͠Մೳ •ASGI ΞϓϦέʔγϣϯ͸ɺasync/await ޓ׵ੑͷ͋ΔίϧʔνϯΛ଴ػ࣮ͯ͠ߦ

  106. "4(*쎂썻썛썽3FBEUIF%PDT •WSGIͱޓ׵ͷ͋Δઃܭʹͳ͍ͬͯΔʢasgirefͰWsgiToAsgiͱ͍͏Ξμϓλʔʣ https://asgi.readthedocs.io/en/latest/ •ASGIΞϓϦέʔγϣϯ͸ɺ୯Ұͷඇಉظݺͼग़͠Մೳ •ASGI ΞϓϦέʔγϣϯ͸ɺasync/await ޓ׵ੑͷ͋ΔίϧʔνϯΛ଴ػ࣮ͯ͠ߦ

  107. "4(*쎂썻썛썽3FBEUIF%PDT •WSGIͱޓ׵ͷ͋Δઃܭʹͳ͍ͬͯΔʢasgirefͰWsgiToAsgiͱ͍͏Ξμϓλʔʣ https://asgi.readthedocs.io/en/latest/ •coroutine application(scope, receive, send) •ASGIΞϓϦέʔγϣϯ͸ɺ୯Ұͷඇಉظݺͼग़͠Մೳ •ASGI ΞϓϦέʔγϣϯ͸ɺasync/await

    ޓ׵ੑͷ͋ΔίϧʔνϯΛ଴ػ࣮ͯ͠ߦ
  108. "4(*쎂썻썛썽3FBEUIF%PDT •WSGIͱޓ׵ͷ͋Δઃܭʹͳ͍ͬͯΔʢasgirefͰWsgiToAsgiͱ͍͏Ξμϓλʔʣ https://asgi.readthedocs.io/en/latest/ •coroutine application(scope, receive, send) •ASGIΞϓϦέʔγϣϯ͸ɺ୯Ұͷඇಉظݺͼग़͠Մೳ •ASGI ΞϓϦέʔγϣϯ͸ɺasync/await

    ޓ׵ੑͷ͋ΔίϧʔνϯΛ଴ػ࣮ͯ͠ߦ
  109. "4(*쎂썻썛썽 •ASGI ͷجຊͷίʔυ͔ΒɺجຊͱͳΔHTTPϦΫΤετͷॲཧΛݟͯΈΔ •ASGIΞϓϦέʔγϣϯ •ASGIαʔό

  110. "4(*쎂썻썛썽3FBEUIF%PDT •ͦͷ΄͔ͷASGIͷ࢓༷ •ASGI sub-specification - Life Span •ASGI Extention -

    HTTP/2 Server Push •ASGI Extention - Websocket Denial Response https://asgi.readthedocs.io/en/latest/
  111. "4(*쎂썻썛썽BTZODJPBTZODBXBJU •͜ͷޙͷίʔυͰ͸ asyncio async/await͕ొ৔͠·͢ɻ •asyncio •ίϧʔνϯ •async/await

  112. "4(*쎂썻썛썽BTZODJPBTZODBXBJU •͜ͷޙͷίʔυͰ͸ asyncio async/await͕ొ৔͠·͢ɻ •asyncio 標準ライブラリに含まれ、コルーチンを活用して主にネットワーク関連の IO処理を非同期に行うためのモジュールです。 •ίϧʔνϯ •async/await

  113. "4(*쎂썻썛썽BTZODJPBTZODBXBJU •͜ͷޙͷίʔυͰ͸ asyncio async/await͕ొ৔͠·͢ɻ •asyncio 標準ライブラリに含まれ、コルーチンを活用して主にネットワーク関連の IO処理を非同期に行うためのモジュールです。 •ίϧʔνϯ •async/await

  114. "4(*쎂썻썛썽BTZODJPBTZODBXBJU •͜ͷޙͷίʔυͰ͸ asyncio async/await͕ొ৔͠·͢ɻ •asyncio •ίϧʔνϯ 処理を明示的に中断し、再開できるタスクを利用して複数の処理を実行すること コルーチンを定義するには async def

    を利用します •async/await 標準ライブラリに含まれ、コルーチンを活用して主にネットワーク関連の IO処理を非同期に行うためのモジュールです。
  115. "4(*쎂썻썛썽BTZODJPBTZODBXBJU •͜ͷޙͷίʔυͰ͸ asyncio async/await͕ొ৔͠·͢ɻ •asyncio •ίϧʔνϯ 処理を明示的に中断し、再開できるタスクを利用して複数の処理を実行すること コルーチンを定義するには async def

    を利用します •async/await 標準ライブラリに含まれ、コルーチンを活用して主にネットワーク関連の IO処理を非同期に行うためのモジュールです。
  116. "4(*쎂썻썛썽BTZODJPBTZODBXBJU •͜ͷޙͷίʔυͰ͸ asyncio async/await͕ొ৔͠·͢ɻ •asyncio •ίϧʔνϯ •async/await async/await構文。asyncでコルーチンを定義し、awaitはコルーチンの 実行結果を取得するために使用します。 処理を明示的に中断し、再開できるタスクを利用して複数の処理を実行すること

    コルーチンを定義するには async def を利用します 標準ライブラリに含まれ、コルーチンを活用して主にネットワーク関連の IO処理を非同期に行うためのモジュールです。
  117. "4(*쎂썻썛썽BTZODJPBTZODBXBJU •͜ͷޙͷίʔυͰ͸ asyncio async/await͕ొ৔͠·͢ɻ •asyncio •ίϧʔνϯ •async/await async/await構文。asyncでコルーチンを定義し、awaitはコルーチンの 実行結果を取得するために使用します。 処理を明示的に中断し、再開できるタスクを利用して複数の処理を実行すること

    コルーチンを定義するには async def を利用します 標準ライブラリに含まれ、コルーチンを活用して主にネットワーク関連の IO処理を非同期に行うためのモジュールです。
  118. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ async def app(scope, receive, send): assert scope['type'] == 'http'

    await send({ 'type': 'http.response.start', 'status': 200, 'headers': [ [b'content-type', b'text/plain'], ] }) await send({ 'type': 'http.response.body', 'body': b'Hello, world!', }) IUUQTXXXVWJDPSOPSH
  119. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ async def app(scope, receive, send): assert scope['type'] == 'http'

    await send({ 'type': 'http.response.start', 'status': 200, 'headers': [ [b'content-type', b'text/plain'], ] }) await send({ 'type': 'http.response.body', 'body': b'Hello, world!', }) IUUQTXXXVWJDPSOPSH
  120. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ async def app(scope, receive, send): assert scope['type'] == 'http'

    await send({ 'type': 'http.response.start', 'status': 200, 'headers': [ [b'content-type', b'text/plain'], ] }) await send({ 'type': 'http.response.body', 'body': b'Hello, world!', }) scope
  121. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ = { "type": "http", "http_version": "2.0", "asgi": { "spec_version":

    "2.1", "version": “3.0", }, "method": "POST", "scheme": "https", "path": "/", "query_string": b"a=b", "headers": [(b"content-length", b"5")], "client": ("10.0.0.0", 1234), "server": ("127.0.0.1", 443), "root_path": ".", } scope IUUQTBTHJSFBEUIFEPDTJPFOMBUFTUTQFDTXXXIUNMIUUQDPOOFDUJPOTDPQF HTTP Connection Scope
  122. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ async def app( , , send): assert scope['type'] ==

    'http' await send({ 'type': 'http.response.start', 'status': 200, 'headers': [ [b'content-type', b'text/plain'], ] }) await send({ 'type': 'http.response.body', 'body': b'Hello, world!', }) receive scope
  123. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ = { "type": "http.request.body", "body": b'{"example": "Some JSON data"}',

    "more_body": False } receive IUUQTBTHJSFBEUIFEPDTJPFOMBUFTUTQFDTXXXIUNMSFRVFTUSFDFJWFFWFOU Request - receive event
  124. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ = { "type": "http.request.body", "body": b'{"example": "Some JSON data"}',

    "more_body": False } receive IUUQTBTHJSFBEUIFEPDTJPFOMBUFTUTQFDTXXXIUNMSFRVFTUSFDFJWFFWFOU Request - receive event
  125. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ = { "type": "http.request.body", "body": b'{"example": "Some JSON data"}',

    "more_body": False } receive IUUQTBTHJSFBEUIFEPDTJPFOMBUFTUTQFDTXXXIUNMSFRVFTUSFDFJWFFWFOU Request - receive event
  126. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ receive async def app(scope, receive, send): assert scope[“type”] ==

    “http” await send({ 'type': 'http.response.start', 'status': 200, 'headers': [ [b'content-type', b'text/plain'], ] }) await send({ 'type': 'http.response.body', 'body': b'Hello, world!', })
  127. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ async def app(scope, receive, send): assert scope[“type”] == “http”

    await send({ 'type': 'http.response.start', 'status': 200, 'headers': [ [b'content-type', b'text/plain'], ] }) await send({ 'type': 'http.response.body', 'body': b'Hello, world!', }) IUUQTBTHJSFBEUIFEPDTJPFOMBUFTUTQFDTXXXIUNMSFTQPOTFTUBSUTFOEFWFOU Response Start - send event
  128. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ async def app(scope, receive, send): assert scope[“type”] == “http”

    await send({ 'type': 'http.response.start', 'status': 200, 'headers': [ [b'content-type', b'text/plain'], ] }) await send({ 'type': 'http.response.body', 'body': b'Hello, world!', }) IUUQTBTHJSFBEUIFEPDTJPFOMBUFTUTQFDTXXXIUNMSFTQPOTFTUBSUTFOEFWFOU Response Start - send event
  129. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ async def app(scope, receive, send): assert scope[“type”] == “http”

    await send({ 'type': 'http.response.start', 'status': 200, 'headers': [ [b'content-type', b'text/plain'], ] }) await send({ 'type': 'http.response.body', 'body': b'Hello, world!', ‘more_body’: })
  130. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ async def app(scope, receive, send): assert scope[“type”] == “http”

    await send({ 'type': 'http.response.start', 'status': 200, 'headers': [ [b'content-type', b'text/plain'], ] }) await send({ 'type': 'http.response.body', 'body': b'Hello, world!', ‘more_body’: }) False
  131. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ async def app(scope, receive, send): assert scope[“type”] == “http”

    await send({ 'type': 'http.response.start', 'status': 200, 'headers': [ [b'content-type', b'text/plain'], ] }) await send({ 'type': 'http.response.body', 'body': b'Hello, world!', })
  132. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅쎦썢썺썶썪썿 •Ҿ਺͸3ͭ •Scope ɿ ΫϥΠΞϯτ͔ΒͷϦΫΤετͷ৘ใؚ͕·Ε͍ͯΔʢWSGIͷenvironʹ ֘౰ʣ •recieveɿαʔό͔ΒͷϘσΟͷ৘ใΛड͚औΓͦ͏ͩ •sendɿԠ౴։࢝ͷsend ͱ Ԡ౴ຊମͷsend

    IUUQTBTHJSFBEUIFEPDTJPFOMBUFTUTQFDTXXXIUNMIUUQDPOOFDUJPOTDPQF HTTP & WebSocket ASGI Message Format - HTTP
  133. Ͱ͸ଓ͍ͯ αʔόଆͷίʔυ

  134. "4(*FDIP8FC쎿썗쏚 •γϯϓϧͳαʔόͷྫͱͯ͠ɺEuro Python 2020 IUUQTZPVUVCF(QRY6*8KJX U

  135. •Philip JonesʢPG Jonesʣ "4(*FDIP8FC쎿썗쏚

  136. •Philip JonesʢPG Jonesʣ "4(*FDIP8FC쎿썗쏚

  137. •Philip JonesʢPG Jonesʣ "4(*FDIP8FC쎿썗쏚

  138. •Philip JonesʢPG Jonesʣ •ASGI Read the Docs ίϛολʔ "4(*FDIP8FC쎿썗쏚

  139. •HTTP1.1ରԠͷASGIαʔόɻߏ੒ͱͯ͠͸େ͖͘ҎԼͷ5ͭɻ •create_scope ؔ਺ɿscopeΛ࡞ΔʢASGIΞϓϦͷୈҰҾ਺Λ࡞Δʣ •create_message ؔ਺ɿreceive༻ͷϝοηʔδΛ࡞ΔʢASGIΞϓϦͷୈ̎Ҿ਺ʣ •mainॲཧɾmainίϧʔνϯɿasyncio Ͱcreateserver •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ •class

    HTTPParser: HTTPͷϦΫΤετΛύʔε͢Δ "4(*FDIP8FC쎿썗쏚
  140. •HTTP1.1ରԠͷASGIαʔόɻߏ੒ͱͯ͠͸େ͖͘ҎԼͷ5ͭɻ •create_scope ؔ਺ɿscopeΛ࡞ΔʢASGIΞϓϦͷୈҰҾ਺Λ࡞Δʣ •create_message ؔ਺ɿreceive༻ͷϝοηʔδΛ࡞ΔʢASGIΞϓϦͷୈ̎Ҿ਺ʣ •mainॲཧɾmainίϧʔνϯɿasyncio Ͱcreateserver •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ •class

    HTTPParser: HTTPͷϦΫΤετΛύʔε͢Δ "4(*FDIP8FC쎿썗쏚
  141. •import import asyncio import sys "4(*FDIP8FC쎿썗쏚

  142. •class HTTPParser: HTTPͷϦΫΤετΛύʔε͢Δ class HTTPParser: def __init__(self): self.part = "REQUEST"

    self.headers = [] self.body_length = 0 def feed_line(self, line: bytes): if self.part == "REQUEST": self.method, self.path, self.version = line.split(b" ", 2) self.part = "HEADERS" elif self.part == "HEADERS" and line.strip() == b"": self.part = "BODY" elif self.part == "HEADERS": name, value = line.split(b":", 1) self.headers.append((name.strip(), value.strip())) if name.lower() == b"content-length": self.body_length = int(value) "4(*FDIP8FC쎿썗쏚
  143. def create_scope(parser): return { "type": "http", "method": parser.method, "asgi": {

    "spec_version": "2.1", "version": "3.0", }, "scheme": "http", "raw_path": parser.path, "path": parser.path.decode(), "headers": parser.headers, } •create_scope ؔ਺ɿscopeΛ࡞ΔʢASGIΞϓϦͷୈҰҾ਺Λ࡞Δʣ "4(*FDIP8FC쎿썗쏚
  144. def create_message(body, more_body): return { "type": "http.request", "body": body, "more_body":

    more_body, } •create_message ؔ਺ɿreceive༻ͷϝοηʔδΛ࡞ΔʢASGIΞϓϦͷୈ̎Ҿ਺ʣ "4(*FDIP8FC쎿썗쏚
  145. if __name__ == "__main__": if len(sys.argv) < 2: sys.exit('"module:callable"ͷܗͰASGIΞϓϦέʔγϣϯΛࢦఆ͍ͯͩ͘͠͞') host,

    port = 'localhost', 8888 app_path = sys.argv[1] module, application = app_path.split(':') module = __import__(module) asgi_app = getattr(module, application) global app app = asgi_app asyncio.run(main(host, port)) •mainॲཧɾmainίϧʔνϯɿasyncio Ͱcreateserver "4(*FDIP8FC쎿썗쏚
  146. async def main(host, port): server = await asyncio.start_server(asgi_http_parser_server, host, port)

    await server.serve_forever() •mainॲཧɾmainίϧʔνϯɿasyncio Ͱcreateserver "4(*FDIP8FC쎿썗쏚
  147. async def main(host, port): server = await asyncio.start_server(asgi_http_parser_server, host, port)

    await server.serve_forever() •mainॲཧɾmainίϧʔνϯɿasyncio Ͱcreateserver "4(*FDIP8FC쎿썗쏚
  148. async def main(host, port): server = await asyncio.start_server(asgi_http_parser_server, host, port)

    await server.serve_forever() •mainॲཧɾmainίϧʔνϯɿasyncio Ͱcreateserver "4(*FDIP8FC쎿썗쏚
  149. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ •গ͠௕͍ͷͰ̐෼ׂ͠·͢ʢ40ߦ͙Β͍Ͱ͢ʣ "4(*FDIP8FC쎿썗쏚

  150. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ async def asgi_http_parser_server(reader, writer): parser = HTTPParser() receive

    = asyncio.Queue() read = 0 while not reader.at_eof(): if parser.part != "BODY": parser.feed_line(await reader.readline()) elif parser.body_length == 0: await receive.put(create_message(b"", False)) break else: body = await reader.read(100) read += len(body) await receive.put(create_message(body, read < parser.body_length)) if read >= parser.body_length: break "4(*FDIP8FC쎿썗쏚
  151. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ async def asgi_http_parser_server(reader, writer): parser = HTTPParser() receive

    = asyncio.Queue() read = 0 while not reader.at_eof(): if parser.part != "BODY": parser.feed_line(await reader.readline()) elif parser.body_length == 0: await receive.put(create_message(b"", False)) break else: body = await reader.read(100) read += len(body) await receive.put(create_message(body, read < parser.body_length)) if read >= parser.body_length: break "4(*FDIP8FC쎿썗쏚
  152. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ async def asgi_http_parser_server(reader, writer): parser = HTTPParser() receive

    = asyncio.Queue() read = 0 while not reader.at_eof(): if parser.part != "BODY": parser.feed_line(await reader.readline()) elif parser.body_length == 0: await receive.put(create_message(b"", False)) break else: body = await reader.read(100) read += len(body) await receive.put(create_message(body, read < parser.body_length)) if read >= parser.body_length: break "4(*FDIP8FC쎿썗쏚
  153. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ # httpͷϦΫΤετͷparser͔ΒscopeΛ࡞Δ scope = create_scope(parser) "4(*FDIP8FC쎿썗쏚

  154. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ # httpͷϦΫΤετͷparser͔ΒscopeΛ࡞Δ scope = create_scope(parser) { "type": "http",

    "http_version": "2.0", "asgi": { "spec_version": "2.1", "version": “3.0", }, "method": "POST", "scheme": "https", "path": "/", "query_string": b"a=b", "headers": [(b"content-length", b"5")], "client": ("10.0.0.0", 1234), "server": ("127.0.0.1", 443), "root_path": ".", } "4(*FDIP8FC쎿썗쏚
  155. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ send = asyncio.Queue() await app(scope, receive.get, send.put) "4(*FDIP8FC쎿썗쏚

  156. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ send = asyncio.Queue() await app(scope, receive.get, send.put) "4(*FDIP8FC쎿썗쏚

  157. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ send = asyncio.Queue() await app(scope, receive.get, send.put) "4(*FDIP8FC쎿썗쏚

  158. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ send = asyncio.Queue() await app(scope, receive.get, send.put) "4(*FDIP8FC쎿썗쏚

  159. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ send = asyncio.Queue() await app(scope, receive.get, send.put) "4(*FDIP8FC쎿썗쏚

  160. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ while True: message = await send.get() if message["type"]

    == "http.response.start": writer.write(b"HTTP/1.1 %d\r\n" % message["status"]) for header in message["headers"]: writer.write(b"%s: %s\r\n" % (header)) writer.write(b"\r\n") elif message["type"] == "http.response.body": if message.get("body") is not None: writer.write(message["body"]) writer.write(b"\r\n") if not message.get("more_body", False): break "4(*FDIP8FC쎿썗쏚
  161. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ while True: message = await send.get() if message["type"]

    == "http.response.start": writer.write(b"HTTP/1.1 %d\r\n" % message["status"]) for header in message["headers"]: writer.write(b"%s: %s\r\n" % (header)) writer.write(b"\r\n") elif message["type"] == "http.response.body": if message.get("body") is not None: writer.write(message["body"]) writer.write(b"\r\n") if not message.get("more_body", False): break "4(*FDIP8FC쎿썗쏚
  162. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ while True: message = await send.get() if message["type"]

    == "http.response.start": writer.write(b"HTTP/1.1 %d\r\n" % message["status"]) for header in message["headers"]: writer.write(b"%s: %s\r\n" % (header)) writer.write(b"\r\n") elif message[“type"] == "http.response.body": if message.get("body") is not None: writer.write(message["body"]) writer.write(b"\r\n") if not message.get("more_body", False): break "4(*FDIP8FC쎿썗쏚
  163. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ while True: message = await send.get() if message["type"]

    == "http.response.start": writer.write(b"HTTP/1.1 %d\r\n" % message["status"]) for header in message["headers"]: writer.write(b"%s: %s\r\n" % (header)) writer.write(b"\r\n") elif message[“type"] == "http.response.body": if message.get("body") is not None: writer.write(message["body"]) writer.write(b"\r\n") if not message.get("more_body", False): break "4(*FDIP8FC쎿썗쏚
  164. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ while True: message = await send.get() if message["type"]

    == "http.response.start": writer.write(b"HTTP/1.1 %d\r\n" % message["status"]) for header in message["headers"]: writer.write(b"%s: %s\r\n" % (header)) writer.write(b"\r\n") elif message[“type"] == "http.response.body": if message.get("body") is not None: writer.write(message["body"]) writer.write(b"\r\n") if not message.get("more_body", False): break "4(*FDIP8FC쎿썗쏚
  165. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ while True: message = await send.get() if message["type"]

    == "http.response.start": writer.write(b"HTTP/1.1 %d\r\n" % message["status"]) for header in message["headers"]: writer.write(b"%s: %s\r\n" % (header)) writer.write(b"\r\n") elif message["type"] == "http.response.body": if message.get("body") is not None: writer.write(message["body"]) writer.write(b"\r\n") if not message.get("more_body", False): break "4(*FDIP8FC쎿썗쏚
  166. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ while True: message = await send.get() if message["type"]

    == "http.response.start": writer.write(b"HTTP/1.1 %d\r\n" % message["status"]) for header in message["headers"]: writer.write(b"%s: %s\r\n" % (header)) writer.write(b"\r\n") elif message["type"] == "http.response.body": if message.get("body") is not None: writer.write(message["body"]) writer.write(b"\r\n") if not message.get("more_body", False): break "4(*FDIP8FC쎿썗쏚
  167. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ while True: message = await send.get() if message["type"]

    == "http.response.start": writer.write(b"HTTP/1.1 %d\r\n" % message["status"]) for header in message["headers"]: writer.write(b"%s: %s\r\n" % (header)) writer.write(b"\r\n") elif message["type"] == "http.response.body": if message.get("body") is not None: writer.write(message["body"]) writer.write(b"\r\n") if not message.get("more_body", False): break "4(*FDIP8FC쎿썗쏚
  168. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ while True: message = await send.get() if message["type"]

    == "http.response.start": writer.write(b"HTTP/1.1 %d\r\n" % message["status"]) for header in message["headers"]: writer.write(b"%s: %s\r\n" % (header)) writer.write(b"\r\n") elif message["type"] == "http.response.body": if message.get("body") is not None: writer.write(message["body"]) writer.write(b"\r\n") if not message.get("more_body", False): break "4(*FDIP8FC쎿썗쏚
  169. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ await writer.drain() writer.close() "4(*FDIP8FC쎿썗쏚

  170. "4(*FDIP8FC쎿썗쏚쎕썿쎘 •࢓༷ʹͦͬͨ3ͭͷҾ਺ʢscope,receive,sendʣ •async/await ͰΞϓϦέʔγϣϯͱ΍ΓͱΓ •ίϧʔνϯͷதʹɺreceiveɺsendͷϧʔϓॲཧ •୯Ұͷඇಉظݺͼग़͠

  171. "4(*FDIP8FC쎿썗쏚쎕썿쎘 •࢓༷ʹͦͬͨ3ͭͷҾ਺ʢscope,receive,sendʣ •async/await ͰΞϓϦέʔγϣϯͱ΍ΓͱΓ •ίϧʔνϯͷதʹɺreceiveɺsendͷϧʔϓॲཧ •୯Ұͷඇಉظݺͼग़͠

  172. "4(*)551쏫쏍쏅썗쏂 Server Application

  173. "4(*)551쏫쏍쏅썗쏂 Server Application { 'asgi': {'spec_version': ‘2.1', 'version': '3.0'}, ...

    'method': ‘GET', 'type': 'http' }
  174. "4(*)551쏫쏍쏅썗쏂 Server Application { 'asgi': {'spec_version': ‘2.1', 'version': '3.0'}, ...

    'method': ‘GET', 'type': 'http' } { "type": "http.request", "body": b'', "more_body": False }
  175. "4(*)551쏫쏍쏅썗쏂 Server Application { 'asgi': {'spec_version': ‘2.1', 'version': '3.0'}, ...

    'method': ‘GET', 'type': 'http' } { "type": "http.request", "body": b'', "more_body": False } { "type": "http.response.start", "status": 200, "headers": [(b"name", b"value")], }
  176. "4(*)551쏫쏍쏅썗쏂 Server Application { 'asgi': {'spec_version': ‘2.1', 'version': '3.0'}, ...

    'method': ‘GET', 'type': 'http' } { "type": "http.request", "body": b'', "more_body": False } { "type": "http.response.start", "status": 200, "headers": [(b"name", b"value")], } { "type": "http.response.body", "body": b"Hello, World", "more_body": False, }
  177. "4(*)551쏫쏍쏅썗쏂 Server Application { 'asgi': {'spec_version': ‘2.1', 'version': '3.0'}, ...

    'method': ‘GET', 'type': 'http' } { "type": "http.request", "body": b'', "more_body": False } { "type": "http.response.start", "status": 200, "headers": [(b"name", b"value")], } { "type": "http.response.body", "body": b"Hello, World", "more_body": False, }
  178. "4(*)551쏫쏍쏅썗쏂 Server Application { 'asgi': {'spec_version': ‘2.1', 'version': '3.0'}, ...

    'method': ‘GET', 'type': 'http' } { "type": "http.request", "body": b'', "more_body": False } { "type": "http.response.start", "status": 200, "headers": [(b"name", b"value")], } { "type": "http.response.body", "body": b"Hello, World", "more_body": False, } {"type": "http.disconnect"}
  179. ໰͍

  180. ໰썛 ඇಉظαʔόͱ͸ʁ ඇಉظαʔόήʔτ΢ΣΠΠϯλʔϑΣʔε "TZODISPOPVT4FSWFS(BUFXBZ*OUFSGBDF

  181. ౴͑

  182. ౴썟 asyncio Ͱ࡞ͬͨWebαʔό ඇಉظαʔόήʔτ΢ΣΠΠϯλʔϑΣʔε "TZODISPOPVT4FSWFS(BUFXBZ*OUFSGBDF

  183. "4(*쎂썻썛썽3FBEUIF%PDT https://asgi.readthedocs.io/en/latest/ ASGI applications must run as async / await

    compatible coroutines (i.e. asyncio-compatible)
  184. "4(*쎂썻썛썽3FBEUIF%PDT ASGI ΞϓϦέʔγϣϯ͸ async / await ޓ׵ͷίϧʔνϯ (͢ͳ Θͪ asyncio

    ޓ׵) ͱ࣮ͯ͠ߦ͞Εͳ͚Ε͹ͳΓ·ͤΜ ɻ https://asgi.readthedocs.io/en/latest/ ASGI applications must run as async / await compatible coroutines (i.e. asyncio-compatible)
  185. "4(*쎂썻썛썽3FBEUIF%PDT ASGI ΞϓϦέʔγϣϯ͸ async / await ޓ׵ͷίϧʔνϯ (͢ͳ Θͪ asyncio

    ޓ׵) ͱ࣮ͯ͠ߦ͞Εͳ͚Ε͹ͳΓ·ͤΜ ɻ https://asgi.readthedocs.io/en/latest/ ASGI applications must run as async / await compatible coroutines (i.e. asyncio-compatible)
  186. "4(*ରԠ쎅ʓʓ쎂ग़ձ썺썶쎠

  187. "4(*ରԠ쎅ʓʓ쎂ग़ձ썺썶쎠 asyncioରԠͰɺ͋ͷIFʢҾ਺3ͭͷ΍ͭʣ

  188. "4(*ରԠ쎅ʓʓ쎂ग़ձ썺썶쎠 asyncioରԠͰɺ͋ͷIFʢҾ਺3ͭͷ΍ͭʣ ͳΜͩͳͱࢥ͍ͬͯͩ͘͞ɻ

  189. "4(*쎂썻썛썽3FBEUIF%PDT •ͦͷ΄͔ͷASGIͷ࢓༷ •ASGI sub-specification - Life Span •ASGI Extention -

    HTTP/2 Server Push •ASGI Extention - Websocket Denial Response https://asgi.readthedocs.io/en/latest/
  190. "4(*8FC4PDLFU Server Application { 'asgi': {'spec_version': ‘2.1', 'version': '3.0'}, ...

    'method': ‘GET', 'type': 'websocket' } { “type": "websocket.connect" } { “type": “websocket.accept" } { “type": “websocket.close” “code": 1000 } { “type": “websocket.send” “text": ”Hello, World” } { “type": “websocket.disconnect" } IUUQTBTHJSFBEUIFEPDTJPFOMBUFTUTQFDTXXXIUNMXFCTPDLFU
  191. "4(*-JGF4BQBO "scope" : { "type": "lifespan", "asgi": {"spec_version": "2.0", "version":

    "3.0"}, } --- SERVER {"type": "lifespan.startup"} {"type": "lifespan.shutdown"} --- APPLICATION {"type": "lifespan.startup.complete"} {"type": "lifespan.shutdown.complete"}
  192. "4(*-JGF4BQBO async def app(scope, receive, send): if scope['type'] == 'lifespan':

    while True: message = await receive() if message['type'] == 'lifespan.startup': ... # Do some startup here! await send({'type': 'lifespan.startup.complete'}) elif message['type'] == 'lifespan.shutdown': ... # Do some shutdown here! await send({'type': 'lifespan.shutdown.complete'}) return else: pass # Handle other types IUUQTBTHJSFBEUIFEPDTJPFOMBUFTUTQFDTMJGFTQBOIUNM
  193. "4(*TVCTQFDJpDBUJPO-JGF4BQBO async def app(scope, receive, send): if scope['type'] == 'lifespan':

    while True: message = await receive() if message['type'] == 'lifespan.startup': ... # Do some startup here! await send({'type': 'lifespan.startup.complete'}) elif message['type'] == 'lifespan.shutdown': ... # Do some shutdown here! await send({'type': 'lifespan.shutdown.complete'}) return else: pass # Handle other types IUUQTBTHJSFBEUIFEPDTJPFOMBUFTUTQFDTMJGFTQBOIUNM
  194. "4(*&YUFOTJPOT)5514FSWFS1VTI "scope": { ..., "extensions": {"http.response.push": {}}, } --- {

    "type": "http.response.push", "path": "/path", "headers": [(b"name", b"value")], } Server Application IUUQTBTHJSFBEUIFEPDTJPFOMBUFTUFYUFOTJPOTIUNMIUUQTFSWFSQVTI
  195. "4(*&YUFOTJPOT8FCTPDLFU%FOJBM3FTQPOTF "scope": { ... "extensions": { "websocket.http.response": {}, }, }

  196. "4(*'SBNFXPSLT 

  197. "4(*'SBNFXPSLT$PNQBSFE  Framework HTTP WebSocket Server Push WebSocket HTTP response

    Quart ✓ ✓ ✓ ✓ FastAPI ✓ ✓ ❌ ❌ Responder ✓ ✓ ❌ ❌ Starlette ✓ ✓ ❌ ❌ Django ✓ ✓ ❌ ❌
  198. "4(*4FSWFST  Daphne Mangum

  199. "4(*4FSWFST  $PNQBSFE  Framework HTTP WebSockets Server Push WebSocket

    HTTP response Hypercorn 1 ✓ 2 ✓ 1 ✓ 2 ✓ ✓ ✓ Uvicorn 1 ✓ 2 ❌ 1 ✓ 2 ❌ ❌ ❌ Daphne 1 ✓ 2 ✓ 1 ✓ 2 ❌ ❌ ❌ Mangum 1 ✓ 2 ❌ 1✓ 2 ❌ ❌ ❌
  200. "4(*쎕썿쎘 •ASGIରԠ ʹ asyncio •ASGIରԠϑϨʔϜϫʔΫ͸૿͍͑ͯΔ •ASGIରԠͷαʔό΋͋Δ •ASGI͸PEPʹͳ͍ͬͯͳ͍

  201. 84(*썿"4(*쎕썿쎘 •WSGI ͱ ASGI ͷ໨త͸ಉ͡ •WSGI ͱ ASGI ͷ࣮૷͸ࣅ͍ͯΔʢͨͩasync/awitͰܾఆతʹҧ͏ʣ •WSGI

    ͱ ASGI ͷঢ়گ΋ࣅ͍ͯΔ •ASGI͸PEPʹͳͬͯ΋Α͍ͷͰ͸
  202. "4(*Λ औΓר͘ঢ়گ

  203. "4(*1&1쎏쎅ಓ ͳͥASGI͸PEPʹͳ͍ͬͯͳ͍ͷ͔ʁ

  204. "4(*1&1쎏쎅ಓ ͳͥASGI͸PEPʹͳ͍ͬͯͳ͍ͷ͔ʁ A.ίΞσϕϩούʔ͕͍͍إΛ͠ͳ͔͔ͬͨΒ

  205. "4(*1&1쎏쎅ಓ python-ideas@python.org ϝʔϦϯάϦετ 2020೥1݄28೔ python-ideas@python.org ϝʔϦϯάϦετ 2018೥10݄28೔

  206. "4(*1&1쎏쎅ಓ python-ideas@python.org ϝʔϦϯάϦετ 2018೥10݄28೔ Standardising ASGI as a PEP IUUQTNBJMQZUIPOPSHBSDIJWFTMJTUQZUIPOJEFBT!QZUIPOPSHUISFBE5$#133**#/7%8/+$9**/.$92,3,$3

  207. "4(*1&1쎏쎅ಓ python-ideas@python.org ϝʔϦϯάϦετ 2020೥1݄28೔ Subject:Is the deployment standard for WSGI

    ready?
  208. "4(*1&1쎏쎅ಓ python-ideas@python.org ϝʔϦϯάϦετ 2020೥1݄28೔ Subject:Is the deployment standard for WSGI

    ready?
  209. "4(*1&1쎏쎅ಓ python-ideas@python.org ϝʔϦϯάϦετ 2020೥1݄28೔ Subject:Is the deployment standard for WSGI

    ready? *EPOUUIJOLUIJTTPSUPGUIJOHTIPVMECFB1&1 -PPLBU"4(*BOEIPXUIBUJTOUB1&1BOETUJMMNBOBHFTUPFYJTU 4JODFUIJTJTO`UBMBOHVBHFSFMBUFEPSQBDLBHFSFMBUFEUIJOH*EPOUUIJOLJUSFBMMZOFFETUPHPUISPVHIUIF1&1 QSPDFTT
  210. "4(*1&1쎏쎅ಓ python-ideas@python.org ϝʔϦϯάϦετ 2020೥1݄28೔ Subject:Is the deployment standard for WSGI

    ready? *EPOUUIJOLUIJTTPSUPGUIJOHTIPVMECFB1&1 -PPLBU"4(*BOEIPXUIBUJTOUB1&1BOETUJMMNBOBHFTUPFYJTU 4JODFUIJTJTO`UBMBOHVBHFSFMBUFEPSQBDLBHFSFMBUFEUIJOH*EPOUUIJOLJUSFBMMZOFFETUPHPUISPVHIUIF1&1 QSPDFTT 4JODF84(*BOE QSPCBCMZTPPO "4(*BSFWFSZDPNNPO"1*TUBOEBSETJO1ZUIPOMBOE UIFZEFTFSWFUP HPJOUPUIF1&1JOEFYBTXFMM *.0
  211. "4(*1&1쎏쎅ಓ It's worth noting that I was discouraged from making

    ASGI a PEP by several Python core developers, which is why I have not been pursuing that process any further. I'm not sure I share this view, so I may come back to it in the future, but there's a reason it's not in the process right now. ಛච͢΂͖͸ɺࢲ͕ASGIΛPEPʹ͢Δ͜ͱΛԿਓ͔ͷPythonίΞ։ൃऀ͔Βམ୾͞Εͯ ͍ͨ͜ͱͰɺͦΕҎ্ͦͷϓϩηεΛ௥ٻͯ͜͠ͳ͔ͬͨ͜ͱͰ͢ɻ ࢲ͸͜ͷݟղʹڞײ͍ͯ͠ΔΘ͚Ͱ͸ͳ͍ͷͰɺকདྷతʹ͸໭ͬͯ͘Δ͔΋͠Ε·ͤΜ ͕ɺࠓ͸ͦͷϓϩηεʹೖ͍ͬͯͳ͍ͷʹ͸ཧ༝͕͋Γ·͢ɻ python-ideas@python.org ϝʔϦϯάϦετ 2020೥1݄28೔
  212. •Awesome ASGI ͱ͍͏GithubϦϙδτϦ “࠷΋༏ΕͨASGIϓϩδΣΫτͱϦιʔεΛ࠷৽ͷঢ়ଶʹอͭͷʹ໾ཱͪ·͢“ "4(*쎅੝쎡্썣쎡 IUUQTHJUIVCDPNqPSJNPOENBODBBXFTPNFBTHJ

  213. "4(*쎅੝쎡্썣쎡 •Awesome ASGI ͱ͍͏GithubϦϙδτϦ •Web Framework •Server •Monitoring •ServerlessʢAWSʣ •GraphQL

  214. •Encode OSS ͱ͍͏ΠΪϦεͷձࣾ "4(*쎅੝쎡্썣쎡 IUUQTXXXFODPEFJP

  215. •Encode OSS ͱ͍͏ΠΪϦεͷձࣾ - ༷ʑͳϓϩμΫτͷ։ൃݩ •uvicorn •starletteʢFastAPI΍Responder ͷϕʔεʹͳ͍ͬͯΔ࠷খASGI FWʣ •HTTPX

    •Django REST framework •ASGIهࣄ΋͋Γ - Hello, ASGI ͳͲͳͲ "4(*쎅੝쎡্썣쎡
  216. •PG Jones ࢯ •ASGI ׬શରԠͷαʔό Hypercorn / ϑϨʔϜϫʔΫͷQuart •༷ʑͳͱ͜ΖͰͷਫ਼ྗతͳొஃ "4(*쎅੝쎡্썣쎡

    IUUQTQHKPOFTEFW
  217. ଎౓쎅࿩ IUUQTXXXUFDIFNQPXFSDPNCFODINBSLT

  218. 1&1쎏쎅ಓ •ASGI͸·ͩ࢝·ͬͨ͹͔Γ •PythonʹࠓؔΘ͍ͬͯΔΘ͕ͨͨͪ͠ҭ͍͚ͯͯΔ΋ͷ •·ͣ͸͞ΘͬͯΈ͍ͯͩ͘͞ •ͻͱ·ͣࢼ͢ͷͰ͋Ε͹ɺFastAPIͱuvicornͰɻ •αʔόʔϓογϡ΍HTTP/2Λࢼ͚ͨ͠Ε͹ɺQuartͱHypercornΛɻ

  219. ࢀߟࢿྉ •An ASGI Server from scratch / Philip Jones IUUQTXXXZPVUVCFDPNXBUDI

    W(QRY6*8KJX •An introduction to ASGI, Asynchronous Server Gateway Interface / Philip Jones IUUQTXXXZPVUVCFDPNXBUDI WUH$,2R986 •Hello, ASGI IUUQTXXXFODPEFJPBSUJDMFTIFMMPBTHJ •Introduction to ASGI: Emergence of an Async Python Web Ecosystem IUUQTqPSJNPOEEFWCMPHBSUJDMFTJOUSPEVDUJPOUPBTHJBTZODQZUIPOXFC