Π‘ΠΎΠ³Π»Π°ΡΠ½ΠΎ RFC 2616 :
ΠΠ½Π°ΡΠ΅Π½ΠΈΡ ΠΏΠΎΠ»Ρ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° HTTP / 1.1 ΠΌΠΎΠΆΠ½ΠΎ ΡΠ°Π·Π΄Π΅Π»ΠΈΡΡ Π½Π° Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΡΡΡΠΎΠΊ, Π΅ΡΠ»ΠΈ ΡΡΡΠΎΠΊΠ° ΠΏΡΠΎΠ΄ΠΎΠ»ΠΆΠ΅Π½ΠΈΡ Π½Π°ΡΠΈΠ½Π°Π΅ΡΡΡ Ρ ΠΏΡΠΎΠ±Π΅Π»Π° ΠΈΠ»ΠΈ Π³ΠΎΡΠΈΠ·ΠΎΠ½ΡΠ°Π»ΡΠ½ΠΎΠΉ ΡΠ°Π±ΡΠ»ΡΡΠΈΠΈ. ΠΡΠ΅ Π»ΠΈΠ½Π΅ΠΉΠ½ΡΠ΅ ΠΏΡΠΎΠ±Π΅Π»Ρ, Π²ΠΊΠ»ΡΡΠ°Ρ ΡΠ²ΠΎΡΠ°ΡΠΈΠ²Π°Π½ΠΈΠ΅, ΠΈΠΌΠ΅ΡΡ ΡΡ ΠΆΠ΅ ΡΠ΅ΠΌΠ°Π½ΡΠΈΠΊΡ, ΡΡΠΎ ΠΈ SP. ΠΠΎΠ»ΡΡΠ°ΡΠ΅Π»Ρ ΠΠΠΠΠ’ Π·Π°ΠΌΠ΅Π½ΠΈΡΡ Π»ΡΠ±ΠΎΠΉ Π»ΠΈΠ½Π΅ΠΉΠ½ΡΠΉ ΠΏΡΠΎΠ±Π΅Π» ΠΎΠ΄Π½ΠΈΠΌ SP ΠΏΠ΅ΡΠ΅Π΄ ΠΈΠ½ΡΠ΅ΡΠΏΡΠ΅ΡΠ°ΡΠΈΠ΅ΠΉ Π·Π½Π°ΡΠ΅Π½ΠΈΡ ΠΏΠΎΠ»Ρ ΠΈΠ»ΠΈ ΠΏΠ΅ΡΠ΅ΡΡΠ»ΠΊΠΎΠΉ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ Π² Π½ΠΈΡΡ ΠΎΠ΄ΡΡΠ΅ΠΌ Π½Π°ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠΈ.
ΠΠ΄Π½Π°ΠΊΠΎ werkzeug Π½Π΅ ΠΏΡΠΈΠ½ΠΈΠΌΠ°Π΅Ρ Π·Π½Π°ΡΠ΅Π½ΠΈΡ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΎΠ² Ρ ΡΠΈΠΌΠ²ΠΎΠ»Π°ΠΌΠΈ Π½ΠΎΠ²ΠΎΠΉ ΡΡΡΠΎΠΊΠΈ, Π΄Π°ΠΆΠ΅ Π΅ΡΠ»ΠΈ ΠΎΠ½ΠΈ ΡΠΎΠ±Π»ΡΠ΄Π°ΡΡ ΡΡΠΎ ΡΠΎΠ³Π»Π°ΡΠ΅Π½ΠΈΠ΅.
>>> import werkzeug
>>> werkzeug.Headers().add('foo', 'bar\n baz')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File ".../venv/local/lib/python2.7/site-packages/werkzeug/datastructures.py", line 1136, in add
self._validate_value(_value)
File ".../venv/local/lib/python2.7/site-packages/werkzeug/datastructures.py", line 1143, in _validate_value
raise ValueError('Detected newline in header value. This is '
ValueError: Detected newline in header value. This is a potential security problem
Π’Π°ΠΊΠΆΠ΅ ΡΡΠΎ ΠΎΠ³ΡΠ°Π½ΠΈΡΠ΅Π½ΠΈΠ΅ ΠΏΡΠΈΠΌΠ΅Π½ΡΠ΅ΡΡΡ Π½Π΅ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°ΡΠ΅Π»ΡΠ½ΠΎ.
>>> werkzeug.Headers([('foo', 'bar\n baz')])
Headers([('foo', 'bar\n baz')])
Π― ΡΡΠΎΠ»ΠΊΠ½ΡΠ»ΡΡ Ρ ΡΡΠΎΠΉ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠΎΠΉ ΠΏΡΠΈ ΠΏΠΎΠΏΡΡΠΊΠ΅ Π½Π°ΠΏΠΈΡΠ°ΡΡ ΡΠ΅ΡΡΠΎΠ²ΡΠ΅ ΠΏΡΠΈΠΌΠ΅ΡΡ, ΠΊΠ°ΡΠ°ΡΡΠΈΠ΅ΡΡ ΠΏΠ΅ΡΠ΅ΡΡΠ»ΠΊΠΈ ΠΊΠ»ΠΈΠ΅Π½ΡΡΠΊΠΈΡ ΡΠ΅ΡΡΠΈΡΠΈΠΊΠ°ΡΠΎΠ² nginx ΡΠ΅ΡΠ΅Π· Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΈ, ΡΠ°ΠΊ ΡΡΠΎ Π΅ΡΡΡ ΡΠ΅Π°Π»ΡΠ½ΡΠΉ Π²Π°ΡΠΈΠ°Π½Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ Π΄Π»Ρ ΠΏΡΠ°Π²ΠΈΠ»ΡΠ½ΠΎΠΉ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΠΈ ΡΡΠΎΠ³ΠΎ.
ΠΠ°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΈ HTTP Π½Π΅ Π΄ΠΎΠΏΡΡΠΊΠ°ΡΡ ΠΏΠ΅ΡΠ΅Π²ΠΎΠ΄Π° ΡΡΡΠΎΠΊΠΈ. Π ΡΠ°Π·Π΄Π΅Π»Π΅, ΠΊΠΎΡΠΎΡΡΠΉ Π²Ρ ΡΠΈΡΠΈΡΡΠ΅ΡΠ΅, Π³ΠΎΠ²ΠΎΡΠΈΡΡΡ ΠΎ ΡΠ²ΠΎΡΠ°ΡΠΈΠ²Π°Π½ΠΈΠΈ, ΠΊΠΎΡΠΎΡΠΎΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΡΠ΄Π°Π»ΡΡΡ Π½ΠΎΠ²ΡΠ΅ ΡΡΡΠΎΠΊΠΈ ΠΈΠ· ΡΠ°Π·Π²Π΅ΡΠ½ΡΡΠΎΠ³ΠΎ Π·Π½Π°ΡΠ΅Π½ΠΈΡ. ΠΡΠΎΡ:
"""foo
bar"""
Π΄ΠΎΠ»ΠΆΠ΅Π½ ΡΠ°Π·Π²Π΅ΡΠ½ΡΡΡΡΡ ΠΏΡΠΈΠΌΠ΅ΡΠ½ΠΎ ΡΠ°ΠΊ:
"foo bar"
ΠΡΠΎΠΌΠ΅ ΡΠΎΠ³ΠΎ, Werkzeug Π½Π΅ Π°Π½Π°Π»ΠΈΠ·ΠΈΡΡΠ΅Ρ HTTP Π½Π° ΡΡΠΎΠΌ ΡΡΠΎΠ²Π½Π΅, ΡΡΠΎ ΡΠ°Π±ΠΎΡΠ° ΡΠ΅ΡΠ²Π΅ΡΠ° WSGI. ΠΠ΄ΠΈΠ½ΡΡΠ²Π΅Π½Π½Π°Ρ ΠΏΡΠΈΡΠΈΠ½Π°, ΠΏΠΎ ΠΊΠΎΡΠΎΡΠΎΠΉ ΠΎΠ½ ΠΎΡΠΊΠ»ΠΎΠ½ΡΠ΅Ρ ΡΠΈΠΌΠ²ΠΎΠ»Ρ Π½ΠΎΠ²ΠΎΠΉ ΡΡΡΠΎΠΊΠΈ ΠΏΡΠΈ ΡΠΈΠ½ΡΠ°ΠΊΡΠΈΡΠ΅ΡΠΊΠΎΠΌ Π°Π½Π°Π»ΠΈΠ·Π΅, - ΡΡΠΎ Π²ΡΡΠ²Π»Π΅Π½ΠΈΠ΅ ΠΏΡΠΎΠ±Π»Π΅ΠΌ Ρ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡΡΡ.
ΠΡΠΎΡ Π±ΠΈΠ»Π΅Ρ Π±ΡΠ» ΠΌΠΎΡΠΈΠ²ΠΈΡΠΎΠ²Π°Π½ ΡΠ΅Π°Π»ΡΠ½ΡΠΌ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ΠΌ Flask Π² ΡΠ΅ΠΆΠΈΠΌΠ΅ ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠΈ Π·Π° ΠΊΠ»ΠΈΠ΅Π½ΡΡΠΊΠΈΠΌΠΈ ΡΠ΅ΡΡΠΈΡΠΈΠΊΠ°ΡΠ°ΠΌΠΈ ΠΏΡΠΎΠΊΡΠΈ-ΡΠ΅ΡΠ²Π΅ΡΠ° nginx. ΠΡΠΈ ΡΠ°ΠΊΠΎΠΉ Π½Π°ΡΡΡΠΎΠΉΠΊΠ΅ Ρ Π·Π°ΠΌΠ΅ΡΠΈΠ» Π½ΠΎΠ²ΡΠ΅ ΡΡΡΠΎΠΊΠΈ Π² Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ°Ρ
, ΠΏΠ΅ΡΠ΅Π΄Π°Π²Π°Π΅ΠΌΡΡ
ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ. ΠΠΎ ΠΊΠΎΠ³Π΄Π° Ρ ΠΏΠΎΠΏΡΡΠ°Π»ΡΡ Π²ΠΎΡΠΏΡΠΎΠΈΠ·Π²Π΅ΡΡΠΈ ΡΡΠΎ Π² ΠΌΠΎΠ΄ΡΠ»ΡΠ½ΠΎΠΌ ΡΠ΅ΡΡΠ΅, Ρ ΠΏΠΎΠ»ΡΡΠΈΠ» ΡΠΊΠ°Π·Π°Π½Π½ΠΎΠ΅ Π²ΡΡΠ΅ ValueError
ΠΏΡΠΈ ΡΠΎΠ·Π΄Π°Π½ΠΈΠΈ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΎΠ² Π·Π°ΠΏΡΠΎΡΠ°.
Π― ΠΏΡΠΎΠ²Π΅Π» Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ Π±ΠΎΠ»ΡΡΠ΅ ΠΈΡΡΠ»Π΅Π΄ΠΎΠ²Π°Π½ΠΈΠΉ ΠΏΠΎ ΡΡΠΎΠΉ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠ΅ ΠΈ ΠΎΠ±Π½Π°ΡΡΠΆΠΈΠ» ΡΠ»Π΅Π΄ΡΡΡΠ΅Π΅:
Π ΡΠΏΠ΅ΡΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ HTTP ( RFC 2616 ) ΡΠΊΠ°Π·Π°Π½ΠΎ, ΡΡΠΎ ΡΠΈΠΌΠ²ΠΎΠ»Ρ Π½ΠΎΠ²ΠΎΠΉ ΡΡΡΠΎΠΊΠΈ Π² Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ°Ρ ΠΠΠΠ£Π’ Π±ΡΡΡ Π·Π°ΠΌΠ΅Π½Π΅Π½Ρ ΠΎΠ΄Π½ΠΈΠΌ ΠΏΡΠΎΠ±Π΅Π»ΠΎΠΌ, Π° Π½Π΅ Π³Π°ΡΠ°Π½ΡΠΈΡΠΎΠ²Π°Π½Π½ΠΎ (ΡΠΌ. Π¦ΠΈΡΠ°ΡΡ Π²ΡΡΠ΅).
Π‘ΠΏΠ΅ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ CGI ( RFC 3875 ), ΠΊΠΎΡΠΎΡΡΡ ΡΠ°ΡΡΠΈΡΡΠ΅Ρ WSGI, ΡΡΠ΅Π±ΡΠ΅Ρ Π·Π°ΠΌΠ΅Π½Ρ Π½ΠΎΠ²ΡΡ ΡΡΡΠΎΠΊ Π² Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ°Ρ Π·Π°ΠΏΡΠΎΡΠΎΠ²:
Π’ΠΎΡΠ½ΠΎ ΡΠ°ΠΊ ΠΆΠ΅ ΠΏΠΎΠ»Π΅ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ°, ΠΊΠΎΡΠΎΡΠΎΠ΅ ΠΎΡ Π²Π°ΡΡΠ²Π°Π΅Ρ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΡΡΡΠΎΠΊ, ΠΠΠΠΠΠ Π±ΡΡΡ ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½Π΅Π½ΠΎ Π² ΠΎΠ΄Π½Ρ ΡΡΡΠΎΠΊΡ.
Π‘ΠΏΠ΅ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ WSGI ( PEP 333 ) ΡΠ°ΠΊΠΆΠ΅ Π·Π°ΠΏΡΠ΅ΡΠ°Π΅Ρ ΡΠΈΠΌΠ²ΠΎΠ»Ρ Π½ΠΎΠ²ΠΎΠΉ ΡΡΡΠΎΠΊΠΈ Π² Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ°Ρ ΠΎΡΠ²Π΅ΡΠΎΠ²:
ΠΠ°ΠΆΠ΄ΡΠΉ
header_value
Π½Π΅ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π²ΠΊΠ»ΡΡΠ°ΡΡ Π½ΠΈΠΊΠ°ΠΊΠΈΡ ΡΠΏΡΠ°Π²Π»ΡΡΡΠΈΡ ΡΠΈΠΌΠ²ΠΎΠ»ΠΎΠ², Π²ΠΊΠ»ΡΡΠ°Ρ ΡΠΈΠΌΠ²ΠΎΠ»Ρ Π²ΠΎΠ·Π²ΡΠ°ΡΠ° ΠΊΠ°ΡΠ΅ΡΠΊΠΈ ΠΈΠ»ΠΈ ΠΏΠ΅ΡΠ΅Π²ΠΎΠ΄Π° ΡΡΡΠΎΠΊΠΈ, ΠΊΠ°ΠΊ Π²ΡΡΡΠΎΠ΅Π½Π½ΡΠ΅, ΡΠ°ΠΊ ΠΈ Π² ΠΊΠΎΠ½ΡΠ΅.
ΠΡΠΎ ΠΎΠ·Π½Π°ΡΠ°Π΅Ρ, ΡΡΠΎ Π·Π΄Π΅ΡΡ Π΅ΡΡΡ Π΄Π²Π΅ ΠΎΡΠΈΠ±ΠΊΠΈ:
Π‘Π΅ΡΠ²Π΅Ρ ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠΈ werkzeug Π½Π΅ΠΏΡΠ°Π²ΠΈΠ»ΡΠ½ΠΎ Π½ΠΎΡΠΌΠ°Π»ΠΈΠ·ΡΠ΅Ρ ΡΠ²Π΅ΡΠ½ΡΡΡΠ΅ ΡΡΡΠΎΠΊΠΈ Π² Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ°Ρ Π·Π°ΠΏΡΠΎΡΠΎΠ².
ΠΠ±ΡΠ΅ΠΊΡ Headers
Π½Π΅ΡΠΎΠ²ΠΌΠ΅ΡΡΠΈΠΌ Ρ ΠΏΡΠΈΠ΅ΠΌΠΎΠΌ Π½ΠΎΠ²ΠΎΠΉ ΡΡΡΠΎΠΊΠΈ Π² Π·Π½Π°ΡΠ΅Π½ΠΈΡΡ
Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΎΠ². ΠΠΎΠ²ΡΠ΅ ΡΡΡΠΎΠΊΠΈ ΠΏΡΠΈΠ½ΠΈΠΌΠ°ΡΡΡΡ Π² ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΎΡΠ΅, Π½ΠΎ Π½Π΅ Π² ΠΌΠ΅ΡΠΎΠ΄Π΅ add()
. ΠΠ΅ΡΠΎΡΡΠ½ΠΎ, Π»ΡΡΡΠ΅, ΡΡΠΎΠ±Ρ ΠΎΠ±ΡΠ΅ΠΊΡ Headers
ΠΎΡΡΠ°Π²Π°Π»ΡΡ ΡΠ°Π·ΡΠ΅ΡΠ°ΡΡΠΈΠΌ ΠΈ Π²ΡΠΏΠΎΠ»Π½ΡΠ» ΠΏΡΠΎΠ²Π΅ΡΠΊΡ ΠΏΡΠΈ ΡΠ°ΠΊΡΠΈΡΠ΅ΡΠΊΠΎΠΌ ΠΏΠΎΡΡΡΠΎΠ΅Π½ΠΈΠΈ ΠΎΡΠ²Π΅ΡΠ° WSGI Π² BaseResponse
. Π’Π°ΠΊΠΈΠΌ ΠΎΠ±ΡΠ°Π·ΠΎΠΌ, Π·Π°ΠΏΡΠ΅ΡΠ΅Π½ΠΈΠ΅ Π½ΠΎΠ²ΠΎΠΉ ΡΡΡΠΎΠΊΠΈ Π² ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΎΡΠ΅ Π½Π΅ Π½Π°ΡΡΡΠΈΡ ΡΠΎΠ²ΠΌΠ΅ΡΡΠΈΠΌΠΎΡΡΡ Ρ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ Π½Π΅ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΡΡΠΈΠΌΠΈ ΡΠ΅ΡΠ²Π΅ΡΠ°ΠΌΠΈ WSGI (ΡΠ°ΠΊΠΈΠΌΠΈ ΠΊΠ°ΠΊ ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½ΡΠΉ ΡΠ΅ΡΠ²Π΅Ρ ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠΈ werkzeug).
Π‘ΠΏΡΠ°Π²Π΅Π΄Π»ΠΈΠ²ΠΎ. Π’Π°ΠΊΠΆΠ΅ Π΅ΡΡΡ Π½ΠΎΠΌΠ΅Ρ 1070, ΠΊΠΎΡΠΎΡΡΠΉ ΠΈΠ³ΡΠ°Π΅Ρ Π² ΡΡΠΎ.
Π‘ΠΎΠ²Π΅ΡΡΠ΅Π½Π½ΠΎ ΡΠ²Π΅ΡΠ΅Π½, ΡΡΠΎ ΡΡΠΎ Π±ΡΠ»ΠΎ ΠΈΡΠΏΡΠ°Π²Π»Π΅Π½ΠΎ Ρ ΠΏΠΎΠΌΠΎΡΡΡ ΠΈΡΠΏΡΠ°Π²Π»Π΅Π½ΠΈΡ Π΄Π»Ρ # 1070. ΠΡΠ»ΠΈ Π½Π΅Ρ, ΡΠΎΠΎΠ±ΡΠΈΡΠ΅ ΠΌΠ½Π΅ Π²ΠΎΡΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΠΌΡΠΉ ΠΏΡΠΈΠΌΠ΅Ρ.
@davidism ΠΠ°ΠΊ Ρ ΡΠΆΠ΅ ΡΠΏΠΎΠΌΠΈΠ½Π°Π» Π² ΠΏΡΠ΅Π΄ΡΠ΄ΡΡΠ΅ΠΌ ΠΊΠΎΠΌΠΌΠ΅Π½ΡΠ°ΡΠΈΠΈ, Π½Π° ΡΠ°ΠΌΠΎΠΌ Π΄Π΅Π»Π΅ Π·Π΄Π΅ΡΡ Π΅ΡΡΡ Π΄Π²Π΅ ΠΎΡΠΈΠ±ΠΊΠΈ, Π½ΠΈ ΠΎΠ΄Π½Π° ΠΈΠ· ΠΊΠΎΡΠΎΡΡΡ Π½Π΅ Π±ΡΠ»Π° ΠΈΡΠΏΡΠ°Π²Π»Π΅Π½Π° ββΠ² ΡΠ΅ΠΊΡΡΠ΅ΠΉ ΠΎΡΠ½ΠΎΠ²Π½ΠΎΠΉ Π²Π΅ΡΠΊΠ΅.
ΠΠ΅ΡΠ²Π°Ρ ΠΎΡΠΈΠ±ΠΊΠ° ΡΠ²ΡΠ·Π°Π½Π° Ρ ΡΠ΅ΠΌ, ΠΊΠ°ΠΊ ΡΠ΅ΡΠ²Π΅Ρ ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠΈ werkzeug ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°Π΅Ρ ΡΡΡΠΎΠΊΠΎΠ²ΡΠ΅ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΈ. ΠΠ³ΠΎ ΠΌΠΎΠΆΠ½ΠΎ Π²ΠΎΡΠΏΡΠΎΠΈΠ·Π²Π΅ΡΡΠΈ Ρ ΠΏΠΎΠΌΠΎΡΡΡ ΡΠ»Π΅Π΄ΡΡΡΠ΅Π³ΠΎ ΡΠ΅ΡΠ²Π΅ΡΠ½ΠΎΠ³ΠΎ ΠΊΠΎΠ΄Π°, ΠΊΠΎΡΠΎΡΡΠΉ ΠΏΠ΅ΡΠ°ΡΠ°Π΅Ρ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° X-Example
:
from werkzeug.serving import run_simple
from werkzeug.wrappers import Request, Response
def app(environ, start_response):
request = Request(environ)
print(repr(request.headers.get('X-Example')))
response = Response(status=204)
return response(environ, start_response)
run_simple('localhost', 8080, app)
ΠΠ°ΡΠ΅ΠΌ ΠΌΡ ΠΌΠΎΠΆΠ΅ΠΌ ΠΎΡΠΏΡΠ°Π²ΠΈΡΡ Π΅ΠΌΡ Π·Π°ΠΏΡΠΎΡ Ρ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΎΠΌ, ΠΎΡ Π²Π°ΡΡΠ²Π°ΡΡΠΈΠΌ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΡΡΡΠΎΠΊ:
GET / HTTP/1.1
Host: localhost:8080
Connection: close
X-Example: foo
bar
ΠΠΆΠΈΠ΄Π°Π΅ΠΌΡΠΉ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ ΡΠ΅ΡΠ²Π΅ΡΠ°:
ΠΠ½Π°ΡΠ΅Π½ΠΈΠ΅ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½Π΅Π½ΠΎ Π² ΠΎΠ΄Π½Ρ ΡΡΡΠΎΠΊΡ
'foo bar'
Π€Π°ΠΊΡΠΈΡΠ΅ΡΠΊΠΈΠΉ Π²ΡΠ²ΠΎΠ΄ ΡΠ΅ΡΠ²Π΅ΡΠ° (Python 2):
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 57361)
Traceback (most recent call last):
File "/usr/lib/python2.7/SocketServer.py", line 295, in _handle_request_noblock
self.process_request(request, client_address)
File "/usr/lib/python2.7/SocketServer.py", line 321, in process_request
self.finish_request(request, client_address)
File "/usr/lib/python2.7/SocketServer.py", line 334, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/usr/lib/python2.7/SocketServer.py", line 649, in __init__
self.handle()
File "/home/.../venv/local/lib/python2.7/site-packages/werkzeug/serving.py", line 320, in handle
rv = BaseHTTPRequestHandler.handle(self)
File "/usr/lib/python2.7/BaseHTTPServer.py", line 340, in handle
self.handle_one_request()
File "/home/.../venv/local/lib/python2.7/site-packages/werkzeug/serving.py", line 355, in handle_one_request
return self.run_wsgi()
File "/home/.../venv/local/lib/python2.7/site-packages/werkzeug/serving.py", line 238, in run_wsgi
self.environ = environ = self.make_environ()
File "/home/.../venv/local/lib/python2.7/site-packages/werkzeug/serving.py", line 217, in make_environ
for key, value in self.get_header_items():
File "/home/.../venv/local/lib/python2.7/site-packages/werkzeug/serving.py", line 441, in get_header_items
key, value = header[0:-2].split(":", 1)
ValueError: need more than 1 value to unpack
----------------------------------------
Π€Π°ΠΊΡΠΈΡΠ΅ΡΠΊΠΈΠΉ Π²ΡΠ²ΠΎΠ΄ ΡΠ΅ΡΠ²Π΅ΡΠ° (Python 3):
ΠΠ½Π°ΡΠ΅Π½ΠΈΠ΅ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ ΡΠΈΠΌΠ²ΠΎΠ»Ρ Π½ΠΎΠ²ΠΎΠΉ ΡΡΡΠΎΠΊΠΈ, Π·Π°ΠΏΡΠ΅ΡΠ΅Π½Π½ΡΠ΅ ΡΠΏΠ΅ΡΠΈΡΠΈΠΊΠ°ΡΠΈΠ΅ΠΉ WSGI.
'foo\r\n bar'
ΠΡΠΎΡΠ°Ρ ΠΎΡΠΈΠ±ΠΊΠ° ΡΠ²ΡΠ·Π°Π½Π° Ρ ΡΠ΅ΠΌ, ΠΊΠ°ΠΊ ΠΎΠ±ΡΠ΅ΠΊΡ Headers
ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°Π΅Ρ Π·Π½Π°ΡΠ΅Π½ΠΈΡ Π½ΠΎΠ²ΠΎΠΉ ΡΡΡΠΎΠΊΠΈ.
>>> from werkzeug import Headers
>>> h1 = Headers([('X-Example', 'foo\r\n bar')])
>>> h2 = Headers()
>>> h2.add('X-Example', 'foo\r\n bar')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/.../venv3/lib/python3.6/site-packages/werkzeug/datastructures.py", line 1166, in add
self._validate_value(_value)
File "/home/.../venv3/lib/python3.6/site-packages/werkzeug/datastructures.py", line 1173, in _validate_value
raise ValueError('Detected newline in header value. This is '
ValueError: Detected newline in header value. This is a potential security problem
ΠΠΆΠΈΠ΄Π°Π΅ΠΌΡΠΉ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ:
ΠΠ±Π΅ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ Π΄ΠΎΠ»ΠΆΠ½Ρ ΠΈΠΌΠ΅ΡΡ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΡΠΉ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ, Π±ΡΠ΄Ρ ΡΠΎ ValueError
ΠΈΠ»ΠΈ ΡΡΠΏΠ΅Ρ
.
Π€Π°ΠΊΡΠΈΡΠ΅ΡΠΊΠΈΠΉ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ:
ΠΠΎΠ½ΡΡΡΡΠΊΡΠΎΡ Headers
ΡΠ°Π·ΡΠ΅ΡΠ°Π΅Ρ ΠΏΠ΅ΡΠ΅Π²ΠΎΠ΄ ΡΡΡΠΎΠΊΠΈ, Π° Headers.add()
ΡΠ²Π΅Π»ΠΈΡΠΈΠ²Π°Π΅Ρ ValueError
.
ΠΠ΅Π΄Π°Π²Π½ΠΎ Ρ Π²ΠΈΠ΄Π΅Π» ValueError
Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΈΠ· Π½Π°ΡΠΈΡ
ΠΏΡΠΎΠ΅ΠΊΡΠΎΠ² (Python 2.7 Ρ Flask), ΠΊΠΎΡΠΎΡΡΠΉ Π½Π°Ρ
ΠΎΠ΄ΠΈΡΡΡ Π·Π° ΠΏΡΠΎΠΊΡΠΈ-ΡΠ΅ΡΠ²Π΅ΡΠΎΠΌ nginx. Π ΠΈΡΠΎΠ³Π΅ Ρ Π²Π΅ΡΠ½ΡΠ»ΡΡ ΠΊ 0.14.1
(ΠΏΠ΅ΡΠ΅ΠΎΠΏΡΠ΅Π΄Π΅Π»ΠΈΠ² Π²Π΅ΡΡΠΈΡ, ΡΠ²ΡΠ·Π°Π½Π½ΡΡ Ρ Flask
), ΠΈ ΠΌΠΎΡ ΠΎΡΠΈΠ±ΠΊΠ° ΠΈΡΡΠ΅Π·Π»Π°. ΠΡΠΌΠ°Π», ΡΡΠΎ Π΄ΠΎΠ±Π°Π²Π»Ρ, ΡΠ°ΠΊ ΠΊΠ°ΠΊ ΠΊΠ°ΠΆΠ΅ΡΡΡ, ΡΡΠΎ Π²Π΅ΡΠ²Ρ 0.15.x
ΠΏΡΠ΅Π΄ΡΡΠ°Π²ΠΈΠ»Π° ΡΡΡ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ (ΠΈΠ»ΠΈ ΠΏΠΎΡΠ΅Π½ΡΠΈΠ°Π»ΡΠ½ΠΎ ΡΠΎΠ·Π΄Π°Π»Π° Π½ΠΎΠ²ΡΡ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ Ρ ΡΠ΅ΠΌ, ΠΊΠ°ΠΊ ΠΎΠ½Π° ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°Π»Π° Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΈ Π·Π°ΠΏΡΠΎΡΠΎΠ²).
------ΠΠΠΠΠΠΠ’Π¬-------:
Π― ΠΎΡΡΠ»Π΅Π΄ΠΈΠ», ΠΊΠ°ΠΊΠΈΠ΅ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΈ ΠΌΡ ΠΏΠ΅ΡΠ΅Π΄Π°Π»ΠΈ, ΠΈ ΠΎΠ΄ΠΈΠ½ ΠΈΠ· Π½ΠΈΡ Π±ΡΠ» ΠΌΠ½ΠΎΠ³ΠΎΡΡΡΠΎΡΠ½ΡΠΌ ΡΠ΅ΡΡΠΈΡΠΈΠΊΠ°ΡΠΎΠΌ Π² ΡΠΎΡΠΌΠ°ΡΠ΅ pem, ΡΠΎ Π΅ΡΡΡ:
SSL_CLIENT_CERT: -----BEGIN CERTIFICATE-----
MIIFHzCCAwegAwIBAgICEDgwDQYJKoZIhvcNAQELBQAwajELMAkGA1UEBhMCdXMx
GDAWBgNVBAoMD3Uucy4gZ292ZXJubWVudDEPMA0GA1UECwwGcGVvcGxlMQwwCgYD
VQQLDANkYWUxEDAOBgNVBAsMB2NoaW1lcmExEDAOBgNVBAMMB0ludGVyQ0EwHhcN
MTcwODMxMTUwMzEwWhcNMjcwODI5MTUwMzEwWjBwMQswCQYDVQQGEwJVUzEYMBYG
A1UECgwPVS5TLiBHb3Zlcm5tZW50MRAwDgYDVQQLDAdjaGltZXJhMQwwCgYDVQQL
....
-----END CERTIFICATE-----
ΠΠ°Ρ ΡΠ΅ΡΠ²Π΅Ρ nginx Π±ΡΠ» Π½Π°ΡΡΡΠΎΠ΅Π½ ΡΠ°ΠΊ:
proxy_set_header SSL_CLIENT_CERT $ssl_client_cert;
ΠΠ΅ΡΠΎΡΡΠ½ΠΎ, Π½Π°ΠΌ ΡΠ»Π΅Π΄ΡΠ΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ $ssl_client_escaped_cert
Π²ΠΌΠ΅ΡΡΠΎ $ssl_client_cert
(ΡΠ°ΠΊ ΠΊΠ°ΠΊ ΡΡΠΎ Π² Π»ΡΠ±ΠΎΠΌ ΡΠ»ΡΡΠ°Π΅ ΡΡΡΠ°ΡΠ΅Π»ΠΎ). ΠΠ΅ ΡΠ²Π΅ΡΠ΅Π½, ΡΡΠΎ ΡΡΠΎ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ ΡΠ΅ΡΠΈΡ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ Ρ ΡΠΈΠ½ΡΠ°ΠΊΡΠΈΡΠ΅ΡΠΊΠΈΠΌ Π°Π½Π°Π»ΠΈΠ·ΠΎΠΌ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ°.
ΠΠ°Π΄Π΅ΡΡΡ, ΡΡΠΎ ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ Π²ΡΠ΅ΠΌ, ΠΊΡΠΎ ΡΡΠ°Π»ΠΊΠΈΠ²Π°Π΅ΡΡΡ Ρ ΡΡΠΎΠΉ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠΎΠΉ. ΠΠΎΡ
ΠΎΠΆΠ΅, ΡΡΠΎ 0.15.1
Π½Π΅ΠΏΡΠ°Π²ΠΈΠ»ΡΠ½ΠΎ ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°Π΅Ρ ΠΌΠ½ΠΎΠ³ΠΎΡΡΡΠΎΡΠ½ΡΠΉ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ, ΡΠ°ΠΊΠΎΠΉ ΠΊΠ°ΠΊ ΡΠ΅ΡΡΠΈΡΠΈΠΊΠ°Ρ PEM, Π² Π½Π°ΡΡΠΎΡΡΠ΅Π΅ Π²ΡΠ΅ΠΌΡ Ρ Python 2.7.
ΠΡΠΎ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠ° Π²Π΅ΡΡΠΈΠΈ 2.7, ΡΠ½ΠΎΠ²Π° Π²ΡΠ·Π²Π°Π½Π½Π°Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΎΠΉ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° ΡΠ΅ΡΠ²Π΅ΡΠ° ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠΈ. Π― Π΄ΠΎΠ±Π°Π²Π»ΡΡ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ ΡΠ²ΠΎΡΠ°ΡΠΈΠ²Π°Π½ΠΈΡ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΎΠ² Π² ΠΊΠΎΠ΄ ΡΠΎΠ²ΠΌΠ΅ΡΡΠΈΠΌΠΎΡΡΠΈ 2.7 Π΄Π»Ρ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΎΠ² Π·Π°ΠΏΡΠΎΡΠΎΠ².
ΠΠΎΠ΄ΡΠ²Π΅ΡΠΆΠ΄Π΅Π½ΠΎ, ΡΡΠΎ ΠΎΡΠΈΠ±ΠΊΠ° ΡΠ΅ΡΠ²Π΅ΡΠ° ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠΈ ΡΠ΅ΠΏΠ΅ΡΡ ΠΈΡΠΏΡΠ°Π²Π»Π΅Π½Π° ββΠΊΠ°ΠΊ Π² Python 2, ΡΠ°ΠΊ ΠΈ Π² 3. ΠΡΠΎΡΠ°Ρ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠ° Ρ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠΌ Headers
Π²ΡΠ΅ Π΅ΡΠ΅ ΠΏΡΠΈΡΡΡΡΡΠ²ΡΠ΅Ρ. ΠΡΠΊΡΡΡ β1608.
Π‘Π°ΠΌΡΠΉ ΠΏΠΎΠ»Π΅Π·Π½ΡΠΉ ΠΊΠΎΠΌΠΌΠ΅Π½ΡΠ°ΡΠΈΠΉ
@davidism ΠΠ°ΠΊ Ρ ΡΠΆΠ΅ ΡΠΏΠΎΠΌΠΈΠ½Π°Π» Π² ΠΏΡΠ΅Π΄ΡΠ΄ΡΡΠ΅ΠΌ ΠΊΠΎΠΌΠΌΠ΅Π½ΡΠ°ΡΠΈΠΈ, Π½Π° ΡΠ°ΠΌΠΎΠΌ Π΄Π΅Π»Π΅ Π·Π΄Π΅ΡΡ Π΅ΡΡΡ Π΄Π²Π΅ ΠΎΡΠΈΠ±ΠΊΠΈ, Π½ΠΈ ΠΎΠ΄Π½Π° ΠΈΠ· ΠΊΠΎΡΠΎΡΡΡ Π½Π΅ Π±ΡΠ»Π° ΠΈΡΠΏΡΠ°Π²Π»Π΅Π½Π° ββΠ² ΡΠ΅ΠΊΡΡΠ΅ΠΉ ΠΎΡΠ½ΠΎΠ²Π½ΠΎΠΉ Π²Π΅ΡΠΊΠ΅.
ΠΠ΅ΡΠ²Π°Ρ ΠΎΡΠΈΠ±ΠΊΠ° ΡΠ²ΡΠ·Π°Π½Π° Ρ ΡΠ΅ΠΌ, ΠΊΠ°ΠΊ ΡΠ΅ΡΠ²Π΅Ρ ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠΈ werkzeug ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°Π΅Ρ ΡΡΡΠΎΠΊΠΎΠ²ΡΠ΅ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΈ. ΠΠ³ΠΎ ΠΌΠΎΠΆΠ½ΠΎ Π²ΠΎΡΠΏΡΠΎΠΈΠ·Π²Π΅ΡΡΠΈ Ρ ΠΏΠΎΠΌΠΎΡΡΡ ΡΠ»Π΅Π΄ΡΡΡΠ΅Π³ΠΎ ΡΠ΅ΡΠ²Π΅ΡΠ½ΠΎΠ³ΠΎ ΠΊΠΎΠ΄Π°, ΠΊΠΎΡΠΎΡΡΠΉ ΠΏΠ΅ΡΠ°ΡΠ°Π΅Ρ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ°
X-Example
:ΠΠ°ΡΠ΅ΠΌ ΠΌΡ ΠΌΠΎΠΆΠ΅ΠΌ ΠΎΡΠΏΡΠ°Π²ΠΈΡΡ Π΅ΠΌΡ Π·Π°ΠΏΡΠΎΡ Ρ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΎΠΌ, ΠΎΡ Π²Π°ΡΡΠ²Π°ΡΡΠΈΠΌ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΡΡΡΠΎΠΊ:
ΠΠΆΠΈΠ΄Π°Π΅ΠΌΡΠΉ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ ΡΠ΅ΡΠ²Π΅ΡΠ°:
ΠΠ½Π°ΡΠ΅Π½ΠΈΠ΅ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½Π΅Π½ΠΎ Π² ΠΎΠ΄Π½Ρ ΡΡΡΠΎΠΊΡ
Π€Π°ΠΊΡΠΈΡΠ΅ΡΠΊΠΈΠΉ Π²ΡΠ²ΠΎΠ΄ ΡΠ΅ΡΠ²Π΅ΡΠ° (Python 2):
Π€Π°ΠΊΡΠΈΡΠ΅ΡΠΊΠΈΠΉ Π²ΡΠ²ΠΎΠ΄ ΡΠ΅ΡΠ²Π΅ΡΠ° (Python 3):
ΠΠ½Π°ΡΠ΅Π½ΠΈΠ΅ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ ΡΠΈΠΌΠ²ΠΎΠ»Ρ Π½ΠΎΠ²ΠΎΠΉ ΡΡΡΠΎΠΊΠΈ, Π·Π°ΠΏΡΠ΅ΡΠ΅Π½Π½ΡΠ΅ ΡΠΏΠ΅ΡΠΈΡΠΈΠΊΠ°ΡΠΈΠ΅ΠΉ WSGI.
ΠΡΠΎΡΠ°Ρ ΠΎΡΠΈΠ±ΠΊΠ° ΡΠ²ΡΠ·Π°Π½Π° Ρ ΡΠ΅ΠΌ, ΠΊΠ°ΠΊ ΠΎΠ±ΡΠ΅ΠΊΡ
Headers
ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°Π΅Ρ Π·Π½Π°ΡΠ΅Π½ΠΈΡ Π½ΠΎΠ²ΠΎΠΉ ΡΡΡΠΎΠΊΠΈ.ΠΠΆΠΈΠ΄Π°Π΅ΠΌΡΠΉ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ:
ΠΠ±Π΅ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ Π΄ΠΎΠ»ΠΆΠ½Ρ ΠΈΠΌΠ΅ΡΡ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΡΠΉ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ, Π±ΡΠ΄Ρ ΡΠΎ
ValueError
ΠΈΠ»ΠΈ ΡΡΠΏΠ΅Ρ .Π€Π°ΠΊΡΠΈΡΠ΅ΡΠΊΠΈΠΉ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ:
ΠΠΎΠ½ΡΡΡΡΠΊΡΠΎΡ
Headers
ΡΠ°Π·ΡΠ΅ΡΠ°Π΅Ρ ΠΏΠ΅ΡΠ΅Π²ΠΎΠ΄ ΡΡΡΠΎΠΊΠΈ, Π°Headers.add()
ΡΠ²Π΅Π»ΠΈΡΠΈΠ²Π°Π΅ΡValueError
.