рдореИрд▓реЗ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рд░ S3 рд╕рдВрдЧ рдореЗрд░реЛ рдЖрдлреНрдиреИ PyPI рднрдгреНрдбрд╛рд░ рдмрдирд╛рдПрдХреЛ рдЫреБред Nginx рдорд╛

рдпрд╕ рд▓реЗрдЦрдорд╛ рдо NJS рд╕рдВрдЧ рдореЗрд░реЛ рдЕрдиреБрднрд╡ рд╕рд╛рдЭрд╛ рдЧрд░реНрди рдЪрд╛рд╣рдиреНрдЫреБ, Nginx Inc рджреНрд╡рд╛рд░рд╛ рд╡рд┐рдХрд╕рд┐рдд Nginx рдХреЛ рд▓рд╛рдЧрд┐ рдЬрд╛рднрд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рджреЛрднрд╛рд╖реЗ, рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЙрджрд╛рд╣рд░рдг рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░ рдпрд╕рдХреЛ рдореБрдЦреНрдп рдХреНрд╖рдорддрд╛рд╣рд░реВ рд╡рд░реНрдгрди рдЧрд░реНрджреИред NJS JavaScript рдХреЛ рдПрдХ рдЙрдкрд╕рдореВрд╣ рд╣реЛ рдЬрд╕рд▓реЗ рддрдкрд╛рдИрдВрд▓рд╛рдИ Nginx рдХреЛ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдЧрд░реНрди рдЕрдиреБрдорддрд┐ рджрд┐рдиреНрдЫред рдкреНрд░рд╢реНрдирдорд╛ рдЖрдлреНрдиреИ рджреЛрднрд╛рд╖реЗ рдХрд┐рди ??? рджрд┐рдорд┐рддреНрд░реА Volyntsev рд╡рд┐рд╕реНрддреГрдд рдЬрд╡рд╛рдл рджрд┐рдПред рдЫреЛрдЯрдХрд░реАрдорд╛: NJS nginx-way рд╣реЛ, рд░ JavaScript рдЕрдзрд┐рдХ рдкреНрд░рдЧрддрд┐рд╢реАрд▓, "рдиреЗрдЯрд┐рдн" рд░ GC рдмрд┐рдирд╛, рд▓реБрдЖ рднрдиреНрджрд╛ рдлрд░рдХ рдЫред

рдзреЗрд░реИ рд╕рдордп рдЕрдШрд┐тАж

рдореЗрд░реЛ рдЕрдиреНрддрд┐рдо рдХрд╛рдордорд╛, рдореИрд▓реЗ рдбрдХрд░-рдХрдореНрдкреЛрдЬ, рдбрд┐рдиреНрдб рд░ рдЕрдиреНрдп рд░рдорд╛рдЗрд▓реЛрд╣рд░реВрдХрд╛ рд╕рд╛рде рдзреЗрд░реИ рдореЛрдЯрд▓реА рд╕реАрдЖрдИ/рд╕реАрдбреА рдкрд╛рдЗрдкрд▓рд╛рдЗрдирд╣рд░реВрдХрд╛ рд╕рд╛рде рдЧрд┐рдЯрд▓реНрдпрд╛рдм рдкреНрд░рд╛рдкреНрдд рдЧрд░реЗрдВ, рдЬреБрди рдХрд╛рдирд┐рдХреЛ рд░реЗрд▓рд╣рд░реВрдорд╛ рд╣рд╕реНрддрд╛рдиреНрддрд░рдг рдЧрд░рд┐рдПрдХреЛ рдерд┐рдпреЛред рдЫрд╡рд┐рд╣рд░реВ рдЬреБрди рдкрд╣рд┐рд▓реЗ CI рдорд╛ рдкреНрд░рдпреЛрдЧ рдЧрд░рд┐рдПрдХрд╛ рдерд┐рдП рддрд┐рдиреАрд╣рд░реВрдХреЛ рдореВрд▓ рд░реВрдкрдорд╛ рд╕рд╛рд░рд┐рдпреЛред рддрд┐рдиреАрд╣рд░реВрд▓реЗ рдареАрдХрд╕рдБрдЧ рдХрд╛рдо рдЧрд░реЗ рдЬрдмрд╕рдореНрдо рд╣рд╛рдореНрд░реЛ gitlab IP рдкрд░рд┐рд╡рд░реНрддрди рднрдпреЛ рд░ CI рдХрджреНрджреВрдорд╛ рдкрд░рд┐рдгрдд рднрдпреЛред рд╕рдорд╕реНрдпрд╛ рдпреЛ рдерд┐рдпреЛ рдХрд┐ CI рдорд╛ рднрд╛рдЧ рд▓рд┐рдиреЗ рдбрдХрд░ рдЫрд╡рд┐рд╣рд░реВ рдордзреНрдпреЗ рдПрдЙрдЯрд╛ git рдерд┐рдпреЛ, рдЬрд╕рд▓реЗ ssh рдорд╛рд░реНрдлрдд рдкрд╛рдЗрдерди рдореЛрдбреНрдпреБрд▓рд╣рд░реВ рддрд╛рдиреНрдпреЛред ssh рдХреЛ рд▓рд╛рдЧреА рддрдкрд╛рдИрд▓рд╛рдИ рдирд┐рдЬреА рдХреБрдЮреНрдЬреА рдЪрд╛рд╣рд┐рдиреНрдЫ рд░... рдпреЛ рдЬреНрдЮрд╛рдд_рд╣реЛрд╕реНрдЯрдХреЛ рд╕рд╛рде рдЫрд╡рд┐рдорд╛ рдерд┐рдпреЛред рд░ рдХреБрдиреИ рдкрдирд┐ CI рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЖрдИрдкреА рд░ рдЬреНрдЮрд╛рдд_рд╣реЛрд╕реНрдЯрдорд╛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдЧрд░рд┐рдПрдХреЛ рдмреАрдЪрдХреЛ рдореЗрд▓ рдирдорд┐рд▓реНрдиреЗ рдХрд╛рд░рдгрд▓реЗ рдХреБрдЮреНрдЬреА рдкреНрд░рдорд╛рдгреАрдХрд░рдг рддреНрд░реБрдЯрд┐рд╕рдБрдЧ рдЕрд╕рдлрд▓ рднрдпреЛред рдЕрд╡рд╕реНрдерд┐рдд рдбрдХрдлрд╛рдЗрд▓рд╣рд░реВрдмрд╛рдЯ рдирдпрд╛рдБ рдЫрд╡рд┐ рджреНрд░реБрдд рд░реВрдкрдорд╛ рднреЗрд▓рд╛ рдЧрд░рд┐рдпреЛ рд░ рд╡рд┐рдХрд▓реНрдк рдердкрд┐рдпреЛ StrictHostKeyChecking noред рддрд░ рдЦрд░рд╛рдм рд╕реНрд╡рд╛рдж рд░рд╣реНрдпреЛ рд░ libs рд▓рд╛рдИ рдирд┐рдЬреА PyPI рднрдгреНрдбрд╛рд░рдорд╛ рд╕рд╛рд░реНрдиреЗ рдЗрдЪреНрдЫрд╛ рдерд┐рдпреЛред рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд рдмреЛрдирд╕, рдирд┐рдЬреА PyPI рдорд╛ рд╕реНрд╡рд┐рдЪ рдЧрд░реЗрдкрдЫрд┐, рдПрдХ рд╕рд░рд▓ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рд░ рдЖрд╡рд╢реНрдпрдХрддрд╛рд╣рд░реВрдХреЛ рд╕рд╛рдорд╛рдиреНрдп рд╡рд┐рд╡рд░рдг рдерд┐рдпреЛредtxt

рдЫрдиреЛрдЯ рднрдЗрд╕рдХреЗрдХреЛ рдЫ, рд╣рдЬреБрд░рд╣рд░реБ!

рд╣рд╛рдореАрд▓реЗ рдХреНрд▓рд╛рдЙрдб рд░ рдХреБрдмрд░реНрдиреЗрдЯреНрд╕рдорд╛ рд╕рдмреИ рдХреБрд░рд╛ рдЪрд▓рд╛рдЙрдБрдЫреМрдВ, рд░ рдЕрдиреНрддрдорд╛ рд╣рд╛рдореА рдПрдЙрдЯрд╛ рд╕рд╛рдиреЛ рд╕реЗрд╡рд╛ рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрди рдЪрд╛рд╣рдиреНрдереНрдпреМрдВ рдЬреБрди рдмрд╛рд╣реНрдп рднрдгреНрдбрд╛рд░рдг рднрдПрдХреЛ рд╕реНрдЯреЗрдЯрд▓реЗрд╕ рдХрдиреНрдЯреЗрдирд░ рдерд┐рдпреЛред рдард┐рдХ рдЫ, рд╣рд╛рдореАрд▓реЗ S3 рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрдХреЛрд▓реЗ, рдпрд╕рд▓рд╛рдИ рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рджрд┐рдЗрдпреЛред рд░, рдпрджрд┐ рд╕рдореНрднрд╡ рдЫ рднрдиреЗ, gitlab рдорд╛ рдкреНрд░рдорд╛рдгреАрдХрд░рдгрдХреЛ рд╕рд╛рде (рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рднрдПрдорд╛ рддрдкрд╛рдЗрдБ рдпрд╕рд▓рд╛рдИ рдЖрдлреИрдВ рдердкреНрди рд╕рдХреНрдиреБрд╣реБрдиреНрдЫ)ред

рджреНрд░реБрдд рдЦреЛрдЬрд▓реЗ рдзреЗрд░реИ рдирддрд┐рдЬрд╛рд╣рд░реВ рд▓реНрдпрд╛рдпреЛ: s3pypi, pypicloud рд░ рд╢рд▓рдЬрдордХрд╛ рд▓рд╛рдЧрд┐ html рдлрд╛рдЗрд▓рд╣рд░реВрдХреЛ "рдореНрдпрд╛рдиреБрдЕрд▓" рд╕рд┐рд░реНрдЬрдирд╛рдХреЛ рд╕рд╛рде рд╡рд┐рдХрд▓реНрдкред рдЕрдиреНрддрд┐рдо рд╡рд┐рдХрд▓реНрдк рдЖрдлреИ рдЧрд╛рдпрдм рднрдпреЛред

s3pypi: рдпреЛ S3 рд╣реЛрд╕реНрдЯрд┐рдЩ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрди рдХреЛ рд▓рд╛рдЧреА рдПрдХ cli рд╣реЛред рд╣рд╛рдореА рдлрд╛рдЗрд▓рд╣рд░реВ рдЕрдкрд▓реЛрдб рдЧрд░реНрдЫреМрдВ, html рдЙрддреНрдкрдиреНрди рдЧрд░реНрдЫреМрдВ рд░ рдЙрд╣реА рдмрд╛рд▓реНрдЯреАрдорд╛ рдЕрдкрд▓реЛрдб рдЧрд░реНрдЫреМрдВред рдШрд░рдХреЛ рдкреНрд░рдпреЛрдЧрдХреЛ рд▓рд╛рдЧрд┐ рдЙрдкрдпреБрдХреНрддред

pypicloud: рдпреЛ рдПрдХ рдЪрд╛рдЦрд▓рд╛рдЧреНрджреЛ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдЬрд╕реНрддреЛ рджреЗрдЦрд┐рдиреНрдереНрдпреЛ, рддрд░ рдХрд╛рдЧрдЬрд╛рдд рдкрдвреЗрдкрдЫрд┐ рдо рдирд┐рд░рд╛рд╢ рднрдПрдБред рд░рд╛рдореНрд░реЛ рдХрд╛рдЧрдЬрд╛рддрд╣рд░реВ рд░ рддрдкрд╛рдИрдВрдХреЛ рдЖрд╡рд╢реНрдпрдХрддрд╛рд╣рд░реВ рдЕрдиреБрд░реВрдк рд╡рд┐рд╕реНрддрд╛рд░ рдЧрд░реНрдиреЗ рдХреНрд╖рдорддрд╛рдХреЛ рдмрд╛рд╡рдЬреБрдж, рд╡рд╛рд╕реНрддрд╡рдорд╛ рдпреЛ рдЕрдирд╛рд╡рд╢реНрдпрдХ рд░ рдХрдиреНрдлрд┐рдЧрд░ рдЧрд░реНрди рдЧрд╛рд╣реНрд░реЛ рднрдпреЛред рддрдкрд╛рдИрдВрдХреЛ рдХрд╛рд░реНрдпрд╣рд░реВ рдЕрдиреБрд░реВрдк рдХреЛрдб рд╕рдЪреНрдпрд╛рдЙрди, рддреНрдпрд╕ рд╕рдордпрдХреЛ рдЕрдиреБрдорд╛рди рдЕрдиреБрд╕рд╛рд░, 3-5 рджрд┐рди рд▓рд╛рдЧреНрдиреЗ рдерд┐рдпреЛред рд╕реЗрд╡рд╛рд▓рд╛рдИ рдбрд╛рдЯрд╛рдмреЗрд╕ рдкрдирд┐ рдЪрд╛рд╣рд┐рдиреНрдЫред рд╣рд╛рдореАрд▓реЗ рдЕрд░реБ рдХреЗрд╣рд┐ рдирднреЗрдЯреЗрдХреЛ рдЕрд╡рд╕реНрдерд╛рдорд╛ рдЫреЛрдбреНрдпреМрдВред

рдердк рдЧрд╣рд┐рд░реЛ рдЦреЛрдЬрд▓реЗ Nginx, ngx_aws_auth рдХреЛ рд▓рд╛рдЧрд┐ рдПрдХ рдореЛрдбреНрдпреБрд▓ рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрдпреЛред рдЙрд╕рдХреЛ рдкрд░реАрдХреНрд╖рдгрдХреЛ рдирддрд┐рдЬрд╛ рдмреНрд░рд╛рдЙрдЬрд░рдорд╛ XML рджреЗрдЦрд╛рдЗрдПрдХреЛ рдерд┐рдпреЛ, рдЬрд╕рд▓реЗ S3 рдмрд╛рд▓реНрдЯрд┐рдирдХреЛ рд╕рд╛рдордЧреНрд░реА рджреЗрдЦрд╛рдЙрдБрджрдЫред рдЦреЛрдЬрдХреЛ рд╕рдордпрдорд╛ рдЕрдиреНрддрд┐рдо рдкреНрд░рддрд┐рдмрджреНрдзрддрд╛ рдПрдХ рд╡рд░реНрд╖ рдкрд╣рд┐рд▓реЗ рдерд┐рдпреЛред рднрдгреНрдбрд╛рд░ рдЫреЛрдбрд┐рдПрдХреЛ рджреЗрдЦрд┐рдиреНрдереНрдпреЛред

рд╕реНрд░реЛрддрдорд╛ рдЧрдПрд░ рдкрдвреЗрд░ PEP-503 рдореИрд▓реЗ рдорд╣рд╕реБрд╕ рдЧрд░реЗрдВ рдХрд┐ XML рд▓рд╛рдИ рдлреНрд▓рд╛рдИрдорд╛ HTML рдорд╛ рд░реВрдкрд╛рдиреНрддрд░рдг рдЧрд░реНрди рд╕рдХрд┐рдиреНрдЫ рд░ pip рдорд╛ рджрд┐рдЗрдиреНрдЫред Nginx рд░ S3 рдХреЛ рдмрд╛рд░реЗрдорд╛ рдЕрд▓рд┐ рдмрдвреА рдЧреБрдЧрд▓ рдЧрд░реЗрдкрдЫрд┐, рдореИрд▓реЗ Nginx рдХреЛ рд▓рд╛рдЧрд┐ JS рдорд╛ рд▓реЗрдЦрд┐рдПрдХреЛ S3 рдорд╛ рдкреНрд░рдорд╛рдгреАрдХрд░рдгрдХреЛ рдЙрджрд╛рд╣рд░рдг рднреЗрдЯреНрдЯрд╛рдПрдБред рдпрд╕рд░реА рдореИрд▓реЗ NJS рд▓рд╛рдИ рднреЗрдЯреЗред

рдпреЛ рдЙрджрд╛рд╣рд░рдгрд▓рд╛рдИ рдЖрдзрд╛рд░рдХреЛ рд░реВрдкрдорд╛ рд▓рд┐рдБрджреИ, рдПрдХ рдШрдгреНрдЯрд╛ рдкрдЫрд┐ рдореИрд▓реЗ рдореЗрд░реЛ рдмреНрд░рд╛рдЙрдЬрд░рдорд╛ ngx_aws_auth рдореЛрдбреНрдпреБрд▓ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрджрд╛ рдЙрд╣реА XML рджреЗрдЦреЗ, рддрд░ рд╕рдмреИ рдХреБрд░рд╛ рдкрд╣рд┐рд▓реЗ рдиреИ JS рдорд╛ рд▓реЗрдЦрд┐рдПрдХреЛ рдерд┐рдпреЛред

рдорд▓рд╛рдИ рд╕рд╛рдБрдЪреНрдЪреИ nginx рд╕рдорд╛рдзрд╛рди рдорди рдкрд░реНрдпреЛред рдкрд╣рд┐рд▓реЛ, рд░рд╛рдореНрд░реЛ рдХрд╛рдЧрдЬрд╛рдд рд░ рдзреЗрд░реИ рдЙрджрд╛рд╣рд░рдгрд╣рд░реВ, рджреЛрд╕реНрд░реЛ, рд╣рд╛рдореА рдлрд╛рдЗрд▓рд╣рд░реВрд╕рдБрдЧ рдХрд╛рдо рдЧрд░реНрдирдХрд╛ рд▓рд╛рдЧрд┐ Nginx рдХреЛ рд╕рдмреИ рдЪреАрдЬрд╣рд░реВ рдкрд╛рдЙрдБрдЫреМрдВ (рдмрд╛рдХрд╕ рдмрд╛рд╣рд┐рд░), рддреЗрд╕реНрд░реЛ, Nginx рдХреЛ рд▓рд╛рдЧрд┐ рдХрдиреНрдлрд┐рдЧрд╣рд░реВ рдХрд╕рд░реА рд▓реЗрдЦреНрдиреЗ рднрдиреЗрд░ рдЬрд╛рдиреНрдиреЗ рдЬреЛ рдХреЛрд╣реАрд▓реЗ рдХреЗ рд╣реЛ рднрдиреЗрд░ рдкрддреНрддрд╛ рд▓рдЧрд╛рдЙрди рд╕рдХреНрд╖рдо рд╣реБрдиреЗрдЫред рдкрд╛рдЗрдерди рд╡рд╛ рдЧреЛ (рдпрджрд┐ рд╕реНрдХреНрд░реНрдпрд╛рдЪрдмрд╛рдЯ рд▓реЗрдЦрд┐рдПрдХреЛ рднрдП) рдХреЛ рддреБрд▓рдирд╛рдорд╛, рдиреЗрдХреНрд╕рд╕рдХреЛ рдЙрд▓реНрд▓реЗрдЦ рдирдЧрд░реНрдиреБ, рдорд┐рдирд┐рдорд▓рд┐рдЬреНрдо рдкрдирд┐ рдореЗрд░реЛ рд▓рд╛рдЧрд┐ рдПрдХ рдкреНрд▓рд╕ рд╣реЛред

TL; DR 2 рджрд┐рди рдкрдЫрд┐, PyPi рдХреЛ рдкрд░реАрдХреНрд╖рдг рд╕рдВрд╕реНрдХрд░рдг рдкрд╣рд┐рд▓реЗ рдиреИ CI рдорд╛ рдкреНрд░рдпреЛрдЧ рдЧрд░рд┐рдПрдХреЛ рдерд┐рдпреЛред

рдпрд╕рд▓реЗ рдХрд╕рд░реА рдХрд╛рдо рдЧрд░реНрдЫ?

рдореЛрдбреНрдпреБрд▓ Nginx рдорд╛ рд▓реЛрдб рдЧрд░рд┐рдПрдХреЛ рдЫ ngx_http_js_module, рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рдбрдХрд░ рдЫрд╡рд┐рдорд╛ рд╕рдорд╛рд╡реЗрд╢ред рд╣рд╛рдореА рдирд┐рд░реНрджреЗрд╢рди рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░ рд╣рд╛рдореНрд░реЛ рд▓рд┐рдкрд┐ рдЖрдпрд╛рдд рдЧрд░реНрдЫреМрдВ js_importNginx рдХрдиреНрдлрд┐рдЧрд░реЗрд╕рдирдорд╛ред рдкреНрд░рдХрд╛рд░реНрдпрд▓рд╛рдИ рдирд┐рд░реНрджреЗрд╢рдирджреНрд╡рд╛рд░рд╛ рдмреЛрд▓рд╛рдЗрдПрдХреЛ рдЫ 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 рдПрдХ subquery рдмрдирд╛рдЗрдПрдХреЛ рдЫ location = /sub-query, рддрд░реНрдХрдмрд╛рдЯ рдкреНрд░рд╛рдкреНрдд рд╡рд┐рдзрд┐ (рд╣рд╛рд▓рдХреЛ рдЙрджрд╛рд╣рд░рдг GET рдорд╛) рд╕рдВрдЧ (r), рдпрд╕ рдкреНрд░рдХрд╛рд░реНрдпрд▓рд╛рдИ рдХрд▓ рдЧрд░реНрджрд╛ рд╕реНрдкрд╖реНрдЯ рд░реВрдкрдорд╛ рдкрд╛рд░рд┐рдд рдЧрд░рд┐рдпреЛред subrequest рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдкреНрд░рдХрд╛рд░реНрдп рдорд╛ рдкреНрд░рд╢реЛрдзрди рдЧрд░рд┐рдиреЗрдЫ call_back.

S3 рдкреНрд░рдпрд╛рд╕ рдЧрд░реНрджреИ

рдирд┐рдЬреА S3 рднрдгреНрдбрд╛рд░рдгрдорд╛ рдЕрдиреБрд░реЛрдз рдЧрд░реНрди, рд╣рд╛рдореАрд▓рд╛рдИ рдЖрд╡рд╢реНрдпрдХ рдЫ:

ACCESS_KEY

SECRET_KEY

S3_BUCKET

рдкреНрд░рдпреЛрдЧ рдЧрд░рд┐рдПрдХреЛ http рд╡рд┐рдзрд┐рдмрд╛рдЯ, рд╣рд╛рд▓рдХреЛ рдорд┐рддрд┐/рд╕рдордп, S3_NAME рд░ URI, рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдкреНрд░рдХрд╛рд░рдХреЛ рд╕реНрдЯреНрд░рд┐рдЩ рдЙрддреНрдкрдиреНрди рд╣реБрдиреНрдЫ, рдЬреБрди SECRET_KEY рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдЧрд░рд┐рдПрдХреЛ (HMAC_SHA1) рд╣реБрдиреНрдЫред рдЕрд░реНрдХреЛ рдЬрд╕реНрддреИ рд▓рд╛рдЗрди рдЫ 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 рд╕рд╛рдЗрди 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 рд▓рд╛рдИ рдЕрдиреБрд░реЛрдз рдЧрд░реНрджрдЫред рдпрджрд┐ рддрдкрд╛рдЗрдБ "рд░реВрдЯ" рдХреЛ рд╕рд╛рдордЧреНрд░реАрд╣рд░реВ рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрди рдЖрд╡рд╢реНрдпрдХ рдЫ рднрдиреЗ, рддрдкрд╛рдЗрдБрд▓реЗ рдбреЗрд▓рд┐рдорд┐рдЯрд░ рд╕рдВрдХреЗрдд рдЧрд░реНрдиреЗ uri рдЕрдиреБрд░реЛрдз рд╕рд┐рд░реНрдЬрдирд╛ рдЧрд░реНрди рдЖрд╡рд╢реНрдпрдХ рдЫред delimiter, рдЬрд╕рд▓реЗ рдбрд╛рдЗрд░реЗрдХреНрдЯрд░реАрд╣рд░реВрд╕рдБрдЧ рд╕рдореНрдмрдиреНрдзрд┐рдд рд╕рдмреИ CommonPrefixes xml рддрддреНрд╡рд╣рд░реВрдХреЛ рд╕реВрдЪреА рдлрд░реНрдХрд╛рдЙрдиреЗрдЫ (PyPI рдХреЛ рдорд╛рдорд▓рд╛рдорд╛, рд╕рдмреИ рдкреНрдпрд╛рдХреЗрдЬрд╣рд░реВрдХреЛ рд╕реВрдЪреА)ред рдпрджрд┐ рддрдкрд╛рдЗрдБ рдПрдХ рд╡рд┐рд╢реЗрд╖ рдбрд╛рдЗрд░реЗрдХреНрдЯрд░реА (рд╕рдмреИ рдкреНрдпрд╛рдХреЗрдЬ рд╕рдВрд╕реНрдХрд░рдгрд╣рд░реВрдХреЛ рд╕реВрдЪреА) рдорд╛ рд╕рд╛рдордЧреНрд░реАрд╣рд░реВрдХреЛ рд╕реВрдЪреА рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрди рдЖрд╡рд╢реНрдпрдХ рдЫ рднрдиреЗ, рддреНрдпрд╕рдкрдЫрд┐ uri рдЕрдиреБрд░реЛрдзрдорд╛ рдбрд╛рдЗрд░реЗрдХреНрдЯрд░реА (рдкреНрдпрд╛рдХреЗрдЬ) рдХреЛ рдирд╛рдордХреЛ рд╕рд╛рде рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдкрдорд╛ рд╕реНрд▓реНрдпрд╛рд╢ / рд╕рдорд╛рдкреНрдд рд╣реБрдиреЗ рдЙрдкрд╕рд░реНрдЧ рдлрд┐рд▓реНрдб рд╣реБрдиреБрдкрд░реНрдЫред рдЕрдиреНрдпрдерд╛, рдбрд╛рдЗрд░реЗрдХреНрдЯрд░реАрдХреЛ рд╕рд╛рдордЧреНрд░реА рдЕрдиреБрд░реЛрдз рдЧрд░реНрджрд╛ рдЯрдХрд░рд╛рд╡ рд╕рдореНрднрд╡ рдЫ, рдЙрджрд╛рд╣рд░рдгрдХрд╛ рд▓рд╛рдЧрд┐ред рддреНрдпрд╣рд╛рдБ рдбрд╛рдЗрд░реЗрдХреНрдЯрд░реАрд╣рд░реВ рдЫрдиреН aiohttp-рдЕрдиреБрд░реЛрдз рд░ aiohttp-рдЕрдиреБрд░реЛрдзрд╣рд░реВ рд░ рдпрджрд┐ рдЕрдиреБрд░реЛрдз рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдЧрд░реНрджрдЫ /?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 рдХреЛ рд░реВрдкрдорд╛ рдкрдард╛рдЙрдиреБ рд╣реЛ, рдкрд╣рд┐рд▓реЗ рд╕рд╛рдордЧреНрд░реА-рдкреНрд░рдХрд╛рд░ рд╣реЗрдбрд░рд▓рд╛рдИ рдЯреЗрдХреНрд╕реНрдЯ/рдПрдЪрдЯреАрдПрдордПрд▓рд╕рдБрдЧ рдмрджрд▓реЗрд░ред

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="/ne/${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 рдкреНрд░рдпреЛрдЧ рдЧрд░реНрди рд╕рдореНрднрд╡ рдЫред Nginx рдорд╛ auth_request рдирд┐рд░реНрджреЗрд╢рди рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░, рд╣рд╛рдореА рд╕реНрдХреНрд░рд┐рдкреНрдЯрдорд╛ рдПрдХ рдкреНрд░рдХрд╛рд░реНрдп рдХрд▓ рд╕рдорд╛рд╡реЗрд╢ subrequest рдорд╛ рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдбрд╛рдЯрд╛ рдкреБрди: рдирд┐рд░реНрджреЗрд╢рд┐рдд рдЧрд░реНрдиреЗрдЫреМрдВред рд╕реНрдХреНрд░рд┐рдкреНрдЯрд▓реЗ Gitlab url рдорд╛ рдЕрд░реНрдХреЛ subrequest рдЧрд░реНрдиреЗрдЫ рд░ рдпрджрд┐ рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдбрд╛рдЯрд╛ рд╕рд╣реА рд░реВрдкрдорд╛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдЧрд░рд┐рдПрдХреЛ рдерд┐рдпреЛ рднрдиреЗ, Gitlab рд▓реЗ рдХреЛрдб 200 рдлрд░реНрдХрд╛рдЙрдиреЗрдЫ рд░ рдкреНрдпрд╛рдХреЗрдЬрдХреЛ рдЕрдкрд▓реЛрдб/рдбрд╛рдЙрдирд▓реЛрдбрд▓рд╛рдИ рдЕрдиреБрдорддрд┐ рджрд┐рдЗрдиреЗрдЫред рдХрд┐рди рдПрдЙрдЯрд╛ рд╕рдмрдХреНрд╡реЗрд░реА рдкреНрд░рдпреЛрдЧ рдирдЧрд░реНрдиреЗ рд░ рддреБрд░реБрдиреНрддреИ Gitlab рдорд╛ рдбрд╛рдЯрд╛ рдкрдард╛рдЙрдиреЗ? рдХрд┐рдирднрдиреЗ рддреНрдпрд╕реЛ рднрдП рд╣рд╛рдореАрд▓реЗ Nginx рдХрдиреНрдлрд┐рдЧрд░реЗрд╕рди рдлрд╛рдЗрд▓ рд╕рдореНрдкрд╛рджрди рдЧрд░реНрдиреБрдкрд░реНрдиреЗрдЫ рдЬрдм рд╣рд╛рдореА рдкреНрд░рд╛рдзрд┐рдХрд░рдгрдорд╛ рдХреБрдиреИ рдкрдирд┐ рдкрд░рд┐рд╡рд░реНрддрди рдЧрд░реНрдЫреМрдВ, рд░ рдпреЛ рдПрдХ рдХрдард┐рди рдХрд╛рдо рд╣реЛред рд╕рд╛рдереИ, рдпрджрд┐ Kubernetes рд▓реЗ рдкрдвреНрдиреЗ-рдорд╛рддреНрд░ рд░реВрдЯ рдлрд╛рдЗрд▓ рдкреНрд░рдгрд╛рд▓реА рдиреАрддрд┐ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдЫ рднрдиреЗ, рдпрд╕рд▓реЗ nginx.conf рд▓рд╛рдИ configmap рдорд╛рд░реНрдлрдд рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдЧрд░реНрджрд╛ рдЕрдЭ рдЬрдЯрд┐рд▓рддрд╛ рдердкреНрдЫред рд░ рдпреЛ configmap рдорд╛рд░реНрдлрдд Nginx рдХрдиреНрдлрд┐рдЧрд░ рдЧрд░реНрди рдкреВрд░реНрдг рд░реВрдкрдорд╛ рдЕрд╕рдореНрднрд╡ рд╣реБрдиреНрдЫ рдЬрдм рднреЛрд▓реНрдпреБрдорд╣рд░реВ (pvc) рд░ рдкрдвреНрдиреЗ-рдорд╛рддреНрд░ рд░реВрдЯ рдлрд╛рдЗрд▓ рдкреНрд░рдгрд╛рд▓реА (рдпреЛ рдкрдирд┐ рд╣реБрдиреНрдЫ) рдХреЛ рдЬрдбрд╛рди рдирд┐рд╖реЗрдз рдЧрд░реНрдиреЗ рдиреАрддрд┐рд╣рд░реВ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрджрд╛ред

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 = рдЖрд╡рд╢реНрдпрдХ ('aws-sdk') рд░ рддреНрдпрд╣рд╛рдБ S3 рдкреНрд░рдорд╛рдгреАрдХрд░рдг рд╕рдВрдЧ "рдмрд╛рдЗрдХ" рд▓реЗрдЦреНрди рдЖрд╡рд╢реНрдпрдХ рдЫреИрди!

рд╡рд┐рдкрдХреНрд╖рдорд╛ рдЬрд╛рдФрдВ

рдореЗрд░реЛ рд▓рд╛рдЧрд┐, рдмрд╛рд╣реНрдп JS рдореЛрдбреНрдпреБрд▓рд╣рд░реВ рдЖрдпрд╛рдд рдЧрд░реНрди рдЕрд╕рдХреНрд╖рдорддрд╛ рдПрдХ рдЕрдкреНрд░рд┐рдп, рддрд░ рдЕрдкреЗрдХреНрд╖рд┐рдд рд╕реБрд╡рд┐рдзрд╛ рднрдпреЛред рдорд╛рдерд┐рдХреЛ рдЙрджрд╛рд╣рд░рдгрдорд╛ рд╡рд░реНрдгрди рдЧрд░рд┐рдПрдХреЛ рдЖрд╡рд╢реНрдпрдХрддрд╛ ('рдХреНрд░рд┐рдкреНрдЯреЛ') рд╣реЛ рдмрд┐рд▓реНрдб-рдЗрди рдореЛрдбреНрдпреБрд▓рд╣рд░реВ рд░ рддрд┐рдиреАрд╣рд░реВрдХреЛ рд▓рд╛рдЧрд┐ рдорд╛рддреНрд░ рдХрд╛рдо рдЖрд╡рд╢реНрдпрдХ рдЫред рд╕реНрдХреНрд░рд┐рдкреНрдЯрдмрд╛рдЯ рдХреЛрдб рдкреБрди: рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдиреЗ рдХреБрдиреИ рддрд░рд┐рдХрд╛ рдкрдирд┐ рдЫреИрди рд░ рддрдкрд╛рдИрдВрд▓реЗ рдпрд╕рд▓рд╛рдИ рд╡рд┐рднрд┐рдиреНрди рдлрд╛рдЗрд▓рд╣рд░реВрдорд╛ рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдЧрд░реЗрд░ рдЯрд╛рдБрд╕реНрдиреБрдкрд░реНрдЫред рдорд▓рд╛рдИ рдЖрд╢рд╛ рдЫ рдХрд┐ рдПрдХ рджрд┐рди рдпреЛ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рд▓рд╛рдЧреВ рд╣реБрдиреЗрдЫред

Nginx рдорд╛ рд╣рд╛рд▓рдХреЛ рдкрд░рд┐рдпреЛрдЬрдирд╛рдХреЛ рд▓рд╛рдЧрд┐ рд╕рдЩреНрдХреБрдЪрди рдкрдирд┐ рдЕрд╕рдХреНрд╖рдо рд╣реБрдиреБрдкрд░реНрдЫ gzip off;

рдХрд┐рдирднрдиреЗ NJS рдорд╛ рдХреБрдиреИ gzip рдореЛрдбреНрдпреБрд▓ рдЫреИрди рд░ рдпрд╕рд▓рд╛рдИ рдЬрдбрд╛рди рдЧрд░реНрди рдЕрд╕рдореНрднрд╡ рдЫ; рддреНрдпрд╕реИрд▓реЗ, рд╕рдВрдХреБрдЪрд┐рдд рдбрд╛рдЯрд╛рд╕рдБрдЧ рдХрд╛рдо рдЧрд░реНрдиреЗ рдХреБрдиреИ рддрд░рд┐рдХрд╛ рдЫреИрдиред рд╕рд╛рдБрдЪреЛ, рдпреЛ рд╡рд╛рд╕реНрддрд╡рдорд╛ рдпрд╕ рдорд╛рдорд▓рд╛рдХреЛ рд▓рд╛рдЧрд┐ рдорд╛рдЗрдирд╕ рд╣реЛрдЗрдиред рддреНрдпрд╣рд╛рдБ рдзреЗрд░реИ рдкрд╛рда рдЫреИрди, рд░ рд╕реНрдерд╛рдирд╛рдиреНрддрд░рдг рдЧрд░рд┐рдПрдХрд╛ рдлрд╛рдЗрд▓рд╣рд░реВ рдкрд╣рд┐рд▓реЗ рдиреИ рд╕рдВрдХреБрдЪрд┐рдд рдЫрдиреН рд░ рдердк рдХрдореНрдкреНрд░реЗрд╕рдирд▓реЗ рддрд┐рдиреАрд╣рд░реВрд▓рд╛рдИ рдзреЗрд░реИ рдорджреНрджрдд рдЧрд░реНрджреИрдиред рд╕рд╛рдереИ, рдпреЛ рддреНрдпрд╕реНрддреЛ рд▓реЛрдбреЗрдб рд╡рд╛ рдХреНрд░рд┐рдЯрд┐рдХрд▓ рд╕реЗрд╡рд╛ рд╣реЛрдЗрди рдХрд┐ рддрдкрд╛рдИрд▓реЗ рдХреЗрд╣рд┐ рдорд┐рд▓рд┐рд╕реЗрдХреЗрдиреНрдб рдЫрд┐рдЯреЛ рд╕рд╛рдордЧреНрд░реА рдбреЗрд▓рд┐рднрд░ рдЧрд░реНрдирдХреЛ рд▓рд╛рдЧрд┐ рдЪрд┐рдиреНрддрд╛ рд▓рд┐рдиреБ рдкрд░реНрдЫред

рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдбрд┐рдмрдЧ рдЧрд░реНрди рд▓рд╛рдореЛ рд╕рдордп рд▓рд╛рдЧреНрдЫ рд░ error.log рдорд╛ "рдкреНрд░рд┐рдиреНрдЯрд╣рд░реВ" рдорд╛рд░реНрдлрдд рдорд╛рддреНрд░ рд╕рдореНрднрд╡ рдЫред рд╕реЗрдЯ рд▓рдЧрд┐рдЩ рд╕реНрддрд░ рдЬрд╛рдирдХрд╛рд░реА, рдЪреЗрддрд╛рд╡рдиреА рд╡рд╛ рддреНрд░реБрдЯрд┐рдорд╛ рдирд┐рд░реНрднрд░ рдЧрд░реНрджреИ, рдХреНрд░рдорд╢рдГ r.log, r.warn, r.error рдкреНрд░рдпреЛрдЧ рдЧрд░реНрди рд╕рдореНрднрд╡ рдЫред рдо Chrome (v3) рд╡рд╛ njs рдХрдиреНрд╕реЛрд▓ рдЙрдкрдХрд░рдгрдорд╛ рдХреЗрд╣реА рд╕реНрдХреНрд░рд┐рдкреНрдЯрд╣рд░реВ рдбрд┐рдмрдЧ рдЧрд░реНрдиреЗ рдкреНрд░рдпрд╛рд╕ рдЧрд░реНрдЫреБ, рддрд░ рддреНрдпрд╣рд╛рдБ рд╕рдмреИ рдХреБрд░рд╛ рдЬрд╛рдБрдЪ рдЧрд░реНрди рд╕рдХрд┐рдБрджреИрдиред рдХреЛрдб рдбрд┐рдмрдЧ рдЧрд░реНрджрд╛, рдЙрд░реНрдл тАЛтАЛтАЛтАЛрдХрд╛рд░реНрдпрд╛рддреНрдордХ рдкрд░реАрдХреНрд╖рдг, рдЗрддрд┐рд╣рд╛рд╕ рдпрд╕реНрддреЛ рджреЗрдЦрд┐рдиреНрдЫ:

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

рд░ рддреНрдпрд╣рд╛рдБ рдпрд╕реНрддрд╛ рд╕рдпреМрдВ рдХреНрд░рдорд╣рд░реВ рд╣реБрди рд╕рдХреНрдЫрдиреНред

рддрд┐рдиреАрд╣рд░реВрдХрд╛ рд▓рд╛рдЧрд┐ рд╕рдмрдХреНрд╡реЗрд░реАрд╣рд░реВ рд░ рдЪрд░рд╣рд░реВ рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░ рдХреЛрдб рд▓реЗрдЦреНрджрд╛ рдПрдХ рдЬрдЯрд┐рд▓ рдЯреНрдпрд╛рдЩреНрдЧрд▓рдорд╛ рдкрд░рд┐рдгрдд рд╣реБрдиреНрдЫред рдХрд╣рд┐рд▓реЗрдХрд╛рд╣реАрдБ рддрдкрд╛рдИрдВ рдЖрдлреНрдиреЛ рдХреЛрдбрдХреЛ рдХрд╛рд░реНрдпрд╣рд░реВрдХреЛ рдЕрдиреБрдХреНрд░рдо рдкрддреНрддрд╛ рд▓рдЧрд╛рдЙрди рдкреНрд░рдпрд╛рд╕ рдЧрд░реНрджреИ рд╡рд┐рднрд┐рдиреНрди IDE рд╡рд┐рдиреНрдбреЛрд╣рд░реВ рд╡рд░рд┐рдкрд░рд┐ рд╣рддрд╛рд░ рдЧрд░реНрди рдерд╛рд▓реНрдиреБрд╣реБрдиреНрдЫред рдпреЛ рдЧрд╛рд╣реНрд░реЛ рдЫреИрди, рддрд░ рдХрд╣рд┐рд▓реЗрдХрд╛рд╣реАрдБ рдпреЛ рдзреЗрд░реИ рдХрд╖реНрдЯрдкреНрд░рдж рдЫред

ES6 рдХреЛ рд▓рд╛рдЧрд┐ рдХреБрдиреИ рдкреВрд░реНрдг рд╕рдорд░реНрдерди рдЫреИрдиред

рдЕрд░реВ рдХреЗрд╣реА рдХрдордЬреЛрд░реАрд╣рд░реВ рд╣реБрди рд╕рдХреНрдЫрдиреН, рддрд░ рдореИрд▓реЗ рдЕрд░реВ рдХреЗрд╣реА рд╕рд╛рдордирд╛ рдЧрд░реЗрдХреЛ рдЫреИрдиред рдпрджрд┐ рддрдкрд╛рдЗрдБрд╕рдБрдЧ NJS рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░ рдирдХрд╛рд░рд╛рддреНрдордХ рдЕрдиреБрднрд╡ рдЫ рднрдиреЗ рдЬрд╛рдирдХрд╛рд░реА рд╕рд╛рдЭрд╛ рдЧрд░реНрдиреБрд╣реЛрд╕реНред

рдирд┐рд╖реНрдХрд░реНрд╖рдорд╛

NJS рдПрдХ рд╣рд▓реНрдХрд╛ рдЦреБрд▓рд╛ рд╕реНрд░реЛрдд рдЕрдиреБрд╡рд╛рджрдХ рд╣реЛ рдЬрд╕рд▓реЗ рддрдкрд╛рдИрдВрд▓рд╛рдИ Nginx рдорд╛ рд╡рд┐рднрд┐рдиреНрди JavaScript рд╕реНрдХреНрд░рд┐рдкреНрдЯрд╣рд░реВ рд▓рд╛рдЧреВ рдЧрд░реНрди рдЕрдиреБрдорддрд┐ рджрд┐рдиреНрдЫред рдпрд╕рдХреЛ рд╡рд┐рдХрд╛рд╕рдХреЛ рдХреНрд░рдордорд╛, рдкреНрд░рджрд░реНрд╢рдирдорд╛ рдареВрд▓реЛ рдзреНрдпрд╛рди рджрд┐рдЗрдПрдХреЛ рдерд┐рдпреЛред рдирд┐рд╕реНрд╕рдиреНрджреЗрд╣, рддреНрдпрд╣рд╛рдБ рдЕрдЭреИ рдзреЗрд░реИ рд╣рд░рд╛рдЗрд░рд╣реЗрдХреЛ рдЫ, рддрд░ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдПрдХ рд╕рд╛рдиреЛ рдЯреЛрд▓реА рджреНрд╡рд╛рд░рд╛ рд╡рд┐рдХрд╕рд┐рдд рдЧрд░рд┐рдПрдХреЛ рдЫ рд░ рддрд┐рдиреАрд╣рд░реВ рд╕рдХреНрд░рд┐рдп рд░реВрдкрдорд╛ рдирдпрд╛рдБ рд╕реБрд╡рд┐рдзрд╛рд╣рд░реВ рдердкреНрджреИ рд░ рдмрдЧрд╣рд░реВ рдлрд┐рдХреНрд╕ рдЧрд░реНрджреИ рдЫрдиреНред рдорд▓рд╛рдИ рдЖрд╢рд╛ рдЫ рдХрд┐ рдХреБрдиреИ рджрд┐рди NJS рд▓реЗ рддрдкрд╛рдИрдВрд▓рд╛рдИ рдмрд╛рд╣реНрдп рдореЛрдбреНрдпреБрд▓рд╣рд░реВ рдЬрдбрд╛рди рдЧрд░реНрди рдЕрдиреБрдорддрд┐ рджрд┐рдиреЗрдЫ, рдЬрд╕рд▓реЗ Nginx рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рд▓рдЧрднрдЧ рдЕрд╕реАрдорд┐рдд рдмрдирд╛рдЙрдиреЗрдЫред рддрд░ рддреНрдпрд╣рд╛рдБ NGINX рдкреНрд▓рд╕ рдЫ рд░ рд╕рдореНрднрд╡рддрдГ рддреНрдпрд╣рд╛рдБ рдХреБрдиреИ рд╕реБрд╡рд┐рдзрд╛рд╣рд░реВ рд╣реБрдиреЗрдЫреИрдирдиреН!

рд▓реЗрдЦрдХреЛ рд▓рд╛рдЧрд┐ рдкреВрд░реНрдг рдХреЛрдбрдХреЛ рд╕рд╛рде рднрдгреНрдбрд╛рд░

AWS рд╕рд╛рдЗрди v4 рд╕рдорд░реНрдердирдХреЛ рд╕рд╛рде njs-pypi

ngx_http_js_module рдореЛрдбреНрдпреБрд▓рдХреЛ рдирд┐рд░реНрджреЗрд╢рдирд╣рд░реВрдХреЛ рд╡рд┐рд╡рд░рдг

рдЖрдзрд┐рдХрд╛рд░рд┐рдХ NJS рднрдгреНрдбрд╛рд░ ╨╕ рдХрд╛рдЧрдЬрд╛рдд

рджрд┐рдорд┐рддреНрд░реА Volintsev рдмрд╛рдЯ NJS рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдиреЗ рдЙрджрд╛рд╣рд░рдгрд╣рд░реВ

njs - nginx рдорд╛ рдиреЗрдЯрд┐рдн рдЬрд╛рднрд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╕реНрдХреНрд░рд┐рдкреНрдЯрд┐рдЩ / рд╕реЗрдиреНрдЯ рд╣рд╛рдИрд▓реЛрдб++ реирежрезреп рдорд╛ рджрд┐рдорд┐рддреНрд░реА рд╡реЛрд▓реНрдирд┐рднрдХреЛ рднрд╛рд╖рдг

рдЙрддреНрдкрд╛рджрди рдорд╛ NJS / HighLoad++ 2019 рдорд╛ Vasily Soshnikov рджреНрд╡рд╛рд░рд╛ рднрд╛рд╖рдг

AWS рдорд╛ REST рдЕрдиреБрд░реЛрдзрд╣рд░реВ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рд░ рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдЧрд░реНрджреИ

рд╕реНрд░реЛрдд: www.habr.com