Werkzeug: 청크 μš”μ²­μ€ μ—¬μ „νžˆ β€‹β€‹μž‘λ™ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

에 λ§Œλ“  2017λ…„ 07μ›” 16일  Β·  4μ½”λ©˜νŠΈ  Β·  좜처: pallets/werkzeug

(μˆ˜μ •μ„ μ‹œλ„ν–ˆλ‹€λŠ” 것을 κΉ¨λ‹¬μ•˜κΈ° λ•Œλ¬Έμ— μ—…λ°μ΄νŠΈλ¨, κ·Έλž˜μ„œ μ›λž˜ λ¬Έμ œμ™€ λ‚˜λ₯Ό ν¬κΈ°ν•˜κ²Œ λ§Œλ“  λ¬Έμ œμ— ν˜Όλž€μŠ€λŸ¬μ›Œν•¨)

Werkzeug (ν˜„μž¬ git master)λ₯Ό μ‚¬μš©ν•˜λŠ” 앱에 청크 μš”μ²­μ„ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. get_input_stream은 LimitedStream(wsgi.input, min(content_length, max_content_length)) ν˜ΈμΆœν•©λ‹ˆλ‹€. 청크 인코딩을 μ‚¬μš©ν•˜λŠ” 경우 min(content_length, max_content_length) λŠ” 항상 Noneμ΄λ©λ‹ˆλ‹€.

진행을 μœ„ν•΄ LimitedStream(stream, content_length or max_content_length) μ‚¬μš©ν•΄ λ³΄μ•˜μ§€λ§Œ κ²°κ΅­ ClientDisconnected μ˜ˆμ™Έκ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€. ν΄λΌμ΄μ–ΈνŠΈ μ—°κ²° ν•΄μ œμ™€ 청크 μš”μ²­μ˜ 차이λ₯Ό ꡬ뢄할 수 μ—†κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€. , wsgi.input.read() λŠ” 두 경우 λͺ¨λ‘ 길이가 0인 λ¬Έμžμ—΄μ„ λ°˜ν™˜ν•©λ‹ˆλ‹€.

κ°€μž₯ μœ μš©ν•œ λŒ“κΈ€

ν˜„μž¬ input_terminated μ§€μ›ν•˜λŠ” wsgiλŠ” λ¬΄μ—‡μž…λ‹ˆκΉŒ? 데이터가 λΉ„μ–΄μžˆλŠ” 이유λ₯Ό λ””λ²„κΉ…ν•˜λŠ” 데 ν•˜λ£¨ 쒅일 λ ˆμ½”λ”© ν•œ ν›„ 슀트림이 λΉ„μ–΄μžˆλŠ” μ΄μœ λŠ” 청크 슀트림 μΈμ½”λ”©μœΌλ‘œ μΈν•œ κ²ƒμž„μ„ 깨달은 ν›„ 이제 이것을 μ§€μ›ν•˜λŠ” 것을 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.

λͺ¨λ“  4 λŒ“κΈ€

이것은 min 의 λ‹¨μˆœν•œ 버그 μ΄μƒμž…λ‹ˆλ‹€. 그것을 고친 ν›„, λ¬Έμ œλŠ” 읽을 것이 max_content_length 미만이면 Werkzeug λΈ”λ‘μœΌλ‘œ wsgi.input.read(max_content_length) λ₯Ό μ˜μ›νžˆ μˆ˜ν–‰ν•œλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. λ˜λŠ” 전체 λ©”μ‹œμ§€λ₯Ό ꡬ문 λΆ„μ„ν•˜κ³  λ²„νΌλ§ν•˜μ—¬ 청크λ₯Ό μ§€μ›ν•˜λŠ” Gunicorn을 μ‚¬μš©ν•˜λ©΄ 길이가 max_content_length 미만으둜 λ‚˜μ˜€λ―€λ‘œ LimitedStream λŠ” ν΄λΌμ΄μ–ΈνŠΈκ°€ 연결이 λŠμ–΄μ§„ κ²ƒμœΌλ‘œ κ°„μ£Όν•©λ‹ˆλ‹€.

λ‚˜λŠ” μž₯κ³ μ—μ„œ μš°λ¦¬κ°€ μ΄μƒν•œ μΌμ„ν•˜μ§€ μ•ŠλŠ”μ§€ ν™•μΈν•˜κΈ° μœ„ν•΄ 이것을 ν…ŒμŠ€νŠΈν–ˆμŠ΅λ‹ˆλ‹€. 빈 μŠ€νŠΈλ¦Όλ„ λ³΄μž…λ‹ˆλ‹€.

κ°€μž₯ κ°„λ‹¨ν•œ 방법은 environ['wsgi.input_terminated'] λ₯Ό μ„€μ •ν•˜λŠ” 미듀웨어λ₯Ό μ œκ³΅ν•˜κ³  청크 전솑을 μ§€μ›ν•˜λŠ” μ„œλ²„λ₯Ό μ‚¬μš©ν•  λ•Œ μ‚¬λžŒλ“€μ—κ²Œμ΄λ₯Ό μ‚¬μš©ν•˜λ„λ‘ μ§€μ‹œν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

ν˜„μž¬ input_terminated μ§€μ›ν•˜λŠ” wsgiλŠ” λ¬΄μ—‡μž…λ‹ˆκΉŒ? 데이터가 λΉ„μ–΄μžˆλŠ” 이유λ₯Ό λ””λ²„κΉ…ν•˜λŠ” 데 ν•˜λ£¨ 쒅일 λ ˆμ½”λ”© ν•œ ν›„ 슀트림이 λΉ„μ–΄μžˆλŠ” μ΄μœ λŠ” 청크 슀트림 μΈμ½”λ”©μœΌλ‘œ μΈν•œ κ²ƒμž„μ„ 깨달은 ν›„ 이제 이것을 μ§€μ›ν•˜λŠ” 것을 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.

environ.get('wsgi.input_terminated') λ₯Ό ν™•μΈν•˜λŠ” 것 외에도 environ.get('HTTP_TRANSFER_ENCODING') == 'chunked' 도 확인해야 ν•˜λ©° 이 경우 λž˜ν•‘λ˜μ§€ μ•Šμ€ μŠ€νŠΈλ¦Όλ„ 직접 λ°˜ν™˜ν•΄μ•Ό ν•©λ‹ˆκΉŒ? 빈 μŠ€νŠΈλ¦Όμ„ λ°˜ν™˜ν•˜λŠ” κ°„λ‹¨ν•œ curl -H 'Transfer-Encoding: chunked' ... 와 같은 문제λ₯Ό ν•΄κ²°ν•©λ‹ˆλ‹€.

RFC2616에 따라

4.4.2
Transfer-Encoding 헀더 ν•„λ“œ (μ„Ήμ…˜ 14.41)κ°€ 있고
"identity"μ΄μ™Έμ˜ κ°’μ΄μžˆλŠ” 경우 전솑 κΈΈμ΄λŠ”
"청크" 전솑 μ½”λ”©(μ„Ήμ…˜ 3.6)을 μ‚¬μš©ν•˜μ—¬ μ •μ˜λ©λ‹ˆλ‹€.
연결을 λ‹«μ•„ λ©”μ‹œμ§€κ°€ μ’…λ£Œλ˜μ§€ μ•ŠλŠ” ν•œ.

4.4.3
Content-Length 헀더 ν•„λ“œ(μ„Ήμ…˜ 14.13)κ°€ μžˆλŠ” 경우 ν•΄λ‹Ή
OCTET의 10μ§„μˆ˜ 값은 μ—”ν‹°ν‹° 길이와
전솑 길이. Content-Length 헀더 ν•„λ“œλŠ” μ „μ†‘λ˜μ–΄μ„œλŠ” μ•ˆ λ©λ‹ˆλ‹€(MUST NOT).
이 두 길이가 λ‹€λ₯Έ 경우(즉, Transfer-Encoding
헀더 ν•„λ“œκ°€ 있음). 두 가지 λͺ¨λ‘λ‘œ λ©”μ‹œμ§€κ°€ μˆ˜μ‹ λ˜λŠ” 경우
Transfer-Encoding 헀더 ν•„λ“œ 및 Content-Length 헀더 ν•„λ“œ,
ν›„μžλŠ” λ¬΄μ‹œλ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€.

... Transfer-Encoding 의 chunked Content-Length 헀더λ₯Ό λ¬΄μ‹œν•˜λ„λ‘ μš”κ΅¬ν•˜λ―€λ‘œμ΄λ₯Ό 기반으둜 슀트림 처리λ₯Ό μˆ˜ν–‰ν•΄μ„œλŠ” μ•ˆλ©λ‹ˆλ‹€. ν˜„μž¬ wsgi.input_terminated κ°€ μ„€μ •λ˜μ–΄ μžˆμ§€ μ•Šμ€ κ²½μš°μž…λ‹ˆλ‹€.

10 λ°”μ΄νŠΈ JSON νŽ˜μ΄λ‘œλ“œμ™€ 같은 정상적인 청크 인코딩이 μž‘λ™ν•˜λ €λ©΄ wsgi.input_terminated λ₯Ό μ„€μ •ν•΄μ•Όν•©λ‹ˆκΉŒ?

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰

κ΄€λ ¨ 문제

SimonSapin picture SimonSapin  Β·  12μ½”λ©˜νŠΈ

lepture picture lepture  Β·  6μ½”λ©˜νŠΈ

Nessphoro picture Nessphoro  Β·  6μ½”λ©˜νŠΈ

davidism picture davidism  Β·  9μ½”λ©˜νŠΈ

caiz picture caiz  Β·  3μ½”λ©˜νŠΈ