Направих ΠΌΠΎΠ΅Ρ‚ΠΎ PyPI Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅ с Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ ΠΈ S3. На Nginx

Π’ Ρ‚Π°Π·ΠΈ статия Π±ΠΈΡ… искал Π΄Π° сподСля ΠΎΠΏΠΈΡ‚Π° си с NJS, JavaScript ΠΈΠ½Ρ‚Π΅Ρ€ΠΏΡ€Π΅Ρ‚Π°Ρ‚ΠΎΡ€ Π·Π° Nginx, Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Π΅Π½ ΠΎΡ‚ Nginx Inc, описвайки основнитС ΠΌΡƒ Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΠΈ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° Ρ€Π΅Π°Π»Π΅Π½ ΠΏΡ€ΠΈΠΌΠ΅Ρ€. NJS Π΅ подмноТСство Π½Π° JavaScript, ΠΊΠΎΠ΅Ρ‚ΠΎ Π²ΠΈ позволява Π΄Π° Ρ€Π°Π·ΡˆΠΈΡ€ΠΈΡ‚Π΅ функционалността Π½Π° Nginx. На Π²ΡŠΠΏΡ€ΠΎΡΠ° Π·Π°Ρ‰ΠΎ собствСн ΠΏΡ€Π΅Π²ΠΎΠ΄Π°Ρ‡??? Π”ΠΌΠΈΡ‚Ρ€ΠΈΠΉ Π’ΠΎΠ»ΠΈΠ½Ρ†Π΅Π² ΠΎΡ‚Π³ΠΎΠ²ΠΎΡ€ΠΈ ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎ. Накратко: NJS Π΅ nginx-way, Π° JavaScript Π΅ ΠΏΠΎ-прогрСсивСн, β€žΡ€ΠΎΠ΄Π΅Π½β€œ ΠΈ Π±Π΅Π· GC, Π·Π° Ρ€Π°Π·Π»ΠΈΠΊΠ° ΠΎΡ‚ Lua.

ΠŸΡ€Π΅Π΄ΠΈ ΠΌΠ½ΠΎΠ³ΠΎ врСмС…

На послСдната ΠΌΠΈ Ρ€Π°Π±ΠΎΡ‚Π° наслСдих gitlab с Ρ€Π΅Π΄ΠΈΡ†Π° ΠΏΡŠΡΡ‚Ρ€ΠΈ CI/CD ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€ΠΈ с docker-compose, dind ΠΈ Π΄Ρ€ΡƒΠ³ΠΈ ΠΈΠ·ΠΊΡƒΡˆΠ΅Π½ΠΈΡ, ΠΊΠΎΠΈΡ‚ΠΎ бяха ΠΏΡ€Π΅Ρ…Π²ΡŠΡ€Π»Π΅Π½ΠΈ към kaniko rails. Π˜Π·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΡΡ‚Π°, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½ΠΈ ΠΏΡ€Π΅Π΄ΠΈ Ρ‚ΠΎΠ²Π° Π² CI, бяха прСмСстСни Π² ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»Π½Π°Ρ‚Π° ΠΈΠΌ Ρ„ΠΎΡ€ΠΌΠ°. Π’Π΅ Ρ€Π°Π±ΠΎΡ‚Π΅Ρ…Π° ΠΏΡ€Π°Π²ΠΈΠ»Π½ΠΎ Π΄ΠΎ дСня, ΠΊΠΎΠ³Π°Ρ‚ΠΎ Π½Π°ΡˆΠΈΡΡ‚ IP адрСс Π½Π° gitlab сС ΠΏΡ€ΠΎΠΌΠ΅Π½ΠΈ ΠΈ CI сС ΠΏΡ€Π΅Π²ΡŠΡ€Π½Π° Π² Ρ‚ΠΈΠΊΠ²Π°. ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΡŠΡ‚ бСшС, Ρ‡Π΅ Π΅Π΄Π½ΠΎ ΠΎΡ‚ Π΄ΠΎΠΊΠ΅Ρ€ изобраТСнията, ΠΊΠΎΠΈΡ‚ΠΎ участваха Π² CI, имашС git, ΠΊΠΎΠΉΡ‚ΠΎ изтСгля Python ΠΌΠΎΠ΄ΡƒΠ»ΠΈ Ρ‡Ρ€Π΅Π· ssh. Π—Π° ssh Π²ΠΈ трябва частСн ΠΊΠ»ΡŽΡ‡ ΠΈ... бСшС Π² ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ Π·Π°Π΅Π΄Π½ΠΎ с unknown_hosts. И всСки CI сС ΠΏΡ€ΠΎΠ²Π°Π»ΠΈ с Π³Ρ€Π΅ΡˆΠΊΠ° ΠΏΡ€ΠΈ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Π½Π° ΠΊΠ»ΡŽΡ‡ ΠΏΠΎΡ€Π°Π΄ΠΈ Π½Π΅ΡΡŠΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΠΈΠ΅ ΠΌΠ΅ΠΆΠ΄Ρƒ рСалния IP ΠΈ Ρ‚ΠΎΠ·ΠΈ, посочСн Π² unknown_hosts. Ново ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ бСшС Π±ΡŠΡ€Π·ΠΎ сглобСно ΠΎΡ‚ ΡΡŠΡ‰Π΅ΡΡ‚Π²ΡƒΠ²Π°Ρ‰ΠΈΡ‚Π΅ Dockfiles ΠΈ опцията бСшС Π΄ΠΎΠ±Π°Π²Π΅Π½Π° StrictHostKeyChecking no. Но Π»ΠΎΡˆΠΈΡΡ‚ вкус остана ΠΈ имашС ΠΆΠ΅Π»Π°Π½ΠΈΠ΅ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈΡ‚Π΅ Π΄Π° сС прСмСстят Π² частно PyPI Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅. Π”ΠΎΠΏΡŠΠ»Π½ΠΈΡ‚Π΅Π»Π΅Π½ бонус, слСд ΠΏΡ€Π΅ΠΌΠΈΠ½Π°Π²Π°Π½Π΅ към частСн PyPI, бСшС ΠΏΠΎ-опростСн ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€ ΠΈ Π½ΠΎΡ€ΠΌΠ°Π»Π½ΠΎ описаниС Π½Π° requirements.txt

Π˜Π·Π±ΠΎΡ€ΡŠΡ‚ Π΅ Π½Π°ΠΏΡ€Π°Π²Π΅Π½, господа!

ИзпълнявамС всичко Π² ΠΎΠ±Π»Π°Ρ†ΠΈΡ‚Π΅ ΠΈ Kubernetes ΠΈ Π² ΠΊΡ€Π°ΠΉΠ½Π° смСтка искахмС Π΄Π° ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ ΠΌΠ°Π»ΠΊΠ° услуга, която бСшС ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ Π±Π΅Π· ΡΡŠΡΡ‚ΠΎΡΠ½ΠΈΠ΅ с външно Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅. Π•, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ S3, бСшС Π΄Π°Π΄Π΅Π½ ΠΏΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚ Π½Π° Π½Π΅Π³ΠΎ. И, Π°ΠΊΠΎ Π΅ възмоТно, с удостовСряванС Π² gitlab (ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Π³ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚Π΅ сами, Π°ΠΊΠΎ Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ).

Π‘ΡŠΡ€Π·ΠΎ Ρ‚ΡŠΡ€ΡΠ΅Π½Π΅ Π΄Π°Π΄Π΅ няколко Ρ€Π΅Π·ΡƒΠ»Ρ‚Π°Ρ‚Π°: s3pypi, pypicloud ΠΈ опция с β€žΡ€ΡŠΡ‡Π½ΠΎβ€œ създаванС Π½Π° html Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅ Π·Π° ряпа. ΠŸΠΎΡΠ»Π΅Π΄Π½Π°Ρ‚Π° опция ΠΈΠ·Ρ‡Π΅Π·Π½Π° ΠΎΡ‚ само сСбС си.

s3pypi: Π’ΠΎΠ²Π° Π΅ cli Π·Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° S3 хостинг. ΠšΠ°Ρ‡Π²Π°ΠΌΠ΅ Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅Ρ‚Π΅, Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°ΠΌΠ΅ html ΠΈ Π³ΠΎ ΠΊΠ°Ρ‡Π²Π°ΠΌΠ΅ Π² ΡΡŠΡ‰Π°Ρ‚Π° ΠΊΠΎΡ„Π°. ΠŸΠΎΠ΄Ρ…ΠΎΠ΄ΡΡ‰ Π·Π° домашна ΡƒΠΏΠΎΡ‚Ρ€Π΅Π±Π°.

pypicloud: ИзглСТдашС ΠΊΠ°Ρ‚ΠΎ интСрСсСн ΠΏΡ€ΠΎΠ΅ΠΊΡ‚, Π½ΠΎ слСд ΠΊΠ°Ρ‚ΠΎ ΠΏΡ€ΠΎΡ‡Π΅Ρ‚ΠΎΡ… докумСнтацията бях Ρ€Π°Π·ΠΎΡ‡Π°Ρ€ΠΎΠ²Π°Π½. Π’ΡŠΠΏΡ€Π΅ΠΊΠΈ Π΄ΠΎΠ±Ρ€Π°Ρ‚Π° докумСнтация ΠΈ Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚Ρ‚Π° Π·Π° Ρ€Π°Π·ΡˆΠΈΡ€ΡΠ²Π°Π½Π΅ спорСд Π²Π°ΡˆΠΈΡ‚Π΅ Π½ΡƒΠΆΠ΄ΠΈ, Π² дСйствитСлност сС ΠΎΠΊΠ°Π·Π° излишСн ΠΈ Ρ‚Ρ€ΡƒΠ΄Π΅Π½ Π·Π° ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€Π°Π½Π΅. ΠšΠΎΡ€ΠΈΠ³ΠΈΡ€Π°Π½Π΅Ρ‚ΠΎ Π½Π° ΠΊΠΎΠ΄Π°, Π·Π° Π΄Π° отговаря Π½Π° Π²Π°ΡˆΠΈΡ‚Π΅ Π·Π°Π΄Π°Ρ‡ΠΈ, спорСд Ρ‚ΠΎΠ³Π°Π²Π°ΡˆΠ½ΠΈΡ‚Π΅ ΠΎΡ†Π΅Π½ΠΊΠΈ, Π±ΠΈ ΠΎΡ‚Π½Π΅Π»ΠΎ 3-5 Π΄Π½ΠΈ. Услугата сС Π½ΡƒΠΆΠ΄Π°Π΅ ΠΈ ΠΎΡ‚ Π±Π°Π·Π° Π΄Π°Π½Π½ΠΈ. ΠžΡΡ‚Π°Π²ΠΈΡ…ΠΌΠ΅ Π³ΠΎ, Π² случай Ρ‡Π΅ Π½Π΅ Π½Π°ΠΌΠ΅Ρ€ΠΈΠΌ Π½ΠΈΡ‰ΠΎ Π΄Ρ€ΡƒΠ³ΠΎ.

По-Π·Π°Π΄ΡŠΠ»Π±ΠΎΡ‡Π΅Π½ΠΎ Ρ‚ΡŠΡ€ΡΠ΅Π½Π΅ Π΄Π°Π΄Π΅ ΠΌΠΎΠ΄ΡƒΠ» Π·Π° Nginx, ngx_aws_auth. Π Π΅Π·ΡƒΠ»Ρ‚Π°Ρ‚ΡŠΡ‚ ΠΎΡ‚ Π½Π΅Π³ΠΎΠ²ΠΎΡ‚ΠΎ тСстванС бСшС XML, ΠΏΠΎΠΊΠ°Π·Π°Π½ Π² Π±Ρ€Π°ΡƒΠ·ΡŠΡ€Π°, ΠΊΠΎΠΉΡ‚ΠΎ показвашС ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Π½ΠΈΠ΅Ρ‚ΠΎ Π½Π° ΠΊΠΎΡ„Π°Ρ‚Π° S3. ΠŸΠΎΡΠ»Π΅Π΄Π½ΠΈΡΡ‚ Π°Π½Π³Π°ΠΆΠΈΠΌΠ΅Π½Ρ‚ ΠΏΠΎ Π²Ρ€Π΅ΠΌΠ΅ Π½Π° Ρ‚ΡŠΡ€ΡΠ΅Π½Π΅Ρ‚ΠΎ бСшС ΠΏΡ€Π΅Π΄ΠΈ Π³ΠΎΠ΄ΠΈΠ½Π°. Π₯Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅Ρ‚ΠΎ изглСТдашС изоставСно.

ΠšΠ°Ρ‚ΠΎ ΠΎΡ‚ΠΈΠ΄Π΅Ρ‚Π΅ Π΄ΠΎ ΠΈΠ·Ρ‚ΠΎΡ‡Π½ΠΈΠΊΠ° ΠΈ ΠΏΡ€ΠΎΡ‡Π΅Ρ‚Π΅Ρ‚Π΅ Π Π•Π -503 Π Π°Π·Π±Ρ€Π°Ρ…, Ρ‡Π΅ XML ΠΌΠΎΠΆΠ΅ Π΄Π° сС ΠΊΠΎΠ½Π²Π΅Ρ€Ρ‚ΠΈΡ€Π° Π² HTML Π² Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΠ΅ ΠΈ Π΄Π° сС Π΄Π°Π΄Π΅ Π½Π° pip. Π‘Π»Π΅Π΄ ΠΊΠ°Ρ‚ΠΎ ΠΏΠΎΡ‚ΡŠΡ€ΡΠΈΡ… Π² Google ΠΌΠ°Π»ΠΊΠΎ ΠΏΠΎΠ²Π΅Ρ‡Π΅ Π·Π° Nginx ΠΈ S3, ΠΏΠΎΠΏΠ°Π΄Π½Π°Ρ… Π½Π° ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π·Π° удостовСряванС Π² S3, написан Π½Π° JS Π·Π° Nginx. Π’Π°ΠΊΠ° сС Π·Π°ΠΏΠΎΠ·Π½Π°Ρ… с NJS.

Π’Π·Π΅ΠΌΠ°ΠΉΠΊΠΈ Ρ‚ΠΎΠ·ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΠΊΠ°Ρ‚ΠΎ основа, Π΅Π΄ΠΈΠ½ час ΠΏΠΎ-късно видях Π² Π±Ρ€Π°ΡƒΠ·ΡŠΡ€Π° си ΡΡŠΡ‰ΠΈΡ XML ΠΊΠ°Ρ‚ΠΎ ΠΏΡ€ΠΈ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° ΠΌΠΎΠ΄ΡƒΠ»Π° ngx_aws_auth, Π½ΠΎ всичко Π²Π΅Ρ‡Π΅ бСшС написано Π² JS.

Много ΠΌΠΈ харСса Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ Π½Π° nginx. ΠŸΡŠΡ€Π²ΠΎ, Π΄ΠΎΠ±Ρ€Π° докумСнтация ΠΈ ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΈ, Π²Ρ‚ΠΎΡ€ΠΎ, ΠΏΠΎΠ»ΡƒΡ‡Π°Π²Π°ΠΌΠ΅ всички прСдимства Π½Π° Nginx Π·Π° Ρ€Π°Π±ΠΎΡ‚Π° с Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅ (извън кутията), Ρ‚Ρ€Π΅Ρ‚ΠΎ, всСки, ΠΊΠΎΠΉΡ‚ΠΎ Π·Π½Π°Π΅ ΠΊΠ°ΠΊ Π΄Π° пишС ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ Π·Π° Nginx, Ρ‰Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° Ρ€Π°Π·Π±Π΅Ρ€Π΅ ΠΊΠ°ΠΊΠ²ΠΎ Π΅ ΠΊΠ°ΠΊΠ²ΠΎ. ΠœΠΈΠ½ΠΈΠΌΠ°Π»ΠΈΠ·ΠΌΡŠΡ‚ ΡΡŠΡ‰ΠΎ Π΅ плюс Π·Π° ΠΌΠ΅Π½, Π² сравнСниС с Python ΠΈΠ»ΠΈ Go (Π°ΠΊΠΎ Π΅ написан ΠΎΡ‚ Π½ΡƒΠ»Π°Ρ‚Π°), Π΄Π° Π½Π΅ Π³ΠΎΠ²ΠΎΡ€ΠΈΠΌ Π·Π° nexus.

TL;DR Π‘Π»Π΅Π΄ 2 Π΄Π½ΠΈ тСстовата вСрсия Π½Π° PyPi Π²Π΅Ρ‡Π΅ бСшС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π° Π² CI.

Как дСйства тя?

ΠœΠΎΠ΄ΡƒΠ»ΡŠΡ‚ сС Π·Π°Ρ€Π΅ΠΆΠ΄Π° Π² Nginx ngx_http_js_module, Π²ΠΊΠ»ΡŽΡ‡Π΅Π½ Π² официалния Π΄ΠΎΠΊΠ΅Ρ€ ΠΎΠ±Ρ€Π°Π·. НиС ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€Π°ΠΌΠ΅ нашия скрипт с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΈΠ²Π°Ρ‚Π° js_importкъм конфигурацията Π½Π° Nginx. Ѐункцията сС ΠΈΠ·Π²ΠΈΠΊΠ²Π° Ρ‡Ρ€Π΅Π· Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΈΠ²Π° js_content. Π”ΠΈΡ€Π΅ΠΊΡ‚ΠΈΠ²Π°Ρ‚Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Π·Π° Π·Π°Π΄Π°Π²Π°Π½Π΅ Π½Π° ΠΏΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ js_set, ΠΊΠΎΠΉΡ‚ΠΎ ΠΏΡ€ΠΈΠ΅ΠΌΠ° ΠΊΠ°Ρ‚ΠΎ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ само функцията, описана Π² скрипта. Но ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° изпълнявамС подзаявки Π² NJS само с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° Nginx, Π° Π½Π΅ с XMLHttpRequest. Π—Π° Π΄Π° Π½Π°ΠΏΡ€Π°Π²ΠΈΡ‚Π΅ Ρ‚ΠΎΠ²Π°, ΡΡŠΠΎΡ‚Π²Π΅Ρ‚Π½ΠΎΡ‚ΠΎ мСстополоТСниС трябва Π΄Π° бъдС Π΄ΠΎΠ±Π°Π²Π΅Π½ΠΎ към конфигурацията Π½Π° Nginx. И ΡΠΊΡ€ΠΈΠΏΡ‚ΡŠΡ‚ трябва Π΄Π° опишС подзаявка към Ρ‚ΠΎΠ²Π° мСстополоТСниС. Π—Π° Π΄Π° ΠΈΠΌΠ°Ρ‚Π΅ Π΄ΠΎΡΡ‚ΡŠΠΏ Π΄ΠΎ функция ΠΎΡ‚ конфигурацията Π½Π° Nginx, ΠΈΠΌΠ΅Ρ‚ΠΎ Π½Π° функцията трябва Π΄Π° бъдС Скспортирано Π² самия скрипт export default.

nginx.conf

load_module modules/ngx_http_js_module.so;
http {
  js_import   imported_name  from script.js;

server {
  listen 8080;
  ...
  location = /sub-query {
    internal;

    proxy_pass http://upstream;
  }

  location / {
    js_content imported_name.request;
  }
}

script.js

function request(r) {
  function call_back(resp) {
    // handler's code
    r.return(resp.status, resp.responseBody);
  }

  r.subrequest('/sub-query', { method: r.method }, call_back);
}

export default {request}

ΠŸΡ€ΠΈ поискванС Π² Π±Ρ€Π°ΡƒΠ·ΡŠΡ€Π° http://localhost:8080/ Π²Π»ΠΈΠ·Π°ΠΌΠ΅ location /Π² която Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΈΠ²Π°Ρ‚Π° js_content ΠΈΠ·Π²ΠΈΠΊΠ²Π° функция request описани Π² нашия скрипт script.js. ΠžΡ‚ своя страна във функцията request сС ΠΏΡ€Π°Π²ΠΈ подзаявка към location = /sub-query, с ΠΌΠ΅Ρ‚ΠΎΠ΄ (Π² тСкущия ΠΏΡ€ΠΈΠΌΠ΅Ρ€ GET), ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ ΠΎΡ‚ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π° (r), ΠΏΡ€Π΅Π΄Π°Π²Π°Π½ ΠΈΠΌΠΏΠ»ΠΈΡ†ΠΈΡ‚Π½ΠΎ, ΠΊΠΎΠ³Π°Ρ‚ΠΎ Ρ‚Π°Π·ΠΈ функция Π΅ ΠΈΠ·Π²ΠΈΠΊΠ°Π½Π°. ΠžΡ‚Π³ΠΎΠ²ΠΎΡ€ΡŠΡ‚ Π½Π° подзаявката Ρ‰Π΅ бъдС ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π΅Π½ във функцията call_back.

ΠžΠΏΠΈΡ‚Π²Π°ΠΌ S3

Π—Π° Π΄Π° Π½Π°ΠΏΡ€Π°Π²ΠΈΠΌ заявка Π·Π° частно S3 Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅, ΠΈΠΌΠ°ΠΌΠ΅ Π½ΡƒΠΆΠ΄Π° ΠΎΡ‚:

ACCESS_KEY

SECRET_KEY

S3_BUCKET

ΠžΡ‚ използвания http ΠΌΠ΅Ρ‚ΠΎΠ΄, Ρ‚Π΅ΠΊΡƒΡ‰Π°Ρ‚Π° Π΄Π°Ρ‚Π°/час, S3_NAME ΠΈ URI сС Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π° ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ Ρ‚ΠΈΠΏ Π½ΠΈΠ·, ΠΊΠΎΠΉΡ‚ΠΎ сС подписва (HMAC_SHA1) с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° SECRET_KEY. Π‘Π»Π΅Π΄Π²Π° Ρ€Π΅Π΄ ΠΊΠ°Ρ‚ΠΎ AWS $ACCESS_KEY:$HASH, ΠΌΠΎΠΆΠ΅ Π΄Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Π² Π·Π°Π³Π»Π°Π²ΠΊΠ°Ρ‚Π° Π·Π° оторизация. Π‘ΡŠΡ‰Π°Ρ‚Π° Π΄Π°Ρ‚Π°/час, която Π΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π° Π·Π° Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°Π½Π΅ Π½Π° Π½ΠΈΠ·Π° Π² ΠΏΡ€Π΅Π΄ΠΈΡˆΠ½Π°Ρ‚Π° ΡΡ‚ΡŠΠΏΠΊΠ°, трябва Π΄Π° сС Π΄ΠΎΠ±Π°Π²ΠΈ към Π·Π°Π³Π»Π°Π²ΠΊΠ°Ρ‚Π° X-amz-date. Π’ ΠΊΠΎΠ΄Π° ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π° Ρ‚Π°ΠΊΠ°:

nginx.conf

load_module modules/ngx_http_js_module.so;
http {
  js_import   s3      from     s3.js;

  js_set      $s3_datetime     s3.date_now;
  js_set      $s3_auth         s3.s3_sign;

server {
  listen 8080;
  ...
  location ~* /s3-query/(?<s3_path>.*) {
    internal;

    proxy_set_header    X-amz-date     $s3_datetime;
    proxy_set_header    Authorization  $s3_auth;

    proxy_pass          $s3_endpoint/$s3_path;
  }

  location ~ "^/(?<prefix>[w-]*)[/]?(?<postfix>[w-.]*)$" {
    js_content s3.request;
  }
}

s3.js(ΠŸΡ€ΠΈΠΌΠ΅Ρ€ Π·Π° ΡƒΠΏΡŠΠ»Π½ΠΎΠΌΠΎΡ‰Π°Π²Π°Π½Π΅ Π½Π° AWS Sign v2, ΠΏΡ€ΠΎΠΌΠ΅Π½Π΅Π½ Π½Π° остарял статус)

var crypt = require('crypto');

var s3_bucket = process.env.S3_BUCKET;
var s3_access_key = process.env.S3_ACCESS_KEY;
var s3_secret_key = process.env.S3_SECRET_KEY;
var _datetime = new Date().toISOString().replace(/[:-]|.d{3}/g, '');

function date_now() {
  return _datetime
}

function s3_sign(r) {
  var s2s = r.method + 'nnnn';

  s2s += `x-amz-date:${date_now()}n`;
  s2s += '/' + s3_bucket;
  s2s += r.uri.endsWith('/') ? '/' : r.variables.s3_path;

  return `AWS ${s3_access_key}:${crypt.createHmac('sha1', s3_secret_key).update(s2s).digest('base64')}`;
}

function request(r) {
  var v = r.variables;

  function call_back(resp) {
    r.return(resp.status, resp.responseBody);
  }

  var _subrequest_uri = r.uri;
  if (r.uri === '/') {
    // root
    _subrequest_uri = '/?delimiter=/';

  } else if (v.prefix !== '' && v.postfix === '') {
    // directory
    var slash = v.prefix.endsWith('/') ? '' : '/';
    _subrequest_uri = '/?prefix=' + v.prefix + slash;
  }

  r.subrequest(`/s3-query${_subrequest_uri}`, { method: r.method }, call_back);
}

export default {request, s3_sign, date_now}

Малко обяснСниС Π·Π° _subrequest_uri: Ρ‚ΠΎΠ²Π° Π΅ ΠΏΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²Π°, която Π² зависимост ΠΎΡ‚ ΠΏΡŠΡ€Π²ΠΎΠ½Π°Ρ‡Π°Π»Π½ΠΈΡ uri Ρ„ΠΎΡ€ΠΌΠΈΡ€Π° заявка към S3. Ако трябва Π΄Π° ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚Π΅ ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Π½ΠΈΠ΅Ρ‚ΠΎ Π½Π° β€žrootβ€œ, Ρ‚ΠΎΠ³Π°Π²Π° трябва Π΄Π° ΡΡŠΠ·Π΄Π°Π΄Π΅Ρ‚Π΅ uri заявка, посочваща раздСлитСля delimiter, ΠΊΠΎΠΉΡ‚ΠΎ Ρ‰Π΅ Π²ΡŠΡ€Π½Π΅ списък Π½Π° всички CommonPrefixes xml Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ΠΈ, ΡΡŠΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²Π°Ρ‰ΠΈ Π½Π° Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠΈ (Π² случая Π½Π° PyPI, списък Π½Π° всички ΠΏΠ°ΠΊΠ΅Ρ‚ΠΈ). Ако трябва Π΄Π° ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚Π΅ списък със ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Π½ΠΈΠ΅Ρ‚ΠΎ Π² ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Π° дирСктория (списък Π½Π° всички вСрсии Π½Π° ΠΏΠ°ΠΊΠ΅Ρ‚), Ρ‚ΠΎΠ³Π°Π²Π° uri заявката трябва Π΄Π° ΡΡŠΠ΄ΡŠΡ€ΠΆΠ° прСфиксно ΠΏΠΎΠ»Π΅ с ΠΈΠΌΠ΅Ρ‚ΠΎ Π½Π° дирСкторията (ΠΏΠ°ΠΊΠ΅Ρ‚Π°), Π·Π°Π΄ΡŠΠ»ΠΆΠΈΡ‚Π΅Π»Π½ΠΎ Π·Π°Π²ΡŠΡ€ΡˆΠ²Π°Ρ‰ΠΎ с Π½Π°ΠΊΠ»ΠΎΠ½Π΅Π½Π° Ρ‡Π΅Ρ€Ρ‚Π° /. Π’ ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π΅Π½ случай са възмоТни ΡΠ±Π»ΡŠΡΡŠΡ†ΠΈ ΠΏΡ€ΠΈ исканС Π½Π° ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Π½ΠΈΠ΅Ρ‚ΠΎ Π½Π° дирСктория, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€. Има Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠΈ aiohttp-request ΠΈ aiohttp-requests ΠΈ Π°ΠΊΠΎ заявката посочва /?prefix=aiohttp-request, Ρ‚ΠΎΠ³Π°Π²Π° ΠΎΡ‚Π³ΠΎΠ²ΠΎΡ€ΡŠΡ‚ Ρ‰Π΅ ΡΡŠΠ΄ΡŠΡ€ΠΆΠ° ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Π½ΠΈΠ΅Ρ‚ΠΎ Π½Π° Π΄Π²Π΅Ρ‚Π΅ Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠΈ. Ако ΠΈΠΌΠ° Π½Π°ΠΊΠ»ΠΎΠ½Π΅Π½Π° Ρ‡Π΅Ρ€Ρ‚Π° Π² края, /?prefix=aiohttp-request/, Ρ‚ΠΎΠ³Π°Π²Π° ΠΎΡ‚Π³ΠΎΠ²ΠΎΡ€ΡŠΡ‚ Ρ‰Π΅ ΡΡŠΠ΄ΡŠΡ€ΠΆΠ° само Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠ°Ρ‚Π° дирСктория. И Π°ΠΊΠΎ поискамС Ρ„Π°ΠΉΠ», Ρ‚ΠΎΠ³Π°Π²Π° получСният uri Π½Π΅ трябва Π΄Π° сС Ρ€Π°Π·Π»ΠΈΡ‡Π°Π²Π° ΠΎΡ‚ оригиналния.

Π—Π°ΠΏΠ°Π·Π΅Ρ‚Π΅ ΠΈ рСстартирайтС Nginx. Π’ Π±Ρ€Π°ΡƒΠ·ΡŠΡ€Π° въвСТдамС адрСса Π½Π° нашия Nginx, Ρ€Π΅Π·ΡƒΠ»Ρ‚Π°Ρ‚ΡŠΡ‚ ΠΎΡ‚ заявката Ρ‰Π΅ бъдС XML, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€:

Бписък с Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠΈ

<?xml version="1.0" encoding="UTF-8"?>
<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  <Name>myback-space</Name>
  <Prefix></Prefix>
  <Marker></Marker>
  <MaxKeys>10000</MaxKeys>
  <Delimiter>/</Delimiter>
  <IsTruncated>false</IsTruncated>
  <CommonPrefixes>
    <Prefix>new/</Prefix>
  </CommonPrefixes>
  <CommonPrefixes>
    <Prefix>old/</Prefix>
  </CommonPrefixes>
</ListBucketResult>

ΠžΡ‚ списъка с Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠΈ Ρ‰Π΅ Π²ΠΈ трябват само Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ΠΈΡ‚Π΅ CommonPrefixes.

Добавяйки дирСкторията, ΠΎΡ‚ която сС Π½ΡƒΠΆΠ΄Π°Π΅ΠΌ, към нашия адрСс Π² Π±Ρ€Π°ΡƒΠ·ΡŠΡ€Π°, Π½ΠΈΠ΅ ΡΡŠΡ‰ΠΎ Ρ‰Π΅ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ Π½Π΅ΠΉΠ½ΠΎΡ‚ΠΎ ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Π½ΠΈΠ΅ Π² XML Ρ„ΠΎΡ€ΠΌΠ°Ρ‚:

Бписък с Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅ Π² дирСктория

<?xml version="1.0" encoding="UTF-8"?>
<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  <Name> myback-space</Name>
  <Prefix>old/</Prefix>
  <Marker></Marker>
  <MaxKeys>10000</MaxKeys>
  <Delimiter></Delimiter>
  <IsTruncated>false</IsTruncated>
  <Contents>
    <Key>old/giphy.mp4</Key>
    <LastModified>2020-08-21T20:27:46.000Z</LastModified>
    <ETag>&#34;00000000000000000000000000000000-1&#34;</ETag>
    <Size>1350084</Size>
    <Owner>
      <ID>02d6176db174dc93cb1b899f7c6078f08654445fe8cf1b6ce98d8855f66bdbf4</ID>
      <DisplayName></DisplayName>
    </Owner>
    <StorageClass>STANDARD</StorageClass>
  </Contents>
  <Contents>
    <Key>old/hsd-k8s.jpg</Key>
    <LastModified>2020-08-31T16:40:01.000Z</LastModified>
    <ETag>&#34;b2d76df4aeb4493c5456366748218093&#34;</ETag>
    <Size>93183</Size>
    <Owner>
      <ID>02d6176db174dc93cb1b899f7c6078f08654445fe8cf1b6ce98d8855f66bdbf4</ID>
      <DisplayName></DisplayName>
    </Owner>
    <StorageClass>STANDARD</StorageClass>
  </Contents>
</ListBucketResult>

ΠžΡ‚ списъка с Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅ Ρ‰Π΅ Π²Π·Π΅ΠΌΠ΅ΠΌ само Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ΠΈ Key.

Всичко, ΠΊΠΎΠ΅Ρ‚ΠΎ остава, Π΅ Π΄Π° Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€Π°Ρ‚Π΅ получСния XML ΠΈ Π΄Π° Π³ΠΎ ΠΈΠ·ΠΏΡ€Π°Ρ‚ΠΈΡ‚Π΅ ΠΊΠ°Ρ‚ΠΎ HTML, ΠΊΠ°Ρ‚ΠΎ ΠΏΡŠΡ€Π²ΠΎ Π·Π°ΠΌΠ΅Π½ΠΈΡ‚Π΅ Π·Π°Π³Π»Π°Π²ΠΊΠ°Ρ‚Π° Content-Type с text/html.

function request(r) {
  var v = r.variables;

  function call_back(resp) {
    var body = resp.responseBody;

    if (r.method !== 'PUT' && resp.status < 400 && v.postfix === '') {
      r.headersOut['Content-Type'] = "text/html; charset=utf-8";
      body = toHTML(body);
    }

    r.return(resp.status, body);
  }
  
  var _subrequest_uri = r.uri;
  ...
}

function toHTML(xml_str) {
  var keysMap = {
    'CommonPrefixes': 'Prefix',
    'Contents': 'Key',
  };

  var pattern = `<k>(?<v>.*?)</k>`;
  var out = [];

  for(var group_key in keysMap) {
    var reS;
    var reGroup = new RegExp(pattern.replace(/k/g, group_key), 'g');

    while(reS = reGroup.exec(xml_str)) {
      var data = new RegExp(pattern.replace(/k/g, keysMap[group_key]), 'g');
      var reValue = data.exec(reS);
      var a_text = '';

      if (group_key === 'CommonPrefixes') {
        a_text = reValue.groups.v.replace(///g, '');
      } else {
        a_text = reValue.groups.v.split('/').slice(-1);
      }

      out.push(`<a href="/bg/${reValue.groups.v}">${a_text}</a>`);
    }
  }

  return '<html><body>n' + out.join('</br>n') + 'n</html></body>'
}

ΠžΠΏΠΈΡ‚Π²Π°ΠΌ PyPI

ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ²Π°ΠΌΠ΅ Π΄Π°Π»ΠΈ Π½ΠΈΡ‰ΠΎ Π½Π΅ сС счупи никъдС Π½Π° ΠΏΠ°ΠΊΠ΅Ρ‚ΠΈ, Π·Π° ΠΊΠΎΠΈΡ‚ΠΎ Π΅ извСстно, Ρ‡Π΅ работят.

# Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ для тСстов Π½ΠΎΠ²ΠΎΠ΅ ΠΎΠΊΡ€ΡƒΠΆΠ΅Π½ΠΈΠ΅
python3 -m venv venv
. ./venv/bin/activate

# Π‘ΠΊΠ°Ρ‡ΠΈΠ²Π°Π΅ΠΌ Ρ€Π°Π±ΠΎΡ‡ΠΈΠ΅ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹.
pip download aiohttp

# Π—Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌ Π² ΠΏΡ€ΠΈΠ²Π°Ρ‚Π½ΡƒΡŽ Ρ€Π΅ΠΏΡƒ
for wheel in *.whl; do curl -T $wheel http://localhost:8080/${wheel%%-*}/$wheel; done

rm -f *.whl

# УстанавливаСм ΠΈΠ· ΠΏΡ€ΠΈΠ²Π°Ρ‚Π½ΠΎΠΉ Ρ€Π΅ΠΏΡ‹
pip install aiohttp -i http://localhost:8080

ΠŸΠΎΠ²Ρ‚Π°Ρ€ΡΠΌΠ΅ с Π½Π°ΡˆΠΈΡ‚Π΅ Π»ΠΈΠ±ΠΈ.

# Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ для тСстов Π½ΠΎΠ²ΠΎΠ΅ ΠΎΠΊΡ€ΡƒΠΆΠ΅Π½ΠΈΠ΅
python3 -m venv venv
. ./venv/bin/activate

pip install setuptools wheel
python setup.py bdist_wheel
for wheel in dist/*.whl; do curl -T $wheel http://localhost:8080/${wheel%%-*}/$wheel; done

pip install our_pkg --extra-index-url http://localhost:8080

Π’ CI ΡΡŠΠ·Π΄Π°Π²Π°Π½Π΅Ρ‚ΠΎ ΠΈ Π·Π°Ρ€Π΅ΠΆΠ΄Π°Π½Π΅Ρ‚ΠΎ Π½Π° ΠΏΠ°ΠΊΠ΅Ρ‚ ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π° Ρ‚Π°ΠΊΠ°:

pip install setuptools wheel
python setup.py bdist_wheel

curl -sSfT dist/*.whl -u "gitlab-ci-token:${CI_JOB_TOKEN}" "https://pypi.our-domain.com/${CI_PROJECT_NAME}"

Π·Π°Π²Π΅Ρ€ΠΊΠ°

Π’ Gitlab Π΅ възмоТно Π΄Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° JWT Π·Π° удостовСряванС/ΡƒΠΏΡŠΠ»Π½ΠΎΠΌΠΎΡ‰Π°Π²Π°Π½Π΅ Π½Π° външни услуги. Използвайки Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΈΠ²Π°Ρ‚Π° auth_request Π² Nginx, Ρ‰Π΅ прСнасочим Π΄Π°Π½Π½ΠΈΡ‚Π΅ Π·Π° удостовСряванС към подзаявка, ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Ρ‰Π° ΠΈΠ·Π²ΠΈΠΊΠ²Π°Π½Π΅ Π½Π° функция Π² скрипта. Π‘ΠΊΡ€ΠΈΠΏΡ‚ΡŠΡ‚ Ρ‰Π΅ Π½Π°ΠΏΡ€Π°Π²ΠΈ Π΄Ρ€ΡƒΠ³Π° подзаявка към URL адрСса Π½Π° Gitlab ΠΈ Π°ΠΊΠΎ Π΄Π°Π½Π½ΠΈΡ‚Π΅ Π·Π° удостовСряванС са посочСни ΠΏΡ€Π°Π²ΠΈΠ»Π½ΠΎ, Ρ‚ΠΎΠ³Π°Π²Π° Gitlab Ρ‰Π΅ Π²ΡŠΡ€Π½Π΅ ΠΊΠΎΠ΄ 200 ΠΈ ΠΊΠ°Ρ‡Π²Π°Π½Π΅Ρ‚ΠΎ/изтСглянСто Π½Π° ΠΏΠ°ΠΊΠ΅Ρ‚Π° Ρ‰Π΅ бъдС Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΎ. Π—Π°Ρ‰ΠΎ Π½Π΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ Π΅Π΄Π½Π° подзаявка ΠΈ Π½Π΅Π·Π°Π±Π°Π²Π½ΠΎ ΠΈΠ·ΠΏΡ€Π°Ρ‚ΠΈΡ‚Π΅ Π΄Π°Π½Π½ΠΈΡ‚Π΅ Π½Π° Gitlab? Π—Π°Ρ‰ΠΎΡ‚ΠΎ Ρ‚ΠΎΠ³Π°Π²Π° Ρ‰Π΅ трябва Π΄Π° Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€Π°ΠΌΠ΅ конфигурационния Ρ„Π°ΠΉΠ» Π½Π° Nginx всСки ΠΏΡŠΡ‚, ΠΊΠΎΠ³Π°Ρ‚ΠΎ ΠΏΡ€Π°Π²ΠΈΠΌ ΠΏΡ€ΠΎΠΌΠ΅Π½ΠΈ Π² оторизацията, Π° Ρ‚ΠΎΠ²Π° Π΅ доста досадна Π·Π°Π΄Π°Ρ‡Π°. ОсвСн Ρ‚ΠΎΠ²Π°, Π°ΠΊΠΎ Kubernetes ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° ΠΏΠΎΠ»ΠΈΡ‚ΠΈΠΊΠ° Π·Π° основна Ρ„Π°ΠΉΠ»ΠΎΠ²Π° систСма само Π·Π° Ρ‡Π΅Ρ‚Π΅Π½Π΅, Ρ‚ΠΎΠ²Π° добавя ΠΎΡ‰Π΅ ΠΏΠΎΠ²Π΅Ρ‡Π΅ слоТност ΠΏΡ€ΠΈ замяната Π½Π° nginx.conf Ρ‡Ρ€Π΅Π· configmap. И става Π°Π±ΡΠΎΠ»ΡŽΡ‚Π½ΠΎ нСвъзмоТно Π΄Π° ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€Π°Ρ‚Π΅ Nginx Ρ‡Ρ€Π΅Π· configmap, ΠΊΠ°Ρ‚ΠΎ Π΅Π΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ с Ρ‚ΠΎΠ²Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ ΠΏΠΎΠ»ΠΈΡ‚ΠΈΠΊΠΈ, забраняващи ΡΠ²ΡŠΡ€Π·Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° Ρ‚ΠΎΠΌΠΎΠ²Π΅ (pvc) ΠΈ root Ρ„Π°ΠΉΠ»ΠΎΠ²Π° систСма само Π·Π° Ρ‡Π΅Ρ‚Π΅Π½Π΅ (Ρ‚ΠΎΠ²Π° ΡΡŠΡ‰ΠΎ сС случва).

Използвайки мСТдинния NJS, ΠΏΠΎΠ»ΡƒΡ‡Π°Π²Π°ΠΌΠ΅ Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ Π΄Π° ΠΏΡ€ΠΎΠΌΠ΅Π½ΠΈΠΌ посочСнитС ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΈ Π² конфигурацията Π½Π° nginx, ΠΊΠ°Ρ‚ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ ΠΏΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ Π½Π° срСдата ΠΈ Π΄Π° Π½Π°ΠΏΡ€Π°Π²ΠΈΠΌ някои ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ Π² скрипта (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π½Π΅ΠΏΡ€Π°Π²ΠΈΠ»Π½ΠΎ Π·Π°Π΄Π°Π΄Π΅Π½ URL).

nginx.conf

location = /auth-provider {
  internal;

  proxy_pass $auth_url;
}

location = /auth {
  internal;

  proxy_set_header Content-Length "";
  proxy_pass_request_body off;
  js_content auth.auth;
}

location ~ "^/(?<prefix>[w-]*)[/]?(?<postfix>[w-.]*)$" {
  auth_request /auth;

  js_content s3.request;
}

s3.js

var env = process.env;
var env_bool = new RegExp(/[Tt]rue|[Yy]es|[Oo]n|[TtYy]|1/);
var auth_disabled  = env_bool.test(env.DISABLE_AUTH);
var gitlab_url = env.AUTH_URL;

function url() {
  return `${gitlab_url}/jwt/auth?service=container_registry`
}

function auth(r) {
  if (auth_disabled) {
    r.return(202, '{"auth": "disabled"}');
    return null
  }

  r.subrequest('/auth-provider',
                {method: 'GET', body: ''},
                function(res) {
                  r.return(res.status, "");
                });
}

export default {auth, url}

Най-вСроятно възниква Π²ΡŠΠΏΡ€ΠΎΡΡŠΡ‚: -Π—Π°Ρ‰ΠΎ Π½Π΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ Π³ΠΎΡ‚ΠΎΠ²ΠΈ ΠΌΠΎΠ΄ΡƒΠ»ΠΈ? Π’Π°ΠΌ Π²Π΅Ρ‡Π΅ всичко Π΅ Π½Π°ΠΏΡ€Π°Π²Π΅Π½ΠΎ! НапримСр var AWS = require('aws-sdk') ΠΈ няма Π½ΡƒΠΆΠ΄Π° Π΄Π° ΠΏΠΈΡˆΠ΅Ρ‚Π΅ β€žbike” със S3 удостовСряванС!

НСка Π΄Π° ΠΏΡ€Π΅ΠΌΠΈΠ½Π΅ΠΌ към минуситС

Π—Π° ΠΌΠ΅Π½ Π½Π΅Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚Ρ‚Π° Π·Π° ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€Π°Π½Π΅ Π½Π° външни JS ΠΌΠΎΠ΄ΡƒΠ»ΠΈ стана нСприятна, Π½ΠΎ ΠΎΡ‡Π°ΠΊΠ²Π°Π½Π° функция. ΠžΠΏΠΈΡΠ°Π½ΠΎΡ‚ΠΎ Π² ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° ΠΏΠΎ-Π³ΠΎΡ€Π΅ require('crypto') Π΅ Π²Π³Ρ€Π°Π΄Π΅Π½ΠΈ ΠΌΠΎΠ΄ΡƒΠ»ΠΈ ΠΈ изискват само произвСдСния Π·Π° тях. Π‘ΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ° няма Π½Π°Ρ‡ΠΈΠ½ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎ ΠΊΠΎΠ΄ ΠΎΡ‚ скриптовС ΠΈ трябва Π΄Π° Π³ΠΎ ΠΊΠΎΠΏΠΈΡ€Π°Ρ‚Π΅ ΠΈ поставитС Π² Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅. Надявам сС, Ρ‡Π΅ някой Π΄Π΅Π½ Ρ‚Π°Π·ΠΈ функционалност Ρ‰Π΅ бъдС Π²Π½Π΅Π΄Ρ€Π΅Π½Π°.

ΠšΠΎΠΌΠΏΡ€Π΅ΡΠΈΡΡ‚Π° ΡΡŠΡ‰ΠΎ трябва Π΄Π° бъдС Π΄Π΅Π°ΠΊΡ‚ΠΈΠ²ΠΈΡ€Π°Π½Π° Π·Π° тСкущия ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ Π² Nginx gzip off;

Въй ΠΊΠ°Ρ‚ΠΎ Π² NJS няма gzip ΠΌΠΎΠ΄ΡƒΠ» ΠΈ Π΅ нСвъзмоТно Π΄Π° сС ΡΠ²ΡŠΡ€ΠΆΠ΅, слСдоватСлно няма Π½Π°Ρ‡ΠΈΠ½ Π΄Π° сС Ρ€Π°Π±ΠΎΡ‚ΠΈ с компрСсирани Π΄Π°Π½Π½ΠΈ. Вярно, Ρ‚ΠΎΠ²Π° Π²ΡΡŠΡ‰Π½ΠΎΡΡ‚ Π½Π΅ Π΅ минус Π·Π° Ρ‚ΠΎΠ·ΠΈ случай. Няма ΠΌΠ½ΠΎΠ³ΠΎ тСкст, Π° ΠΏΡ€Π΅Ρ…Π²ΡŠΡ€Π»Π΅Π½ΠΈΡ‚Π΅ Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅ са Π²Π΅Ρ‡Π΅ компрСсирани ΠΈ Π΄ΠΎΠΏΡŠΠ»Π½ΠΈΡ‚Π΅Π»Π½Π°Ρ‚Π° компрСсия няма Π΄Π° ΠΈΠΌ ΠΏΠΎΠΌΠΎΠ³Π½Π΅ ΠΌΠ½ΠΎΠ³ΠΎ. ОсвСн Ρ‚ΠΎΠ²Π°, Ρ‚ΠΎΠ²Π° Π½Π΅ Π΅ Ρ‚ΠΎΠ»ΠΊΠΎΠ²Π° Π½Π°Ρ‚ΠΎΠ²Π°Ρ€Π΅Π½Π° ΠΈΠ»ΠΈ ΠΊΡ€ΠΈΡ‚ΠΈΡ‡Π½Π° услуга, Ρ‡Π΅ Π΄Π° трябва Π΄Π° сС Π·Π°Π½ΠΈΠΌΠ°Π²Π°Ρ‚Π΅ с доставянС Π½Π° ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Π½ΠΈΠ΅ няколко милисСкунди ΠΏΠΎ-Π±ΡŠΡ€Π·ΠΎ.

ΠžΡ‚ΡΡ‚Ρ€Π°Π½ΡΠ²Π°Π½Π΅Ρ‚ΠΎ Π½Π° Π³Ρ€Π΅ΡˆΠΊΠΈ Π² скрипта ΠΎΡ‚Π½Π΅ΠΌΠ° ΠΌΠ½ΠΎΠ³ΠΎ Π²Ρ€Π΅ΠΌΠ΅ ΠΈ Π΅ възмоТно само Ρ‡Ρ€Π΅Π· β€žΠΎΡ‚ΠΏΠ΅Ρ‡Π°Ρ‚ΡŠΡ†ΠΈβ€œ Π² error.log. Π’ зависимост ΠΎΡ‚ Π·Π°Π΄Π°Π΄Π΅Π½Π°Ρ‚Π° информация Π·Π° Π½ΠΈΠ²ΠΎ Π½Π° рСгистриранС, ΠΏΡ€Π΅Π΄ΡƒΠΏΡ€Π΅ΠΆΠ΄Π΅Π½ΠΈΠ΅ ΠΈΠ»ΠΈ Π³Ρ€Π΅ΡˆΠΊΠ°, Π΅ възмоТно Π΄Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ ΡΡŠΠΎΡ‚Π²Π΅Ρ‚Π½ΠΎ 3 ΠΌΠ΅Ρ‚ΠΎΠ΄Π° r.log, r.warn, r.error. ΠžΠΏΠΈΡ‚Π²Π°ΠΌ сС Π΄Π° отстраня Π³Ρ€Π΅ΡˆΠΊΠΈ Π² някои скриптовС Π² Chrome (v8) ΠΈΠ»ΠΈ конзолния инструмСнт njs, Π½ΠΎ Π½Π΅ всичко ΠΌΠΎΠΆΠ΅ Π΄Π° сС ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈ Ρ‚Π°ΠΌ. ΠŸΡ€ΠΈ отстраняванС Π½Π° Π³Ρ€Π΅ΡˆΠΊΠΈ Π² ΠΊΠΎΠ΄, извСстСн ΠΎΡ‰Π΅ ΠΊΠ°Ρ‚ΠΎ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»Π½ΠΎ тСстванС, историята ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π° ΠΏΠΎ слСдния Π½Π°Ρ‡ΠΈΠ½:

docker-compose restart nginx
curl localhost:8080/
docker-compose logs --tail 10 nginx

ΠΈ ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΈΠΌΠ° стотици Ρ‚Π°ΠΊΠΈΠ²Π° послСдоватСлности.

ΠŸΠΈΡΠ°Π½Π΅Ρ‚ΠΎ Π½Π° ΠΊΠΎΠ΄ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° подзаявки ΠΈ ΠΏΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ Π·Π° тях сС ΠΏΡ€Π΅Π²Ρ€ΡŠΡ‰Π° Π² Π·Π°ΠΏΠ»Π΅Ρ‚Π΅Π½Π° ΠΏΠ»Π΅Ρ‚Π΅Π½ΠΈΡ†Π°. Понякога Π·Π°ΠΏΠΎΡ‡Π²Π°Ρ‚Π΅ Π΄Π° Π±ΡŠΡ€Π·Π°Ρ‚Π΅ ΠΈΠ· Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ IDE ΠΏΡ€ΠΎΠ·ΠΎΡ€Ρ†ΠΈ, ΠΎΠΏΠΈΡ‚Π²Π°ΠΉΠΊΠΈ сС Π΄Π° Ρ€Π°Π·Π±Π΅Ρ€Π΅Ρ‚Π΅ послСдоватСлността ΠΎΡ‚ дСйствия Π½Π° вашия ΠΊΠΎΠ΄. НС Π΅ Ρ‚Ρ€ΡƒΠ΄Π½ΠΎ, Π½ΠΎ понякога Π΅ ΠΌΠ½ΠΎΠ³ΠΎ досадно.

Няма пълна ΠΏΠΎΠ΄Π΄Ρ€ΡŠΠΆΠΊΠ° Π·Π° ES6.

МоТС Π΄Π° ΠΈΠΌΠ° Π΄Ρ€ΡƒΠ³ΠΈ Π½Π΅Π΄ΠΎΡΡ‚Π°Ρ‚ΡŠΡ†ΠΈ, Π½ΠΎ Π½Π΅ съм срСщал Π½ΠΈΡ‰ΠΎ Π΄Ρ€ΡƒΠ³ΠΎ. Π‘ΠΏΠΎΠ΄Π΅Π»Π΅Ρ‚Π΅ информация, Π°ΠΊΠΎ ΠΈΠΌΠ°Ρ‚Π΅ ΠΎΡ‚Ρ€ΠΈΡ†Π°Ρ‚Π΅Π»Π΅Π½ ΠΎΠΏΠΈΡ‚ с NJS.

Π—Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅

NJS Π΅ Π»Π΅ΠΊ ΠΈΠ½Ρ‚Π΅Ρ€ΠΏΡ€Π΅Ρ‚Π°Ρ‚ΠΎΡ€ с ΠΎΡ‚Π²ΠΎΡ€Π΅Π½ ΠΊΠΎΠ΄, ΠΊΠΎΠΉΡ‚ΠΎ Π²ΠΈ позволява Π΄Π° внСдряватС Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ JavaScript скриптовС Π² Nginx. По Π²Ρ€Π΅ΠΌΠ΅ Π½Π° Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Π²Π°Π½Π΅Ρ‚ΠΎ ΠΌΡƒ бСшС ΠΎΠ±ΡŠΡ€Π½Π°Ρ‚ΠΎ голямо Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° производитСлността. Π Π°Π·Π±ΠΈΡ€Π° сС, всС ΠΎΡ‰Π΅ ΠΌΠ½ΠΎΠ³ΠΎ липсва, Π½ΠΎ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΡŠΡ‚ сС Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Π²Π° ΠΎΡ‚ малък Π΅ΠΊΠΈΠΏ ΠΈ Ρ‚Π΅ Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎ добавят Π½ΠΎΠ²ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΈ ΠΊΠΎΡ€ΠΈΠ³ΠΈΡ€Π°Ρ‚ Π³Ρ€Π΅ΡˆΠΊΠΈ. Надявам сС, Ρ‡Π΅ някой Π΄Π΅Π½ NJS Ρ‰Π΅ Π²ΠΈ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈ Π΄Π° ΡΠ²ΡŠΡ€ΠΆΠ΅Ρ‚Π΅ външни ΠΌΠΎΠ΄ΡƒΠ»ΠΈ, ΠΊΠΎΠ΅Ρ‚ΠΎ Ρ‰Π΅ Π½Π°ΠΏΡ€Π°Π²ΠΈ функционалността Π½Π° Nginx ΠΏΠΎΡ‡Ρ‚ΠΈ Π½Π΅ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½Π°. Но ΠΈΠΌΠ° NGINX Plus ΠΈ Π½Π°ΠΉ-вСроятно няма Π΄Π° ΠΈΠΌΠ° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ!

Π₯Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅ с пълСн ΠΊΠΎΠ΄ Π½Π° статията

njs-pypi с ΠΏΠΎΠ΄Π΄Ρ€ΡŠΠΆΠΊΠ° Π½Π° AWS Sign v4

ОписаниС Π½Π° Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΈΠ²ΠΈΡ‚Π΅ Π½Π° ΠΌΠΎΠ΄ΡƒΠ»Π° ngx_http_js_module

ΠžΡ„ΠΈΡ†ΠΈΠ°Π»Π½ΠΎ Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅ Π½Π° NJS ΠΈ докумСнтация

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ΠΈ Π·Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° NJS ΠΎΡ‚ Π”ΠΌΠΈΡ‚Ρ€ΠΈΠΉ Π’ΠΎΠ»ΠΈΠ½Ρ†Π΅Π²

njs - собствСн JavaScript скрипт Π² nginx / Π Π΅Ρ‡ Π½Π° Π”ΠΌΠΈΡ‚Ρ€ΠΈΠΉ Π’ΠΎΠ»Π½Π΅Π² Π½Π° Saint HighLoad++ 2019

NJS Π² производство / Π Π΅Ρ‡ Π½Π° Василий Бошников Π½Π° HighLoad++ 2019

ПодписванС ΠΈ удостовСряванС Π½Π° REST заявки Π² AWS

Π˜Π·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ: www.habr.com