Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

썡쎕썟썷쎣쎟 •෱ా ൏໵ʢJunya Fukudaʣʢ@JunyaFffʣ •גࣜձࣾ೔ຊγεςϜٕݚʢJSLʣॴଐ •PyCon JP 2020 Gold Sponser ʢΦϯϥΠϯϒʔεʹ΋༡ͼʹ͖ͯͶʣ •GEEKLAB.NAGANO •࠷ۙϚΠϯΫϥϑτͰখֶੜ޲͚Youtube഑৴࢝ΊΔ ΪʔΫϥϘ௕໺ϚΠΫϥ

Slide 3

Slide 3 text

ຊ쏅쏍쏁쏱쏽쎅ྲྀ쎣 •HTTPͷྺ࢙Λ؆୯ʹৼΓฦΓ •WSGIͷྺ࢙ •ASGIͷ࢓༷ͷ͸ͳ͠ʢΫϥΠΞϯτͱαʔόͷίʔυΛަ͑ͯʣ •ASGIΛऔΓר͘ঢ়گ

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

Ωʔϫʔυ

Slide 9

Slide 9 text

Ωʔϫʔυ ໰͍

Slide 10

Slide 10 text

쎷썗쏹썗쏓

Slide 11

Slide 11 text

쎷썗쏹썗쏓 ಉظ

Slide 12

Slide 12 text

ಉظ ඇಉظ 쎷썗쏹썗쏓

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

쎷썗쏹썗쏓 ಉظ ඇಉظ PEP

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

໰썛

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

·ͣ͸͡Ίʹ

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

)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ʣ

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

Ͱ͸·ͣ͸84(*ͷ࿩

Slide 37

Slide 37 text

ಉظ

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

84(* •WSGIʢWeb Server Gateway Interfaceʣͷུ •Type͸ʮInformationalʯ •2003೥ʹPEP 333 ʢ 2010೥ PEP 3333 Python3ରԠʣ ΫϥΠΞϯτ 8FCαʔό ΞϓϦέʔγϣϯ ϑϨʔϜϫʔΫ

Slide 48

Slide 48 text

썴쎙썴쎙쎁쎪쎅썶쎘쎂84(*썣썾썤썶쎅썢 •౰࣌ɺWeb Framework͕ᷓΕ͍ͯͨ •Zope, Quixote, Webware, SkunkWeb, PSO, and Twisted Web

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

Server Application 84(*ॲཧ쎅ྲྀ쎣

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

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", }

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

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

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

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

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

•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(*쎿썗쏚

Slide 71

Slide 71 text

•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(*쎿썗쏚

Slide 72

Slide 72 text

84(*쎿썗쏚 •WSGI؀ڥม਺ͱίʔϧόοΫؔ਺ΛҾ਺ͱͨ͠ɺWSGIΞϓϦέʔγϣϯͷݺͼग़͠ byte_response_body = application(env, start_response)

Slide 73

Slide 73 text

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

Slide 74

Slide 74 text

84(*쎿썗쏚 •WSGI؀ڥม਺ͱίʔϧόοΫؔ਺ΛҾ਺ͱͨ͠ɺWSGIΞϓϦέʔγϣϯͷݺͼग़͠ byte_response_body = application(env, start_response)

Slide 75

Slide 75 text

Server Application 84(*ॲཧ쎅ྲྀ쎣

Slide 76

Slide 76 text

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

Slide 77

Slide 77 text

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

Slide 78

Slide 78 text

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

Slide 79

Slide 79 text

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

Slide 80

Slide 80 text

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

Slide 81

Slide 81 text

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

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

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

Slide 84

Slide 84 text

84(*'SBNFXPSL

Slide 85

Slide 85 text

84(*4FSWFS mod_wsgi

Slide 86

Slide 86 text

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

Slide 87

Slide 87 text

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

Slide 88

Slide 88 text

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

Slide 89

Slide 89 text

͢΂ͯ͸BTZODBXBJU͔Β࢝·ͬͨ

Slide 90

Slide 90 text

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

Slide 91

Slide 91 text

썰쎐썽쎆BTZODBXBJU썢쎠࢝쎕썺썶 •ඇಉظIOͷͨΊͷڞ௨ίϯϙʔωϯτ͕Pythonʹ௥Ճ •Pyhton 3.4 ʢ2014೥ʣ ΑΓ asyncio Ϟδϡʔϧ •Pyhton 3.5 ʢ2015೥ʣΑΓ async/await ͕ར༻Մೳʹͳͬͨ

Slide 92

Slide 92 text

썰쎐썽쎆BTZODBXBJU썢쎠࢝쎕썺썶 •asyncioɺasync/await ొ৔ޙɺඇಉظͳ Web Framework͕ᷓΕ͍ͯͨ •SANICɺTornadoɺaiohttpɺViboraɺJapronto Japronto!

Slide 93

Slide 93 text

ͷɺͰ͠ΐ͏͔

Slide 94

Slide 94 text

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

Slide 95

Slide 95 text

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

Slide 96

Slide 96 text

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

Slide 97

Slide 97 text

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

Slide 98

Slide 98 text

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

Slide 99

Slide 99 text

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

Slide 100

Slide 100 text

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

Slide 101

Slide 101 text

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

Slide 102

Slide 102 text

"4(*쎂썻썛썽3FBEUIF%PDT •WSGIͱޓ׵ͷ͋Δઃܭʹͳ͍ͬͯΔʢasgirefͰWsgiToAsgiͱ͍͏Ξμϓλʔʣ https://asgi.readthedocs.io/en/latest/

Slide 103

Slide 103 text

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

Slide 104

Slide 104 text

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

Slide 105

Slide 105 text

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

Slide 106

Slide 106 text

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

Slide 107

Slide 107 text

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

Slide 108

Slide 108 text

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

Slide 109

Slide 109 text

"4(*쎂썻썛썽 •ASGI ͷجຊͷίʔυ͔ΒɺجຊͱͳΔHTTPϦΫΤετͷॲཧΛݟͯΈΔ •ASGIΞϓϦέʔγϣϯ •ASGIαʔό

Slide 110

Slide 110 text

"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/

Slide 111

Slide 111 text

"4(*쎂썻썛썽BTZODJPBTZODBXBJU •͜ͷޙͷίʔυͰ͸ asyncio async/await͕ొ৔͠·͢ɻ •asyncio •ίϧʔνϯ •async/await

Slide 112

Slide 112 text

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

Slide 113

Slide 113 text

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

Slide 114

Slide 114 text

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

Slide 115

Slide 115 text

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

Slide 116

Slide 116 text

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

Slide 117

Slide 117 text

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

Slide 118

Slide 118 text

"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

Slide 119

Slide 119 text

"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

Slide 120

Slide 120 text

"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

Slide 121

Slide 121 text

"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

Slide 122

Slide 122 text

"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

Slide 123

Slide 123 text

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

Slide 124

Slide 124 text

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

Slide 125

Slide 125 text

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

Slide 126

Slide 126 text

"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!', })

Slide 127

Slide 127 text

"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

Slide 128

Slide 128 text

"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

Slide 129

Slide 129 text

"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’: })

Slide 130

Slide 130 text

"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

Slide 131

Slide 131 text

"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!', })

Slide 132

Slide 132 text

"4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅쎦썢썺썶썪썿 •Ҿ਺͸3ͭ •Scope ɿ ΫϥΠΞϯτ͔ΒͷϦΫΤετͷ৘ใؚ͕·Ε͍ͯΔʢWSGIͷenvironʹ ֘౰ʣ •recieveɿαʔό͔ΒͷϘσΟͷ৘ใΛड͚औΓͦ͏ͩ •sendɿԠ౴։࢝ͷsend ͱ Ԡ౴ຊମͷsend IUUQTBTHJSFBEUIFEPDTJPFOMBUFTUTQFDTXXXIUNMIUUQDPOOFDUJPOTDPQF HTTP & WebSocket ASGI Message Format - HTTP

Slide 133

Slide 133 text

Ͱ͸ଓ͍ͯ αʔόଆͷίʔυ

Slide 134

Slide 134 text

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

Slide 135

Slide 135 text

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

Slide 136

Slide 136 text

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

Slide 137

Slide 137 text

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

Slide 138

Slide 138 text

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

Slide 139

Slide 139 text

•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쎿썗쏚

Slide 140

Slide 140 text

•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쎿썗쏚

Slide 141

Slide 141 text

•import import asyncio import sys "4(*FDIP8FC쎿썗쏚

Slide 142

Slide 142 text

•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쎿썗쏚

Slide 143

Slide 143 text

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쎿썗쏚

Slide 144

Slide 144 text

def create_message(body, more_body): return { "type": "http.request", "body": body, "more_body": more_body, } •create_message ؔ਺ɿreceive༻ͷϝοηʔδΛ࡞ΔʢASGIΞϓϦͷୈ̎Ҿ਺ʣ "4(*FDIP8FC쎿썗쏚

Slide 145

Slide 145 text

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쎿썗쏚

Slide 146

Slide 146 text

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쎿썗쏚

Slide 147

Slide 147 text

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쎿썗쏚

Slide 148

Slide 148 text

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쎿썗쏚

Slide 149

Slide 149 text

•asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ •গ͠௕͍ͷͰ̐෼ׂ͠·͢ʢ40ߦ͙Β͍Ͱ͢ʣ "4(*FDIP8FC쎿썗쏚

Slide 150

Slide 150 text

•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쎿썗쏚

Slide 151

Slide 151 text

•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쎿썗쏚

Slide 152

Slide 152 text

•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쎿썗쏚

Slide 153

Slide 153 text

•asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ # httpͷϦΫΤετͷparser͔ΒscopeΛ࡞Δ scope = create_scope(parser) "4(*FDIP8FC쎿썗쏚

Slide 154

Slide 154 text

•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쎿썗쏚

Slide 155

Slide 155 text

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

Slide 156

Slide 156 text

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

Slide 157

Slide 157 text

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

Slide 158

Slide 158 text

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

Slide 159

Slide 159 text

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

Slide 160

Slide 160 text

•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쎿썗쏚

Slide 161

Slide 161 text

•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쎿썗쏚

Slide 162

Slide 162 text

•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쎿썗쏚

Slide 163

Slide 163 text

•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쎿썗쏚

Slide 164

Slide 164 text

•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쎿썗쏚

Slide 165

Slide 165 text

•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쎿썗쏚

Slide 166

Slide 166 text

•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쎿썗쏚

Slide 167

Slide 167 text

•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쎿썗쏚

Slide 168

Slide 168 text

•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쎿썗쏚

Slide 169

Slide 169 text

•asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ await writer.drain() writer.close() "4(*FDIP8FC쎿썗쏚

Slide 170

Slide 170 text

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

Slide 171

Slide 171 text

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

Slide 172

Slide 172 text

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

Slide 173

Slide 173 text

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

Slide 174

Slide 174 text

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

Slide 175

Slide 175 text

"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")], }

Slide 176

Slide 176 text

"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, }

Slide 177

Slide 177 text

"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, }

Slide 178

Slide 178 text

"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"}

Slide 179

Slide 179 text

໰͍

Slide 180

Slide 180 text

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

Slide 181

Slide 181 text

౴͑

Slide 182

Slide 182 text

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

Slide 183

Slide 183 text

"4(*쎂썻썛썽3FBEUIF%PDT https://asgi.readthedocs.io/en/latest/ ASGI applications must run as async / await compatible coroutines (i.e. asyncio-compatible)

Slide 184

Slide 184 text

"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)

Slide 185

Slide 185 text

"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)

Slide 186

Slide 186 text

"4(*ରԠ쎅ʓʓ쎂ग़ձ썺썶쎠

Slide 187

Slide 187 text

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

Slide 188

Slide 188 text

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

Slide 189

Slide 189 text

"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/

Slide 190

Slide 190 text

"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

Slide 191

Slide 191 text

"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"}

Slide 192

Slide 192 text

"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

Slide 193

Slide 193 text

"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

Slide 194

Slide 194 text

"4(*&YUFOTJPOT)5514FSWFS1VTI "scope": { ..., "extensions": {"http.response.push": {}}, } --- { "type": "http.response.push", "path": "/path", "headers": [(b"name", b"value")], } Server Application IUUQTBTHJSFBEUIFEPDTJPFOMBUFTUFYUFOTJPOTIUNMIUUQTFSWFSQVTI

Slide 195

Slide 195 text

"4(*&YUFOTJPOT8FCTPDLFU%FOJBM3FTQPOTF "scope": { ... "extensions": { "websocket.http.response": {}, }, }

Slide 196

Slide 196 text

"4(*'SBNFXPSLT

Slide 197

Slide 197 text

"4(*'SBNFXPSLT$PNQBSFE Framework HTTP WebSocket Server Push WebSocket HTTP response Quart ✓ ✓ ✓ ✓ FastAPI ✓ ✓ ❌ ❌ Responder ✓ ✓ ❌ ❌ Starlette ✓ ✓ ❌ ❌ Django ✓ ✓ ❌ ❌

Slide 198

Slide 198 text

"4(*4FSWFST Daphne Mangum

Slide 199

Slide 199 text

"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 ❌ ❌ ❌

Slide 200

Slide 200 text

"4(*쎕썿쎘 •ASGIରԠ ʹ asyncio •ASGIରԠϑϨʔϜϫʔΫ͸૿͍͑ͯΔ •ASGIରԠͷαʔό΋͋Δ •ASGI͸PEPʹͳ͍ͬͯͳ͍

Slide 201

Slide 201 text

84(*썿"4(*쎕썿쎘 •WSGI ͱ ASGI ͷ໨త͸ಉ͡ •WSGI ͱ ASGI ͷ࣮૷͸ࣅ͍ͯΔʢͨͩasync/awitͰܾఆతʹҧ͏ʣ •WSGI ͱ ASGI ͷঢ়گ΋ࣅ͍ͯΔ •ASGI͸PEPʹͳͬͯ΋Α͍ͷͰ͸

Slide 202

Slide 202 text

"4(*Λ औΓר͘ঢ়گ

Slide 203

Slide 203 text

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

Slide 204

Slide 204 text

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

Slide 205

Slide 205 text

"4(*1&1쎏쎅ಓ [email protected] ϝʔϦϯάϦετ 2020೥1݄28೔ [email protected] ϝʔϦϯάϦετ 2018೥10݄28೔

Slide 206

Slide 206 text

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

Slide 207

Slide 207 text

"4(*1&1쎏쎅ಓ [email protected] ϝʔϦϯάϦετ 2020೥1݄28೔ Subject:Is the deployment standard for WSGI ready?

Slide 208

Slide 208 text

"4(*1&1쎏쎅ಓ [email protected] ϝʔϦϯάϦετ 2020೥1݄28೔ Subject:Is the deployment standard for WSGI ready?

Slide 209

Slide 209 text

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

Slide 210

Slide 210 text

"4(*1&1쎏쎅ಓ [email protected] ϝʔϦϯάϦετ 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

Slide 211

Slide 211 text

"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ίΞ։ൃऀ͔Βམ୾͞Εͯ ͍ͨ͜ͱͰɺͦΕҎ্ͦͷϓϩηεΛ௥ٻͯ͜͠ͳ͔ͬͨ͜ͱͰ͢ɻ ࢲ͸͜ͷݟղʹڞײ͍ͯ͠ΔΘ͚Ͱ͸ͳ͍ͷͰɺকདྷతʹ͸໭ͬͯ͘Δ͔΋͠Ε·ͤΜ ͕ɺࠓ͸ͦͷϓϩηεʹೖ͍ͬͯͳ͍ͷʹ͸ཧ༝͕͋Γ·͢ɻ [email protected] ϝʔϦϯάϦετ 2020೥1݄28೔

Slide 212

Slide 212 text

•Awesome ASGI ͱ͍͏GithubϦϙδτϦ “࠷΋༏ΕͨASGIϓϩδΣΫτͱϦιʔεΛ࠷৽ͷঢ়ଶʹอͭͷʹ໾ཱͪ·͢“ "4(*쎅੝쎡্썣쎡 IUUQTHJUIVCDPNqPSJNPOENBODBBXFTPNFBTHJ

Slide 213

Slide 213 text

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

Slide 214

Slide 214 text

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

Slide 215

Slide 215 text

•Encode OSS ͱ͍͏ΠΪϦεͷձࣾ - ༷ʑͳϓϩμΫτͷ։ൃݩ •uvicorn •starletteʢFastAPI΍Responder ͷϕʔεʹͳ͍ͬͯΔ࠷খASGI FWʣ •HTTPX •Django REST framework •ASGIهࣄ΋͋Γ - Hello, ASGI ͳͲͳͲ "4(*쎅੝쎡্썣쎡

Slide 216

Slide 216 text

•PG Jones ࢯ •ASGI ׬શରԠͷαʔό Hypercorn / ϑϨʔϜϫʔΫͷQuart •༷ʑͳͱ͜ΖͰͷਫ਼ྗతͳొஃ "4(*쎅੝쎡্썣쎡 IUUQTQHKPOFTEFW

Slide 217

Slide 217 text

଎౓쎅࿩ IUUQTXXXUFDIFNQPXFSDPNCFODINBSLT

Slide 218

Slide 218 text

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

Slide 219

Slide 219 text

ࢀߟࢿྉ •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