Jinja: urlencode๋Š” ์Šฌ๋ž˜์‹œ๋ฅผ ์ด์Šค์ผ€์ดํ”„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค

์— ๋งŒ๋“  2015๋…„ 11์›” 20์ผ  ยท  21์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: pallets/jinja

์ด๊ฒƒ์€ #444์—์„œ ์ œ๊ธฐ๋˜์—ˆ์ง€๋งŒ ์ด ์ฝ”๋“œ ๋Š” Python 3.4.1์—์„œ ํ•ญ์ƒ b'/' ํ‰๊ฐ€๋˜๋ฏ€๋กœ ์Šฌ๋ž˜์‹œ๋Š” ์—ฌ์ „ํžˆ ์ด์Šค์ผ€์ดํ”„๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

API ํ˜ธ์ถœ์„ ํ†ตํ•ด gitlab ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— ํŒŒ์ผ์„ ๋งŒ๋“ค๋ ค๊ณ  ํ•  ๋•Œ ์ด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. gitlab API๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์Šฌ๋ž˜์‹œ๋ฅผ ์ธ์ฝ”๋”ฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. {{ myvar | urlencode | regex_replace('/','%2F') }}. ํ”Œ๋ ˆ์ด๋ถ ์ž‘์—…์—์„œ Ansible ๋ฐ Jinja2 ํ•„ํ„ฐ๋กœ ์ž‘์—…ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋‚ด๊ฐ€ ์ž‘๋™ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์„ ์น˜๋Š” ์‚ฌ๋žŒ๋“ค์„ ์œ„ํ•œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ชจ๋“  21 ๋Œ“๊ธ€

๊ทธ๋ƒฅ ์กฐ์‹ฌ @mitsuhiko
์ด์œ ๋Š” ๋ชจ๋ฅด๊ฒ ์ง€๋งŒ do_urlencode ์—ฌ์ „ํžˆ ์Šฌ๋ž˜์‹œ๋ฅผ ์ด์Šค์ผ€์ดํ”„ํ•˜์ง€ ์•Š๋Š” ๋ฐ˜๋ฉด unicode_urlencode ๋Š” ์˜ˆ์ƒ๋Œ€๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

Python 3.4.3 (default, Oct 14 2015, 20:28:29)
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import jinja2
>>> jinja2.utils.unicode_urlencode("http://url.by", for_qs=True)
'http%3A%2F%2Furl.by'
>>> jinja2.filters.do_urlencode("http://url.by")
'http%3A//url.by'
>>> jinja2.__version__
'2.9.dev'

urlencode ํ•„ํ„ฐ๋Š” ์Šฌ๋ž˜์‹œ๋ฅผ ์ด์Šค์ผ€์ดํ”„ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ผญ ๊ทธ๋ž˜์•ผ ํ•˜๋Š” ํŠน๋ณ„ํ•œ ์ด์œ ๊ฐ€ ์žˆ๋‚˜์š”? ์ด๊ฒƒ์„ ๋ช…ํ™•ํžˆ ํ•˜๊ธฐ ์œ„ํ•ด: ์ „๋‹ฌ๋œ ํ‚ค/๊ฐ’ ์Œ์˜ ๊ฐ’ ์œ„์น˜์—์„œ ์Šฌ๋ž˜์‹œ๋งŒ ์ธ์ฝ”๋”ฉํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด URL ์ธ์ฝ”๋”ฉ์„ ์œ„ํ•œ ๊ธฐ๋Šฅ์˜ ํ‘œ์ค€ ๋™์ž‘์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. http://meyerweb.com/eric/tools/dencoder/ ์™€ ๊ฐ™์€ ๋„๊ตฌ๋Š” ์ด๋Ÿฌํ•œ ๋ฐฉ์‹์œผ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ์ด์Šค์ผ€์ดํ”„ ์ฒ˜๋ฆฌ๋œ ์Šฌ๋ž˜์‹œ๊ฐ€ ์žˆ๋Š” GET ์š”์ฒญ ๋‚ด๋ถ€์— URL์ด ์ „๋‹ฌ๋  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒํ•˜๋Š” ํšŒ์‚ฌ ๋‚ด๋ถ€์— ํ•˜๋‚˜ ์ด์ƒ์˜ ๋„๊ตฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
๋˜ํ•œ, ๋‚˜๋Š” ์ดํ•ดํ•˜์ง€ ์•Š๋Š” ์ด์œ  unicode_urlencode ๋ผ๋Š” ๋‚ด๋ถ€ do_urlencode ์™€ for_qs=True .
์ œ๊ฐ€ ๋ญ”๊ฐ€ ์ž˜๋ชป ์ดํ•ดํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ์ผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์Šฌ๋ž˜์‹œ๋Š” ๊ฒฝ๋กœ ๊ตฌ์„ฑ ์š”์†Œ์˜ ์˜ˆ์•ฝ๋œ ๋ฌธ์ž์ด๋ฉฐ ๋” ์ผ๋ฐ˜์ ์ธ ๋™์ž‘์€ URL ์ธ์ฝ”๋”ฉ ๋™์ž‘์„ ๊ฐ•์ œํ•  ๋•Œ ์Šฌ๋ž˜์‹œ๋ฅผ ์ œ์™ธํ•œ ๋ชจ๋“  ๊ฒƒ์„ ์ธ์ฝ”๋”ฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. (์Šฌ๋ž˜์‹œ๋ฅผ %2f ๋กœ ์ธ์ฝ”๋”ฉํ•˜๋Š”) ๋Œ€์•ˆ์€ ๋ฐฑ์—”๋“œ ์„œ๋ฒ„๊ฐ€ ์ผ๋ฐ˜์ ์œผ๋กœ %2f ๋ฐ / ๋ฅผ ๊ตฌ๋ณ„ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๋ณด์•ˆ ๋ฌธ์ œ๋กœ ์ธํ•ด ๋Œ€๋ถ€๋ถ„์˜ ์„œ๋ฒ„๊ฐ€ ์ด๋Ÿฌํ•œ ์š”์ฒญ์„ ์™„์ „ํžˆ ๊ฑฐ๋ถ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์˜๋ฏธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋””์ฝ”๋”ฉ๋œ ์˜ฅํ…Ÿ์—์„œ ์ž‘๋™ํ•  ๋•Œ ๊ฒฝ๋กœ ๊ตฌ์„ฑ ์š”์†Œ.

๋”ฐ๋ผ์„œ ์Šฌ๋ž˜์‹œ๊ฐ€ ์‹ค์ œ๋กœ ์ธ์ฝ”๋”ฉ์ด ์˜๋ฏธ๊ฐ€ ์žˆ๋Š” ์œ ์ผํ•œ ๋ถ€๋ถ„์€ ์ฟผ๋ฆฌ ๋ฌธ์ž์—ด์— ์žˆ์œผ๋ฉฐ ์—ฌ๊ธฐ์—์„œ urlencode ์˜ dict ๊ธฐ๋ฐ˜ ์ธ์ฝ”๋”๊ฐ€ ๊ทธ๋ ‡๊ฒŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์Šฌ๋ž˜์‹œ๊ฐ€ ์žˆ์–ด๋„ ์ธ์ฝ”๋”ฉํ•  ํ•„์š”๊ฐ€ ์—†์œผ๋ฏ€๋กœ ์ธ์ฝ”๋”ฉ์„ ๊ฐ•์ œํ•  ์ด์œ ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

urlencode ํ•จ์ˆ˜๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋ฏ€๋กœ ์Šฌ๋ž˜์‹œ๋ฅผ ์ธ์ฝ”๋”ฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ •์˜ ์š”๊ตฌ ์‚ฌํ•ญ์ด ์žˆ๋Š” ๊ฒฝ์šฐ ํ•„ํ„ฐ ๋“ฑ๋ก์—์„œ ๊ธฐ๋Šฅ์„ ์žฌ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ™•์ธ. ์•„๋ฅด๋ฏผ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

์•ˆ๋…•ํ•˜์„ธ์š”, ์Šฌ๋ž˜์‹œ ๊ฑฐ๋ถ€์™€ ๋™์ผํ•œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

jinja2.Template("{{ ๋””์Šคํฌ|๊ฑฐ๋ถ€('sameas', '/')|๋ชฉ๋ก }}").render(disks=["/", "/mnt/disk0", "/mnt/disk1"])
์œ "['/', '/mnt/disk0', '/mnt/disk1']"

๋ฃจํŠธ ๋””์Šคํฌ๋ฅผ ๊ฑฐ๋ถ€ํ•˜๊ณ  ์‹ถ์ง€๋งŒ ๋” ์ด์ƒ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

>>> import jinja2
>>> jinja2.Template("{{ disks|reject('sameas', '/')|list }}").render(disks=["/", "/mnt/disk0", "/mnt/disk1"])
u"['/mnt/disk0', '/mnt/disk1']"
>>> jinja2.__version__
Out[3]: '2.8'

๋‚˜๋ฅผ ์œ„ํ•ด ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

@ThiefMaster๊ฐ€ ์—ฌ์ „ํžˆ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํŒŒ์ด์ฌ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? ์‚ฌ์šฉํ•œ ํŒŒ์ด์ฌ ๋ฒ„์ „์ด ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

    Python 2.7.10 (default, May 23 2015, 09:44:00) [MSC v.1500 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import jinja2
    >>> jinja2.Template("{{ disks|reject('sameas', '/')|list }}").render(disks=["/", "/mnt/disk0", "/mnt/disk1"])
    u"['/', '/mnt/disk0', '/mnt/disk1']"
    >>> jinja2.__version__
    '2.8'

์˜ค.. sameas ๋Š” is ( 'foo' is 'foo' ๊ฐ€ ์ž‘๋™ํ•  ๊ฒƒ์ด๋ผ๊ณ  ๊ธฐ๋Œ€ํ•  ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค). ๋‹น์‹ ์ด ์›ํ•˜๋Š” equalto ์‚ฌ์šฉํ•˜๋Š” == .

์˜ˆ, ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์ €๋Š” Jinja2์˜ ๊ฐ€์กฑ์ด ์•„๋‹™๋‹ˆ๋‹ค. @ThiefMaster ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์Šฌ๋ž˜์‹œ๊ฐ€ ์‹ค์ œ๋กœ ์˜๋ฏธ ์žˆ๋Š” ์ธ์ฝ”๋”ฉ์ด ๋˜๋Š” ์œ ์ผํ•œ ๋ถ€๋ถ„์€ ์ฟผ๋ฆฌ ๋ฌธ์ž์—ด์— ์žˆ์œผ๋ฉฐ urlencode๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” dict ๊ธฐ๋ฐ˜ ์ธ์ฝ”๋”๊ฐ€ ๊ทธ๋ ‡๊ฒŒ ์ž‘๋™ํ•˜๋Š” ๊ณณ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์Šฌ๋ž˜์‹œ๊ฐ€ ์žˆ์–ด๋„ ์ธ์ฝ”๋”ฉํ•  ํ•„์š”๊ฐ€ ์—†์œผ๋ฏ€๋กœ ์ธ์ฝ”๋”ฉ์„ ๊ฐ•์ œํ•  ์ด์œ ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

์•„๋‹ˆ์š”, ์˜ˆ๋ฅผ ๋“ค์–ด ์‚ฌ์šฉ์ž ์ด๋ฆ„๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ์—๋„ / ๋ฅผ ์ธ์ฝ”๋”ฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
์ด๊ฒƒ์ด JS์— encodeURI __and__ encodeURIComponent ๊ฐ€ ์žˆ๋Š” ์ด์œ ์ž…๋‹ˆ๋‹ค.

๊ทธ๊ฒƒ์€ ์ถฉ๋ถ„ํžˆ ๊ณตํ‰ํ•˜์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” ํ•„์š”ํ•˜์ง€ ์•Š์œผ๋ฉฐ ํฌํ•จ ๋œ ์ž๊ฒฉ ์ฆ๋ช…์€ ์–ด์จŒ๋“  ์‚ฌ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ…œํ”Œ๋ฆฟ ๋‚ด์—์„œ ์ƒ์„ฑ๋  ๊ฐ€๋Šฅ์„ฑ์ด ๋‚ฎ๊ธฐ ๋•Œ๋ฌธ์— ์‹ค์ œ๋กœ ๊ณ ๋ คํ•  ๊ฐ€์น˜๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค.

Ansible์€ Jinja๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ ์‹œ์Šคํ…œ์„ ์„ค์ •ํ•  ๋•Œ ๋ณด์•ˆ ์ž๊ฒฉ ์ฆ๋ช…์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ž…๋‹ˆ๋‹ค. ๋ฐฉ๊ธˆ ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋œ ๋น„๋ฐ€๋ฒˆํ˜ธ์— ์Šฌ๋ž˜์‹œ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋Š”๋ฐ ์ด ์Šฌ๋ž˜์‹œ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค URL์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด urlencode ๋กœ ๋Œ€์ฒด๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. ์ด๋Š” ๋งค์šฐ ๋ถˆํ–‰ํ•œ ์ผ์ž…๋‹ˆ๋‹ค. ํ˜„์žฌ ๋™์ž‘์„ ๊นจ๋Š” ๊ฒƒ์ด ๋ฌธ์ œ๊ฐ€ ๋  ์ˆ˜ ์žˆ์ง€๋งŒ ์Šฌ๋ž˜์‹œ๋ฅผ ์ด์Šค์ผ€์ดํ”„ํ•˜์ง€ ์•Š๋Š” ๋‘ ๋ฒˆ์งธ ํ•„ํ„ฐ๋ฅผ ๋„์ž…ํ•˜์ง€ ์•Š๊ฒ ์Šต๋‹ˆ๊นŒ?

์•ค์„œ๋ธ”์€ ๊ทธ๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Jinja ์ž์ฒด์—๋Š” ๊ทธ๋Ÿฌํ•œ ๋ณ€๊ฒฝ์ด ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ •์˜ ํ•„ํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ๋‚ด์žฅ ํ•„ํ„ฐ๋ฅผ ๊ต์ฒดํ•  ์ˆ˜ ์žˆ์„ ์ •๋„๋กœ ์ถฉ๋ถ„ํžˆ ํ™•์žฅ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

@ThiefMaster Jinja ์ž์ฒด์— ํฌํ•จํ•˜๋Š” ๊ฒƒ์ด ์œ ์šฉํ•œ์ง€ ๊ฒฐ์ •ํ•  ๋•Œ HTML ํ…œํ”Œ๋ฆฟ์„ ๊ตฌ์„ฑํ•˜๋Š” ๊ฒƒ ์ด์™ธ์˜ ์‚ฌ์šฉ ์‚ฌ๋ก€๋Š” ๊ด€๋ จ์ด ์—†์Šต๋‹ˆ๊นŒ? ์˜ˆ๋ฅผ ๋“ค์–ด, Ansible๊ณผ ์œ ์‚ฌํ•œ ๋ชฉ์ ์„ ๊ฐ€์ง„ Saltstack ํ”„๋กœ์ ํŠธ๋„ ํ…œํ”Œ๋ฆฟ์— Jinja๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ ๋™์ผํ•œ ๋ณ€๊ฒฝ์˜ ์ด์ ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@danielkza saltstack ์ด ํ•„ํ„ฐ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์„

@mitsuhiko ์™œ Jinja์— ๋‚ด์žฅ ํ•„ํ„ฐ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๊นŒ? ์—ฌ๋Ÿฌ ์‚ฌ์šฉ ์‚ฌ๋ก€์—์„œ ์œ ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋ผ๊ณ  ์ถ”์ธกํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. URL์—์„œ ์Šฌ๋ž˜์‹œ๋ฅผ ์ด์Šค์ผ€์ดํ”„ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด ๋ฐ”๋žŒ์งํ•œ ๋‘ ๊ฐ€์ง€ ์˜ˆ๋กœ Ansible๊ณผ Salt๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ชจ๋“  ์‚ฌ๋žŒ์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

safe ์ธ์ˆ˜๋ฅผ urlencode ์— ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์€ Python์˜ urllib.url_quote ์ฒ˜๋Ÿผ ๊ธฐ๋ณธ์ ์œผ๋กœ ์Šฌ๋ž˜์‹œ๊ฐ€ ์œ ์ง€๋˜์ง€๋งŒ ์‰ฝ๊ฒŒ ๋ฌด์‹œํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ์‹์œผ๋กœ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

Jinja๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ๋ช‡ ๊ฐ€์ง€ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์•ฝ 95%๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋Š” urlencoding์„ ์œ„ํ•œ ๋‘ ๊ฐ€์ง€ ๋ชจ๋“œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์ „์„ ์ธ์ฝ”๋”ฉํ•˜์—ฌ ์ „์ฒด ์ฟผ๋ฆฌ ๋ฌธ์ž์—ด์„ ์ธ์ฝ”๋”ฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋ฌธ์ž์—ด์˜ urlencode๋ฅผ ํ†ตํ•œ ๊ฒฝ๋กœ์— ์œ ํšจํ•œ ๊ณตํ†ต ์ง‘ํ•ฉ์œผ๋กœ ์ธ์ฝ”๋”ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” utf-8์ด๋‚˜ ๊ทธ ์™ธ์—๋Š” ์•„๋ฌด๊ฒƒ๋„ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์–ด๋””์—์„œ ๋ฉˆ์ถœ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. URL์— ๋„ˆ๋ฌด ๋งŽ์€ ๋ถ€๋ถ„์ด ์žˆ๊ณ  ํ™์ฑ„๊ฐ€ ์žˆ์œผ๋ฉฐ ๋ชจ๋‘ ๊ณ ์œ ํ•œ ๊ผฌ์ž„์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ๊ฑฐ๊ธฐ์— ์žˆ์„ ๋•Œ netloc์šฉ ํ“จ๋‹ˆ์ฝ”๋“œ ์ธ์ฝ”๋”๋„ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

API ํ˜ธ์ถœ์„ ํ†ตํ•ด gitlab ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— ํŒŒ์ผ์„ ๋งŒ๋“ค๋ ค๊ณ  ํ•  ๋•Œ ์ด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. gitlab API๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์Šฌ๋ž˜์‹œ๋ฅผ ์ธ์ฝ”๋”ฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. {{ myvar | urlencode | regex_replace('/','%2F') }}. ํ”Œ๋ ˆ์ด๋ถ ์ž‘์—…์—์„œ Ansible ๋ฐ Jinja2 ํ•„ํ„ฐ๋กœ ์ž‘์—…ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋‚ด๊ฐ€ ์ž‘๋™ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์„ ์น˜๋Š” ์‚ฌ๋žŒ๋“ค์„ ์œ„ํ•œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์–ด๋–ค ๋ฌธ์ž๋ฅผ ๋ฐฑ๋ถ„์œจ๋กœ ์ธ์ฝ”๋”ฉํ•ด์•ผ ํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ์•ฝ๊ฐ„์˜ ๋…ผ์Ÿ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋‚ด์šฉ์€ ํ˜„์žฌ RFC3986์—์„œ ๋‹ค๋ฃจ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. https://tools.ietf.org/html/rfc3986#section -2.2

๋‚ด ์‚ฌ์šฉ ์‚ฌ๋ก€์˜ ๊ฒฝ์šฐ @ahuffman ์ด ํ•ฉ๋ฆฌ์ ์ธ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค.

๋˜ ๋‚˜์™”์œผ๋‹ˆ๊นŒ ๋‹ซ๊ณ  ์‹ถ์–ด์š”. ์ด๊ฒƒ์— ๋Œ€ํ•œ ๋‚˜์˜ ์ฃผ์žฅ์€ ์ด๋ฏธ ์—ฌ๊ธฐ์—์„œ ์ด๋ฏธ ์–ธ๊ธ‰๋˜์—ˆ์ง€๋งŒ GitLab์˜ API์— ๋„์›€์ด ๋˜๋„๋ก ๋‹ค๋ฅธ ํ•„ํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•  ๊ฒƒ์„ ์ œ์•ˆํ•˜๋Š” ํ˜„์žฌ PR์ด ์—ด๋ ค ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค์‹œ ๊ฐ•์กฐํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค(#864).

๋ชจ๋“  ์ข…๋ฅ˜์˜ ํ”„๋ก์‹œ ์„ค์ • ๋’ค์— ๋ฐฐ์น˜๋˜๊ณ  ์ด์— ๋Œ€ํ•ด ์—ด๋ ค ์žˆ๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ GitLab์˜ API๊ฐ€ ์†์ƒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค( ์˜ˆ์ œ ๋ฌธ์ œ ). ๋Œ€์‹  ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•๊ณผ ์‚ฌ๋žŒ๋“ค์ด ํ•˜์ง€ ๋ง์•„์•ผ ํ•˜๋Š” ์ด์œ ๋ฅผ ๋ฌธ์„œํ™”ํ•  ๊ฒƒ์„ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค.

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์˜ ์˜ˆ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

{{ value|urlencode|replace("/", "%2f") }}

์ด๊ฒƒ์€ ์•ฝ๊ฐ„์˜ ์ž…์žฅ์„ ์ทจํ•˜๋Š” ๊ฒƒ์ด์ง€๋งŒ ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์‚ฌ๋žŒ๋“ค์ด ์ด์ „์— ์žˆ์—ˆ๋˜ ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์˜ ์‹ค์ˆ˜๋ฅผ ๋ฐ˜๋ณตํ•˜์ง€ ์•Š๋„๋ก ๊ฒฉ๋ คํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰