αžαŸ’αž‰αž»αŸ†αž”αž„αŸ’αž€αžΎαžαžƒαŸ’αž›αžΆαŸ†αž„ PyPI αž•αŸ’αž‘αžΆαž›αŸ‹αžαŸ’αž›αž½αž“αžšαž”αžŸαŸ‹αžαŸ’αž‰αž»αŸ†αžŠαŸ„αž™αž˜αžΆαž“αž€αžΆαžšαž’αž“αž»αž‰αŸ’αž‰αžΆαž αž“αž·αž„ S3 αŸ” αž“αŸ…αž›αžΎ Nginx

αž“αŸ…αž€αŸ’αž“αž»αž„αž’αžαŸ’αžαž”αž‘αž“αŸαŸ‡αžαŸ’αž‰αž»αŸ†αž…αž„αŸ‹αž…αŸ‚αž€αžšαŸ†αž›αŸ‚αž€αž”αž‘αž–αž·αžŸαŸ„αž’αž“αŸαžšαž”αžŸαŸ‹αžαŸ’αž‰αž»αŸ†αž‡αžΆαž˜αž½αž™ NJS αžŠαŸ‚αž›αž‡αžΆαž’αŸ’αž“αž€αž”αž€αž”αŸ’αžšαŸ‚ JavaScript αžŸαž˜αŸ’αžšαžΆαž”αŸ‹ Nginx αžŠαŸ‚αž›αž”αž„αŸ’αž€αžΎαžαž‘αžΎαž„αžŠαŸ„αž™ Nginx Inc αžŠαŸ„αž™αž–αžŽαŸŒαž“αžΆαž’αŸ†αž–αžΈαžŸαž˜αžαŸ’αžαž—αžΆαž–αž…αž˜αŸ’αž”αž„αžšαž”αžŸαŸ‹αžœαžΆαžŠαŸ„αž™αž”αŸ’αžšαžΎαž§αž‘αžΆαž αžšαžŽαŸαž‡αžΆαž€αŸ‹αžŸαŸ’αžαŸ‚αž„αŸ” NJS αž‚αžΊαž‡αžΆαžŸαŸ†αžŽαž»αŸ†αžšαž„αž“αŸƒ JavaScript αžŠαŸ‚αž›αž’αž“αž»αž‰αŸ’αž‰αžΆαžαž±αŸ’αž™αž’αŸ’αž“αž€αž–αž„αŸ’αžšαžΈαž€αž˜αž»αžαž„αžΆαžšαžšαž”αžŸαŸ‹ Nginx αŸ” αž‘αŸ…αž“αžΉαž„αžŸαŸ†αžŽαž½αžš αž αŸαžαž»αž’αŸ’αžœαžΈαž’αŸ’αž“αž€αž”αž€αž”αŸ’αžšαŸ‚αžαŸ’αž›αž½αž“αž―αž„??? Dmitry Volyntsev αž”αžΆαž“αž†αŸ’αž›αžΎαž™αž™αŸ‰αžΆαž„αž›αž˜αŸ’αž’αž·αžαŸ” αž“αž·αž™αžΆαž™αž±αŸ’αž™αžαŸ’αž›αžΈαŸ– NJS αž‚αžΊαž‡αžΆαžœαž·αž’αžΈ nginx αž αžΎαž™ JavaScript αž€αžΆαž“αŸ‹αžαŸ‚αžšαžΈαž€αž…αž˜αŸ’αžšαžΎαž“ "ដើម" αž“αž·αž„αžŠαŸ„αž™αž‚αŸ’αž˜αžΆαž“ GC αž˜αž·αž“αžŠαžΌαž… Lua αŸ”

αž‡αžΆβ€‹αž™αžΌαžšβ€‹αž™αžΆβ€‹αžŽαžΆαžŸαŸ‹β€‹αž˜αž€β€‹αž αžΎαž™β€¦

αž“αŸ…αž€αžΆαžšαž„αžΆαžšαž…αž»αž„αž€αŸ’αžšαŸ„αž™αžšαž”αžŸαŸ‹αžαŸ’αž‰αž»αŸ† αžαŸ’αž‰αž»αŸ†αž”αžΆαž“αž‘αž‘αž½αž›αž˜αžšαžαž€ gitlab αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž”αŸ†αž–αž„αŸ‹ CI/CD motley αž‡αžΆαž…αŸ’αžšαžΎαž“αž‡αžΆαž˜αž½αž™αž“αžΉαž„ docker-compose, dind αž“αž·αž„αž€αžΆαžšαžšαžΈαž€αžšαžΆαž™αž•αŸ’αžŸαŸαž„αž‘αŸ€αž αžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαž”αžΆαž“αž•αŸ’αž‘αŸαžšαž‘αŸ… kaniko rails αŸ” αžšαžΌαž”αž—αžΆαž–β€‹αžŠαŸ‚αž›β€‹αžαŸ’αžšαžΌαžœβ€‹αž”αžΆαž“β€‹αž”αŸ’αžšαžΎβ€‹αž–αžΈαž˜αž»αž“β€‹αž€αŸ’αž“αž»αž„ CI αžαŸ’αžšαžΌαžœβ€‹αž”αžΆαž“β€‹αž•αŸ’αž›αžΆαžŸαŸ‹αž‘αžΈβ€‹αž€αŸ’αž“αž»αž„β€‹αž‘αž˜αŸ’αžšαž„αŸ‹β€‹αžŠαžΎαž˜β€‹αžšαž”αžŸαŸ‹β€‹αž–αž½αž€αž‚αŸαŸ” αž–αž½αž€αž‚αŸαž”αžΆαž“αž’αŸ’αžœαžΎαž€αžΆαžšαž™αŸ‰αžΆαž„αžαŸ’αžšαžΉαž˜αžαŸ’αžšαžΌαžœαžšαž αžΌαžαžŠαž›αŸ‹αžαŸ’αž„αŸƒαžŠαŸ‚αž› IP gitlab αžšαž”αžŸαŸ‹αž™αžΎαž„αž”αžΆαž“αž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžš αž αžΎαž™ CI αž”αŸ’αžšαŸ‚αž‘αŸ…αž‡αžΆαž›αŸ’αž–αŸ…αŸ” αž”αž‰αŸ’αž αžΆαž‚αžΊαžαžΆαžšαžΌαž”αž—αžΆαž– docker αž˜αž½αž™αžŠαŸ‚αž›αž”αžΆαž“αž…αžΌαž›αžšαž½αž˜αž€αŸ’αž“αž»αž„ CI αž˜αžΆαž“ git αžŠαŸ‚αž›αž‘αžΆαž‰αž˜αŸ‰αžΌαžŒαž»αž› Python αžαžΆαž˜αžšαž™αŸˆ ssh αŸ” αžŸαž˜αŸ’αžšαžΆαž”αŸ‹ ssh αž’αŸ’αž“αž€β€‹αžαŸ’αžšαžΌαžœβ€‹αž€αžΆαžšβ€‹αžŸαŸ„αž―αž€αž‡αž“ αž αžΎαž™... αžœαžΆβ€‹αž˜αžΆαž“β€‹αž“αŸ…β€‹αž€αŸ’αž“αž»αž„β€‹αžšαžΌαž”αž—αžΆαž–β€‹αž‡αžΆαž˜αž½αž™β€‹αž“αžΉαž„β€‹ know_hosts αŸ” αž αžΎαž™ CI αžŽαžΆαž˜αž½αž™αž”αžΆαž“αž”αžšαžΆαž‡αŸαž™αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž€αŸ†αž αž»αžŸαž€αŸ’αž“αž»αž„αž€αžΆαžšαž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹αž‚αž“αŸ’αž›αžΉαŸ‡αžŠαŸ„αž™αžŸαžΆαžšαžαŸ‚αž—αžΆαž–αž˜αž·αž“αžŸαŸŠαžΈαž‚αŸ’αž“αžΆαžšαžœαžΆαž„ IP αž–αž·αžαž”αŸ’αžšαžΆαž€αžŠ αž“αž·αž„αž˜αž½αž™αžŠαŸ‚αž›αž”αžΆαž“αž”αž‰αŸ’αž‡αžΆαž€αŸ‹αž“αŸ…αž€αŸ’αž“αž»αž„ know_hosts αŸ” αžšαžΌαž”αž—αžΆαž–αžαŸ’αž˜αžΈαž˜αž½αž™αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ’αžšαž˜αžΌαž›αž•αŸ’αžαž»αŸ†αž™αŸ‰αžΆαž„αž†αžΆαž”αŸ‹αžšαž αŸαžŸαž–αžΈ Dockfiles αžŠαŸ‚αž›αž˜αžΆαž“αžŸαŸ’αžšαžΆαž”αŸ‹ αž αžΎαž™αž‡αž˜αŸ’αžšαžΎαžŸαžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž“αŸ’αžαŸ‚αž˜ StrictHostKeyChecking no. αž”αŸ‰αž»αž“αŸ’αžαŸ‚αžšαžŸαž‡αžΆαžαž·αž˜αž·αž“αž›αŸ’αž’αž“αŸ…αžαŸ‚αž˜αžΆαž“ αž αžΎαž™αž˜αžΆαž“αž”αŸ†αžŽαž„αž”αŸ’αžšαžΆαžαŸ’αž“αžΆαž…αž„αŸ‹αž•αŸ’αž›αžΆαžŸαŸ‹αž‘αžΈ libs αž‘αŸ…αžƒαŸ’αž›αžΆαŸ†αž„ PyPI αž―αž€αž‡αž“αŸ” αž”αŸ’αžšαžΆαž€αŸ‹αžšαž„αŸ’αžœαžΆαž“αŸ‹αž”αž“αŸ’αžαŸ‚αž˜ αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž–αžΈαž”αŸ’αžαžΌαžšαž‘αŸ… PyPI αž―αž€αž‡αž“ αž‚αžΊαž‡αžΆαž”αŸ†αž–αž„αŸ‹αžŠαŸ‚αž›αž„αžΆαž™αžŸαŸ’αžšαž½αž›αž‡αžΆαž„ αž“αž·αž„αž€αžΆαžšαž–αž·αž–αžŽαŸŒαž“αžΆαž’αž˜αŸ’αž˜αžαžΆαž“αŸƒ requirement.txt

αž‡αž˜αŸ’αžšαžΎαžŸβ€‹αž”αžΆαž“β€‹αž’αŸ’αžœαžΎβ€‹αž αžΎαž™β€‹αžŸαž»αž—αžΆαž–β€‹αž“αžΆαžšαžΈ!

αž™αžΎαž„αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž’αŸ’αžœαžΈαž‚αŸ’αžšαž”αŸ‹αž™αŸ‰αžΆαž„αž“αŸ…αž€αŸ’αž“αž»αž„αž–αž–αž€ αž“αž·αž„ Kubernetes αž αžΎαž™αž“αŸ…αž‘αžΈαž”αž‰αŸ’αž…αž”αŸ‹αž™αžΎαž„αž…αž„αŸ‹αž‘αž‘αž½αž›αž”αžΆαž“αžŸαŸαžœαžΆαž€αž˜αŸ’αž˜αžαžΌαž…αž˜αž½αž™αžŠαŸ‚αž›αž‡αžΆαž€αž»αž„αžαžΊαž“αŸαžšαžŠαŸ‚αž›αž‚αŸ’αž˜αžΆαž“αžšαžŠαŸ’αž‹αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž€αž“αŸ’αž›αŸ‚αž„αž•αŸ’αž‘αž»αž€αžαžΆαž„αž€αŸ’αžšαŸ…αŸ” αž‡αžΆαž€αžΆαžšαž”αŸ’αžšαžŸαžΎαžšαžŽαžΆαžŸαŸ‹, αž…αžΆαž”αŸ‹αžαžΆαŸ†αž„αž–αžΈαž™αžΎαž„αž”αŸ’αžšαžΎ S3, αž’αžΆαž‘αž·αž—αžΆαž–αžαŸ’αžšαžΌαžœαž”αžΆαž“αž•αŸ’αžαž›αŸ‹αž‘αŸ…αž±αŸ’αž™αžœαžΆαŸ” αž αžΎαž™αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž’αžΆαž…αž’αŸ’αžœαžΎαž‘αŸ…αž”αžΆαž“ αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž€αžΆαžšαž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹αž“αŸ…αž€αŸ’αž“αž»αž„ gitlab (αž’αŸ’αž“αž€αž’αžΆαž…αž”αž“αŸ’αžαŸ‚αž˜αžœαžΆαžŠαŸ„αž™αžαŸ’αž›αž½αž“αž―αž„αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž…αžΆαŸ†αž”αžΆαž…αŸ‹) αŸ”

αž€αžΆαžšαžŸαŸ’αžœαŸ‚αž„αžšαž€αžšαž αŸαžŸαž•αŸ’αžαž›αŸ‹αž›αž‘αŸ’αž’αž•αž›αž‡αžΆαž…αŸ’αžšαžΎαž“αŸ– s3pypi, pypicloud αž“αž·αž„αž‡αž˜αŸ’αžšαžΎαžŸαž‡αžΆαž˜αž½αž™αž€αžΆαžšαž”αž„αŸ’αž€αžΎαžαž―αž€αžŸαžΆαžš html αžŸαž˜αŸ’αžšαžΆαž”αŸ‹ turnips "αžŠαŸ„αž™αžŠαŸƒ" αŸ” αž‡αž˜αŸ’αžšαžΎαžŸαž…αž»αž„αž€αŸ’αžšαŸ„αž™αž”αžΆαž“αž”αžΆαžαŸ‹αžαŸ’αž›αž½αž“αŸ”

s3pypiαŸ– αž“αŸαŸ‡αž‚αžΊαž‡αžΆ cli αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹ S3 hostingαŸ” αž™αžΎαž„αž•αŸ’αž‘αž»αž€αž‘αžΎαž„αž―αž€αžŸαžΆαžš αž”αž„αŸ’αž€αžΎαž html αž αžΎαž™αž”αž„αŸ’αž αŸ„αŸ‡αžœαžΆαž‘αŸ…αž€αŸ’αž“αž»αž„αž’αž»αž„αžαŸ‚αž˜αž½αž™αŸ” αžŸαžΆαž€αžŸαž˜αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž“αŸ…αž•αŸ’αž‘αŸ‡αŸ”

pypicloudαŸ– αžœαžΆαž αžΆαž€αŸ‹αžŠαžΌαž…αž‡αžΆαž‚αž˜αŸ’αžšαŸ„αž„αž‚αž½αžšαž±αŸ’αž™αž…αžΆαž”αŸ‹αž’αžΆαžšαž˜αŸ’αž˜αžŽαŸαž˜αž½αž™ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž–αžΈαž”αžΆαž“αž’αžΆαž“αž―αž€αžŸαžΆαžš αžαŸ’αž‰αž»αŸ†αž˜αžΆαž“αž€αžΆαžšαžαž€αž…αž·αžαŸ’αžαŸ” αž‘αŸ„αŸ‡αž”αžΈαž‡αžΆαž˜αžΆαž“αž―αž€αžŸαžΆαžšαž›αŸ’αž’ αž“αž·αž„αžŸαž˜αžαŸ’αžαž—αžΆαž–αž€αŸ’αž“αž»αž„αž€αžΆαžšαž–αž„αŸ’αžšαžΈαž€αž±αŸ’αž™αžŸαž˜αžŸαŸ’αžšαž”αž‘αŸ…αž“αžΉαž„αžαž˜αŸ’αžšαžΌαžœαž€αžΆαžšαžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αž€αŸαžŠαŸ„αž™ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αžαžΆαž˜αž–αž·αžαžœαžΆαž”αŸ’αžšαŸ‚αž‘αŸ…αž‡αžΆαž›αŸ‚αž„αžαŸ’αžšαžΌαžœαž€αžΆαžšαžαž‘αŸ…αž‘αŸ€αž αž“αž·αž„αž–αž·αž”αžΆαž€αž€αŸ’αž“αž»αž„αž€αžΆαžšαž€αŸ†αžŽαžαŸ‹αžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’αŸ” αž€αžΆαžšαž€αŸ‚αž€αžΌαžŠαž±αŸ’αž™αžŸαž˜αž“αžΉαž„αž€αž·αž…αŸ’αž…αž€αžΆαžšαžšαž”αžŸαŸ‹αž’αŸ’αž“αž€ αž™αŸ„αž„αž‘αŸ…αžαžΆαž˜αž€αžΆαžšαž”αŸ‰αžΆαž“αŸ‹αžŸαŸ’αž˜αžΆαž“αž“αŸ…αž–αŸαž›αž“αŸ„αŸ‡αž“αžΉαž„αž…αŸ†αžŽαžΆαž™αž–αŸαž› 3-5 αžαŸ’αž„αŸƒαŸ” αžŸαŸαžœαžΆαž€αž˜αŸ’αž˜αž€αŸαžαŸ’αžšαžΌαžœαž€αžΆαžšαž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αž•αž„αžŠαŸ‚αžšαŸ” αž™αžΎαž„αž‘αž»αž€αžœαžΆαž…αŸ„αž› αž€αŸ’αž“αž»αž„αž€αžšαžŽαžΈαžŠαŸ‚αž›αž™αžΎαž„αžšαž€αž˜αž·αž“αžƒαžΎαž‰αž’αŸ’αžœαžΈαž•αŸ’αžŸαŸαž„αŸ”

αž€αžΆαžšαžŸαŸ’αžœαŸ‚αž„αžšαž€αžŸαŸŠαžΈαž‡αž˜αŸ’αžšαŸ…αž”αž“αŸ’αžαŸ‚αž˜αž‘αŸ€αžαž”αžΆαž“αž•αŸ’αžαž›αŸ‹αž›αž‘αŸ’αž’αž•αž›αž˜αŸ‰αžΌαžŒαž»αž›αžŸαž˜αŸ’αžšαžΆαž”αŸ‹ Nginx, ngx_aws_auth αŸ” αž›αž‘αŸ’αž’αž•αž›αž“αŸƒαž€αžΆαžšαž’αŸ’αžœαžΎαžαŸαžŸαŸ’αžαžšαž”αžŸαŸ‹αž‚αžΆαžαŸ‹αž‚αžΊ XML αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž„αŸ’αž αžΆαž‰αž“αŸ…αž€αŸ’αž“αž»αž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž»αž€αžšαž€αžŠαŸ‚αž›αž”αž„αŸ’αž αžΆαž‰αž–αžΈαž˜αžΆαžαž·αž€αžΆαž“αŸƒαž’αž»αž„ S3 αŸ” αž€αžΆαžšαž”αŸ’αžαŸαž‡αŸ’αž‰αžΆαž…αž·αžαŸ’αžαž…αž»αž„αž€αŸ’αžšαŸ„αž™αž“αŸ…αž–αŸαž›αž“αŸƒαž€αžΆαžšαžŸαŸ’αžœαŸ‚αž„αžšαž€αž‚αžΊαž€αžΆαž›αž–αžΈαž˜αž½αž™αž†αŸ’αž“αžΆαŸ†αž˜αž»αž“αŸ” αžƒαŸ’αž›αžΆαŸ†αž„αž˜αžΎαž›αž‘αŸ…αžαŸ’αžšαžΌαžœαž‚αŸαž”αŸ„αŸ‡αž”αž„αŸ‹αž…αŸ„αž›αŸ”

αžŠαŸ„αž™αž…αžΌαž›αž‘αŸ…αž€αžΆαž“αŸ‹αž”αŸ’αžšαž—αž–αž“αž·αž„αž’αžΆαž“ αž—αžΈ .៑ αžαŸ’αž‰αž»αŸ†αž”αžΆαž“αžŠαžΉαž„αžαžΆ XML αž’αžΆαž…αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ†αž”αŸ’αž›αŸ‚αž„αž‘αŸ…αž‡αžΆ HTML αž—αŸ’αž›αžΆαž˜αŸ— αž αžΎαž™αž•αŸ’αžαž›αŸ‹αž‘αŸ… pip αŸ” αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž–αžΈ googling αž”αž“αŸ’αžαž·αž…αž”αž“αŸ’αžαŸ‚αž˜αž‘αŸ€αžαž’αŸ†αž–αžΈ 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αžšαž½αž˜αž”αž‰αŸ’αž…αžΌαž›αž“αŸ…αž€αŸ’αž“αž»αž„αžšαžΌαž”αž—αžΆαž– docker αž•αŸ’αž›αžΌαžœαž€αžΆαžšαŸ” αž™αžΎαž„αž“αžΆαŸ†αž…αžΌαž›αžŸαŸ’αž‚αŸ’αžšαžΈαž”αžšαž”αžŸαŸ‹αž™αžΎαž„αžŠαŸ„αž™αž”αŸ’αžšαžΎαž€αžΆαžšαžŽαŸ‚αž“αžΆαŸ† 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="/km/${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

αž™αžΎαž„αž’αŸ’αžœαžΎαž˜αŸ’αžαž„αž‘αŸ€αžαž‡αžΆαž˜αž½αž™ libs αžšαž”αžŸαŸ‹αž™αžΎαž„αŸ”

# Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ для тСстов Π½ΠΎΠ²ΠΎΠ΅ ΠΎΠΊΡ€ΡƒΠΆΠ΅Π½ΠΈΠ΅
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 αž αžΎαž™αž€αžΆαžšαž”αž„αŸ’αž αŸ„αŸ‡/αž‘αžΆαž‰αž™αž€αž€αž‰αŸ’αž…αž”αŸ‹αž“αžΉαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αž“αž»αž‰αŸ’αž‰αžΆαžαŸ” αž αŸαžαž»αž’αŸ’αžœαžΈαž˜αž·αž“αž”αŸ’αžšαžΎ subquery αž˜αž½αž™ αž αžΎαž™αž•αŸ’αž‰αžΎαž‘αž·αž“αŸ’αž“αž“αŸαž™αž—αŸ’αž›αžΆαž˜αŸ—αž‘αŸ… 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 αžαžΆαž„αž€αŸ’αžšαŸ…αž”αžΆαž“αž€αŸ’αž›αžΆαž™αž‡αžΆαž˜αž»αžαž„αžΆαžšαž˜αž·αž“αžŸαž”αŸ’αž”αžΆαž™αž…αž·αžαŸ’αž αž”αŸ‰αž»αž“αŸ’αžαŸ‚αžšαŸ†αž–αžΉαž„αž‘αž»αž€αŸ” αž”αžΆαž“αž–αž·αž–αžŽαŸŒαž“αžΆαž“αŸ…αž€αŸ’αž“αž»αž„αž§αž‘αžΆαž αžšαžŽαŸαžαžΆαž„αž›αžΎαž‘αžΆαž˜αž‘αžΆαžš ('crypto') αž‚αžΊ αž˜αŸ‰αžΌαžŒαž»αž›αžŸαžΆαž„αžŸαž„αŸ‹ αž αžΎαž™αžαŸ’αžšαžΌαžœαž€αžΆαžšαžαŸ‚αž€αžΆαžšαž„αžΆαžšαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž–αž½αž€αž‚αŸαŸ” αžœαžΆαž€αŸαž˜αž·αž“αž˜αžΆαž“αžœαž·αž’αžΈαžŠαžΎαž˜αŸ’αž”αžΈαž”αŸ’αžšαžΎαž€αžΌαžŠαž‘αžΎαž„αžœαž·αž‰αž–αžΈαžŸαŸ’αž‚αŸ’αžšαžΈαž”αž‘αŸ αž αžΎαž™αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαž…αž˜αŸ’αž›αž„ αž“αž·αž„αž”αž·αž‘αž—αŸ’αž‡αžΆαž”αŸ‹αžœαžΆαž‘αŸ…αž€αŸ’αž“αž»αž„αž―αž€αžŸαžΆαžšαž•αŸ’αžŸαŸαž„αŸ—αŸ” αžαŸ’αž‰αž»αŸ†αžŸαž„αŸ’αžƒαžΉαž˜αžαžΆαžαŸ’αž„αŸƒαžŽαžΆαž˜αž½αž™αž˜αž»αžαž„αžΆαžšαž“αŸαŸ‡αž“αžΉαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αž“αž»αžœαžαŸ’αžαŸ”

αž€αžΆαžšαž”αž„αŸ’αž αžΆαž”αŸ‹αž€αŸαžαŸ’αžšαžΌαžœαžαŸ‚αž”αž·αž‘αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž‚αž˜αŸ’αžšαŸ„αž„αž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αž“αŸ…αž€αŸ’αž“αž»αž„ Nginx αž•αž„αžŠαŸ‚αžšαŸ” gzip off;

αžŠαŸ„αž™αžŸαžΆαžšαžαŸ‚αž˜αž·αž“αž˜αžΆαž“αž˜αŸ‰αžΌαžŒαž»αž› gzip αž“αŸ…αž€αŸ’αž“αž»αž„ NJS αž αžΎαž™αžœαžΆαž˜αž·αž“αž’αžΆαž…αž‘αŸ…αžšαž½αž…αž‘αŸαž€αŸ’αž“αž»αž„αž€αžΆαžšαžαž—αŸ’αž‡αžΆαž”αŸ‹αžœαžΆ αžŠαžΌαž…αŸ’αž“αŸαŸ‡αž αžΎαž™ αžœαžΆαž˜αž·αž“αž˜αžΆαž“αžœαž·αž’αžΈαžŠαžΎαž˜αŸ’αž”αžΈαž’αŸ’αžœαžΎαž€αžΆαžšαž‡αžΆαž˜αž½αž™αž‘αž·αž“αŸ’αž“αž“αŸαž™αžŠαŸ‚αž›αž”αžΆαž“αž”αž„αŸ’αž αžΆαž”αŸ‹αž“αŸ„αŸ‡αž‘αŸαŸ” αž–αž·αž αž“αŸαŸ‡αž˜αž·αž“αž˜αŸ‚αž“αž‡αžΆαž€αžΆαžšαžŠαž€αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžšαžŽαžΈαž“αŸαŸ‡αž‘αŸαŸ” αž˜αž·αž“αž˜αžΆαž“αž’αžαŸ’αžαž”αž‘αž…αŸ’αžšαžΎαž“αž‘αŸ αž αžΎαž™αž―αž€αžŸαžΆαžšαžŠαŸ‚αž›αž”αžΆαž“αž•αŸ’αž‘αŸαžšαžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž„αŸ’αž αžΆαž”αŸ‹αžšαž½αž…αž αžΎαž™ αž αžΎαž™αž€αžΆαžšαž”αž„αŸ’αž αžΆαž”αŸ‹αž”αž“αŸ’αžαŸ‚αž˜αž“αžΉαž„αž˜αž·αž“αž‡αž½αž™αž–αž½αž€αž‚αŸαž…αŸ’αžšαžΎαž“αž‘αŸαŸ” αžŠαžΌαž…αž‚αŸ’αž“αžΆαž“αŸαŸ‡αž•αž„αžŠαŸ‚αžš αž“αŸαŸ‡αž˜αž·αž“αž˜αŸ‚αž“αž‡αžΆαžŸαŸαžœαžΆαž€αž˜αŸ’αž˜αžŠαŸ‚αž›αž•αŸ’αž‘αž»αž€ αž¬αžŸαŸ†αžαžΆαž“αŸ‹αž“αŸ„αŸ‡αž‘αŸ αžŠαŸ‚αž›αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαžšαŸ†αžαžΆαž“αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž€αžΆαžšαž…αŸ‚αž€αž…αžΆαž™αž˜αžΆαžαž·αž€αžΆαž›αžΏαž“αž‡αžΆαž„αž–αžΈαžšαž”αžΈαž˜αž·αž›αŸ’αž›αžΈαžœαž·αž“αžΆαž‘αžΈαŸ”

αž€αžΆαžšαž”αŸ†αž”αžΆαžαŸ‹αž€αŸ†αž αž»αžŸαžŸαŸ’αž‚αŸ’αžšαžΈαž”αž…αŸ†αžŽαžΆαž™αž–αŸαž›αž™αžΌαžš αž αžΎαž™αž’αžΆαž…αž’αŸ’αžœαžΎαž‘αŸ…αž”αžΆαž“αžαŸ‚αžαžΆαž˜αžšαž™αŸˆ "αž€αžΆαžšαž”αŸ„αŸ‡αž–αž»αž˜αŸ’αž–" αž“αŸ…αž€αŸ’αž“αž»αž„ 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

αž αžΎαž™αžœαžΆαž’αžΆαž…αž˜αžΆαž“αžšαžΆαž”αŸ‹αžšαž™αž›αŸ†αžŠαžΆαž”αŸ‹αŸ”

αž€αžΆαžšαžŸαžšαžŸαŸαžšαž€αžΌαžŠαžŠαŸ„αž™αž”αŸ’αžšαžΎαžŸαŸ†αžŽαž½αžšαžšαž„ αž“αž·αž„αž’αžαŸαžšαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž–αž½αž€αžœαžΆαž”αŸ’αžšαŸ‚αž‘αŸ…αž‡αžΆ tangle tangle αŸ” αž–αŸαž›αžαŸ’αž›αŸ‡αž’αŸ’αž“αž€αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αž”αŸ’αžšαž‰αžΆαž”αŸ‹αž”αŸ’αžšαž‰αžΆαž›αŸ‹αž‡αž»αŸ†αžœαž·αž‰αž”αž„αŸ’αž’αž½αž… IDE αž•αŸ’αžŸαŸαž„αŸ—αž‚αŸ’αž“αžΆαžŠαŸ„αž™αž–αŸ’αž™αžΆαž™αžΆαž˜αžŸαŸ’αžœαŸ‚αž„αžšαž€αž›αŸ†αžŠαžΆαž”αŸ‹αž“αŸƒαžŸαž€αž˜αŸ’αž˜αž—αžΆαž–αž“αŸƒαž€αžΌαžŠαžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αŸ” αžœαžΆαž˜αž·αž“αž–αž·αž”αžΆαž€αž‘αŸ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž–αŸαž›αžαŸ’αž›αŸ‡αžœαžΆαžšαŸ†αžαžΆαž“αžαŸ’αž›αžΆαŸ†αž„αžŽαžΆαžŸαŸ‹αŸ”

αž˜αž·αž“αž˜αžΆαž“αž€αžΆαžšαž‚αžΆαŸ†αž‘αŸ’αžšαž–αŸαž‰αž›αŸαž‰αžŸαž˜αŸ’αžšαžΆαž”αŸ‹ ES6 αž‘αŸαŸ”

αžœαžΆβ€‹αž’αžΆαž…β€‹αž“αžΉαž„β€‹αž˜αžΆαž“β€‹αž…αŸ†αžŽαž»αž…β€‹αžαŸ’αžœαŸ‡αžαžΆαžβ€‹αž˜αž½αž™β€‹αž…αŸ†αž“αž½αž“β€‹αž•αŸ’αžŸαŸαž„β€‹αž‘αŸ€αž αž”αŸ‰αž»αž“αŸ’αžαŸ‚β€‹αžαŸ’αž‰αž»αŸ†β€‹αž˜αž·αž“β€‹αž”αžΆαž“β€‹αž‡αž½αž”β€‹αž”αŸ’αžšαž‘αŸ‡β€‹αž’αŸ’αžœαžΈβ€‹αž•αŸ’αžŸαŸαž„β€‹αž‘αŸ€αžβ€‹αž‘αŸαŸ” αž…αŸ‚αž€αžšαŸ†αž›αŸ‚αž€αž–αŸαžαŸŒαž˜αžΆαž“ αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž’αŸ’αž“αž€αž˜αžΆαž“αž”αž‘αž–αž·αžŸαŸ„αž’αž“αŸαž’αžœαž·αž‡αŸ’αž‡αž˜αžΆαž“αž€αŸ’αž“αž»αž„αž€αžΆαžšαž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹ NJSαŸ”

αžŸαŸαž…αž€αŸ’αžαžΈαžŸαž“αŸ’αž“αž·αžŠαŸ’αž‹αžΆαž“

NJS αž‚αžΊαž‡αžΆαž’αŸ’αž“αž€αž”αž€αž”αŸ’αžšαŸ‚αž”αŸ’αžšαž—αž–αž”αžΎαž€αž…αŸ†αž αžŠαŸ‚αž›αž˜αžΆαž“αž‘αž˜αŸ’αž„αž“αŸ‹αžŸαŸ’αžšαžΆαž›αžŠαŸ‚αž›αž’αž“αž»αž‰αŸ’αž‰αžΆαžαž±αŸ’αž™αž’αŸ’αž“αž€αž’αž“αž»αžœαžαŸ’αžαžŸαŸ’αž‚αŸ’αžšαžΈαž” JavaScript αž•αŸ’αžŸαŸαž„αŸ—αž“αŸ…αž€αŸ’αž“αž»αž„ Nginx αŸ” αž€αŸ’αž“αž»αž„αž’αŸ†αž‘αž»αž„αž–αŸαž›αž“αŸƒαž€αžΆαžšαž’αž—αž·αžœαžŒαŸ’αžαž“αŸαžšαž”αžŸαŸ‹αžœαžΆ αž€αžΆαžšαž™αž€αž…αž·αžαŸ’αžαž‘αž»αž€αžŠαžΆαž€αŸ‹αž™αŸ‰αžΆαž„αžαŸ’αž›αžΆαŸ†αž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž™αž€αž…αž·αžαŸ’αžαž‘αž»αž€αžŠαžΆαž€αŸ‹αž…αŸ†αž–αŸ„αŸ‡αž€αžΆαžšαž’αž“αž»αžœαžαŸ’αžαŸ” αž‡αžΆαž€αžΆαžšαž–αž·αžαžŽαžΆαžŸαŸ‹ αž“αŸ…αž˜αžΆαž“αž…αŸ†αžŽαž»αž…αžαŸ’αžœαŸ‡αžαžΆαžαž‡αžΆαž…αŸ’αžšαžΎαž“ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž‚αž˜αŸ’αžšαŸ„αž„αž“αŸαŸ‡αž€αŸ†αž–αž»αž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž„αŸ’αž€αžΎαžαž‘αžΎαž„αžŠαŸ„αž™αž€αŸ’αžšαž»αž˜αžαžΌαž…αž˜αž½αž™ αž αžΎαž™αž–αž½αž€αž‚αŸαž€αŸ†αž–αž»αž„αž”αž“αŸ’αžαŸ‚αž˜αž™αŸ‰αžΆαž„αžŸαž€αž˜αŸ’αž˜αž“αžΌαžœαž˜αž»αžαž„αžΆαžšαžαŸ’αž˜αžΈαŸ— αž“αž·αž„αž‡αž½αžŸαž‡αž»αž›αž€αŸ†αž αž»αžŸαŸ” αžαŸ’αž‰αž»αŸ†αžŸαž„αŸ’αžƒαžΉαž˜αžαžΆαžαŸ’αž„αŸƒαžŽαžΆαž˜αž½αž™ NJS αž“αžΉαž„αž’αž“αž»αž‰αŸ’αž‰αžΆαžαž±αŸ’αž™αž’αŸ’αž“αž€αž—αŸ’αž‡αžΆαž”αŸ‹αž˜αŸ‰αžΌαžŒαž»αž›αžαžΆαž„αž€αŸ’αžšαŸ… αžŠαŸ‚αž›αž“αžΉαž„αž’αŸ’αžœαžΎαž±αŸ’αž™αž˜αž»αžαž„αžΆαžš Nginx αžŸαŸ’αž‘αžΎαžšαžαŸ‚αž‚αŸ’αž˜αžΆαž“αžŠαŸ‚αž“αž€αŸ†αžŽαžαŸ‹αŸ” αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž˜αžΆαž“ NGINX Plus αž αžΎαž™αž‘αŸ†αž“αž„αž‡αžΆαž˜αž·αž“αž˜αžΆαž“αž›αž€αŸ’αžαžŽαŸˆαž–αž·αžŸαŸαžŸαž‘αŸ!

αžƒαŸ’αž›αžΆαŸ†αž„αžŠαŸ‚αž›αž˜αžΆαž“αž›αŸαžαž€αžΌαžŠαž–αŸαž‰αž›αŸαž‰αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž’αžαŸ’αžαž”αž‘

njs-pypi αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž€αžΆαžšαž‚αžΆαŸ†αž‘αŸ’αžš AWS Sign v4

αž€αžΆαžšαž–αž·αž–αžŽαŸŒαž“αžΆαž’αŸ†αž–αžΈαž€αžΆαžšαžŽαŸ‚αž“αžΆαŸ†αž“αŸƒαž˜αŸ‰αžΌαžŒαž»αž› ngx_http_js_module

αžƒαŸ’αž›αžΆαŸ†αž„ NJS αž•αŸ’αž›αžΌαžœαž€αžΆαžš ΠΈ αž―αž€αžŸαžΆαžš

αž§αž‘αžΆαž αžšαžŽαŸαž“αŸƒαž€αžΆαžšαž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹ NJS αž–αžΈ Dmitry Volintsev

njs - αžŸαŸ’αž‚αŸ’αžšαžΈαž” JavaScript αžŠαžΎαž˜αž“αŸ…αž€αŸ’αž“αž»αž„ nginx / αžŸαž»αž“αŸ’αž‘αžšαž€αžαžΆαžŠαŸ„αž™ Dmitry Volnyev αž“αŸ… Saint HighLoad++ 2019

NJS αž“αŸ…αž€αŸ’αž“αž»αž„αž•αž›αž·αžαž€αž˜αŸ’αž˜ / αžŸαž»αž“αŸ’αž‘αžšαž€αžαžΆαžŠαŸ„αž™ Vasily Soshnikov αž“αŸ… HighLoad++ 2019

αž€αžΆαžšαž…αž»αŸ‡αž αžαŸ’αžαž›αŸαžαžΆ αž“αž·αž„αž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹αžŸαŸ†αžŽαžΎ REST αž“αŸ…αž€αŸ’αž“αž»αž„ AWS

αž”αŸ’αžšαž—αž–: www.habr.com