Kuv ua kuv tus kheej PyPI repository nrog kev tso cai thiab S3. Ntawm Nginx

Hauv tsab xov xwm no kuv xav qhia kuv cov kev paub dhau los nrog NJS, tus neeg txhais lus JavaScript rau Nginx tsim los ntawm Nginx Inc, piav qhia nws lub peev xwm tseem ceeb uas siv qhov piv txwv tiag tiag. NJS yog ib feem ntawm JavaScript uas tso cai rau koj txuas ntxiv kev ua haujlwm ntawm Nginx. Rau lo lus nug vim li cas koj tus txhais lus??? Dmitry Volyntsev teb kom meej. Hauv luv luv: NJS yog nginx-txoj kev, thiab JavaScript yog qhov ua tau zoo dua, "native" thiab tsis muaj GC, tsis zoo li Lua.

Ntev dhau los…

Ntawm kuv txoj haujlwm kawg, kuv tau txais gitlab nrog ntau cov motley CI / CD cov kav dej nrog docker-compose, dind thiab lwm yam zoo siab, uas tau pauv mus rau kaniko rails. Cov duab uas yav tas los siv hauv CI tau txav mus rau hauv lawv daim ntawv qub. Lawv ua hauj lwm kom zoo mus txog rau hnub thaum peb gitlab IP hloov thiab CI hloov mus ua taub dag. Qhov teeb meem yog tias ib qho ntawm cov duab docker uas koom nrog CI muaj git, uas rub Python modules ntawm ssh. Rau ssh koj xav tau tus yuam sij ntiag tug thiab ... nws nyob hauv daim duab nrog rau paub_hosts. Thiab ib qho CI ua tsis tiav nrog qhov yuam kev pov thawj tseem ceeb vim qhov tsis sib haum xeeb ntawm tus IP tiag tiag thiab ib qho tau teev tseg hauv know_hosts. Ib daim duab tshiab tau sib sau ua ke los ntawm Dockfiles uas twb muaj lawm thiab cov kev xaiv tau ntxiv StrictHostKeyChecking no. Tab sis qhov tsis zoo saj tseem nyob thiab muaj lub siab xav txav cov libs mus rau qhov chaw khaws PyPI ntiag tug. Ib qho ntxiv lawm, tom qab hloov mus rau PyPI ntiag tug, yog qhov yooj yim dua thiab cov lus piav qhia ntawm cov tseev kom muaj.txt

Qhov kev xaiv tau ua lawm, Gentlemen!

Peb khiav txhua yam hauv huab thiab Kubernetes, thiab thaum kawg peb xav tau qhov kev pabcuam me me uas yog lub thawv tsis muaj neeg nyob nrog rau sab nraud. Zoo, txij li thaum peb siv S3, qhov tseem ceeb tau muab rau nws. Thiab, yog tias ua tau, nrog kev lees paub hauv gitlab (koj tuaj yeem ntxiv nws tus kheej yog tias tsim nyog).

Kev tshawb nrhiav sai tau txais ntau qhov txiaj ntsig: s3pypi, pypicloud thiab ib qho kev xaiv nrog "phau ntawv" tsim cov ntaub ntawv html rau turnips. Qhov kev xaiv kawg ploj ntawm nws tus kheej.

s3pypi: Nov yog cli siv S3 hosting. Peb upload cov ntaub ntawv, tsim cov html thiab upload rau tib lub thoob. Haum rau kev siv hauv tsev.

pypicloud: Nws zoo li qhov project nthuav, tab sis tom qab nyeem cov ntaub ntawv kuv poob siab. Txawm hais tias cov ntaub ntawv zoo thiab muaj peev xwm nthuav dav kom haum rau koj cov kev xav tau, qhov tseeb nws tau dhau los ua qhov tsis txaus ntseeg thiab nyuaj rau kev teeb tsa. Kho cov cai kom haum rau koj cov dej num, raws li kev kwv yees thaum lub sijhawm ntawd, yuav siv sijhawm 3-5 hnub. Cov kev pabcuam kuj xav tau ib lub database. Peb tau tso tseg yog tias peb tsis pom lwm yam.

Kev tshawb nrhiav qhov tob ntxiv tau txais ib qho module rau Nginx, ngx_aws_auth. Qhov tshwm sim ntawm nws qhov kev sim yog XML tso tawm hauv qhov browser, uas pom cov ntsiab lus ntawm S3 thoob. Qhov kev cog lus kawg thaum lub sijhawm tshawb nrhiav yog ib xyoos dhau los. Lub repository ntsia tso tseg.

Los ntawm kev mus rau qhov chaw thiab nyeem ntawv PEB-503 Kuv pom tau hais tias XML tuaj yeem hloov mus rau HTML ntawm ya thiab muab rau pip. Tom qab googling me ntsis ntxiv txog Nginx thiab S3, Kuv tuaj hla ib qho piv txwv ntawm kev lees paub hauv S3 sau hauv JS rau Nginx. Yog li kuv tau ntsib NJS.

Ua piv txwv li no, ib teev tom qab kuv pom hauv kuv tus browser tib XML li thaum siv ngx_aws_auth module, tab sis txhua yam twb tau sau rau hauv JS.

Kuv yeej nyiam qhov kev daws teeb meem nginx. Ua ntej, cov ntaub ntawv zoo thiab ntau yam piv txwv, qhov thib ob, peb tau txais tag nrho cov khoom zoo ntawm Nginx rau kev ua haujlwm nrog cov ntaub ntawv (tawm ntawm lub thawv), qhov thib peb, leej twg paub yuav ua li cas sau configs rau Nginx yuav tuaj yeem paub tias yog dab tsi. Minimalism kuj yog ib qho ntxiv rau kuv, piv rau Python lossis Go (yog tias sau los ntawm kos), tsis hais txog nexus.

TL;DR Tom qab 2 hnub, qhov kev sim version ntawm PyPi twb tau siv hauv CI.

Ua li cas nws ua hauj lwm?

Lub module yog loaded rau hauv Nginx ngx_http_js_module, suav nrog hauv daim duab docker official. Peb import peb tsab ntawv siv cov lus qhia js_importrau Nginx configuration. Lub luag haujlwm yog hu los ntawm kev qhia js_content. Cov lus qhia yog siv los teeb tsa cov kev hloov pauv js_set, uas yuav siv sij hawm raws li kev sib cav tsuas yog cov haujlwm tau piav qhia hauv tsab ntawv. Tab sis peb tuaj yeem ua tiav cov lus nug hauv NJS tsuas yog siv Nginx, tsis yog XMLHttpRequest. Txhawm rau ua qhov no, qhov chaw sib thooj yuav tsum tau ntxiv rau Nginx teeb tsa. Thiab tsab ntawv yuav tsum piav qhia txog qhov kev thov rau qhov chaw no. Txhawm rau nkag mus rau ib qho haujlwm los ntawm Nginx config, lub npe ua haujlwm yuav tsum raug xa tawm hauv tsab ntawv nws tus kheej 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}

Thaum thov hauv browser http://localhost:8080/ peb mus rau hauv location /uas cov lus qhia js_content hu ua function request piav nyob rau hauv peb tsab ntawv script.js. Nyob rau hauv lem, nyob rau hauv lub functionality request subquery yog ua rau location = /sub-query, nrog ib txoj kev (hauv qhov piv txwv tam sim no GET) tau los ntawm kev sib cav (r), dhau implicitly thaum lub luag haujlwm no hu ua. Cov lus teb subrequest yuav raug ua tiav hauv txoj haujlwm call_back.

Sim S3

Txhawm rau ua qhov kev thov rau kev khaws cia S3 ntiag tug, peb xav tau:

ACCESS_KEY

SECRET_KEY

S3_BUCKET

Los ntawm txoj kev siv http, hnub tim/lub sij hawm tam sim no, S3_NAME thiab URI, ib hom hlua yog tsim, uas tau kos npe (HMAC_SHA1) siv SECRET_KEY. Tom ntej no yog ib txoj kab zoo li AWS $ACCESS_KEY:$HASH, tuaj yeem siv rau hauv daim ntawv tso cai header. Tib hnub / lub sij hawm uas tau siv los tsim cov hlua hauv cov kauj ruam dhau los yuav tsum tau ntxiv rau hauv header X-amz-date. Hauv code nws zoo li no:

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 authorization example, change to deprecated status)

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}

Me ntsis piav txog _subrequest_uri: qhov no yog qhov sib txawv uas, nyob ntawm qhov pib uri, ua ntawv thov rau S3. Yog tias koj xav tau kom tau txais cov ntsiab lus ntawm "hauv paus", ces koj yuav tsum tsim ib daim ntawv thov uri uas qhia txog qhov delimiter delimiter, uas yuav xa rov qab ib daim ntawv teev npe ntawm tag nrho cov CommonPrefixes xml cov ntsiab lus, sib xws rau cov npe (nyob rau hauv rooj plaub ntawm PyPI, ib daim ntawv teev tag nrho cov pob). Yog tias koj xav tau cov npe ntawm cov ntsiab lus hauv cov npe tshwj xeeb (cov npe ntawm tag nrho cov pob versions), ces qhov kev thov uri yuav tsum muaj cov npe ua ntej nrog lub npe ntawm cov ntawv teev npe (pob khoom) yuav tsum xaus nrog tus lej / . Txwv tsis pub, kev sib tsoo tuaj yeem ua tau thaum thov cov ntsiab lus ntawm cov npe, piv txwv. Muaj cov npe aiohttp-request thiab aiohttp-requests thiab yog tias qhov kev thov qhia meej /?prefix=aiohttp-request, tom qab ntawd cov lus teb yuav muaj cov ntsiab lus ntawm ob lub npe. Yog hais tias muaj ib tug slash ntawm qhov kawg, /?prefix=aiohttp-request/, ces cov lus teb yuav tsuas muaj cov ntaub ntawv yuav tsum tau. Thiab yog hais tias peb thov ib cov ntaub ntawv, ces lub resulting uri yuav tsum tsis txhob txawv los ntawm tus thawj.

Txuag thiab rov pib Nginx. Hauv qhov browser peb nkag mus rau qhov chaw nyob ntawm peb Nginx, qhov tshwm sim ntawm qhov kev thov yuav yog XML, piv txwv li:

Daim ntawv teev npe

<?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>

Los ntawm cov npe ntawm cov npe koj tsuas yog xav tau cov ntsiab lus CommonPrefixes.

Los ntawm kev ntxiv cov npe peb xav tau rau peb qhov chaw nyob hauv browser, peb tseem yuav tau txais nws cov ntsiab lus hauv XML daim ntawv:

Daim ntawv teev cov ntaub ntawv nyob rau hauv ib tug directory

<?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>

Los ntawm cov npe ntawm cov ntaub ntawv peb yuav coj tsuas yog cov ntsiab lus Key.

Txhua yam uas tseem tshuav yog txhawm rau txheeb xyuas qhov tshwm sim XML thiab xa tawm raws li HTML, thawj zaug hloov Cov Ntsiab Lus-Hloov header nrog ntawv nyeem / 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="/hmn/${reValue.groups.v}">${a_text}</a>`);
    }
  }

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

Sim PyPI

Peb xyuas tias tsis muaj dab tsi tawg nyob qhov twg ntawm pob khoom uas paub tias ua haujlwm.

# Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ для тСстов Π½ΠΎΠ²ΠΎΠ΅ ΠΎΠΊΡ€ΡƒΠΆΠ΅Π½ΠΈΠ΅
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

Peb rov qab nrog peb 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

Hauv CI, tsim thiab thauj cov pob zoo li no:

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}"

Kev Txhaum Cai

Hauv Gitlab nws tuaj yeem siv JWT rau kev lees paub / kev tso cai ntawm cov kev pabcuam sab nraud. Siv cov lus qhia auth_request hauv Nginx, peb yuav hloov cov ntaub ntawv pov thawj rau cov lus thov uas muaj cov haujlwm hu hauv tsab ntawv. Tsab ntawv yuav ua lwm qhov kev thov rau Gitlab url thiab yog tias cov ntaub ntawv pov thawj tau teev tseg kom raug, ces Gitlab yuav rov qab code 200 thiab upload / rub tawm ntawm pob yuav raug tso cai. Vim li cas ho tsis siv ib qho lus nug thiab xa cov ntaub ntawv tam sim ntawd rau Gitlab? Vim tias tom qab ntawd peb yuav tau hloov kho Nginx teeb tsa cov ntaub ntawv txhua zaus peb hloov pauv hauv kev tso cai, thiab qhov no yog txoj haujlwm nyuaj heev. Tsis tas li ntawd, yog Kubernetes siv txoj cai ntawm kev nyeem ntawv nkaus xwb hauv paus, ces qhov no ntxiv qhov nyuaj dua thaum hloov nginx.conf ntawm configmap. Thiab nws yuav tsis yooj yim sua kom teeb tsa Nginx ntawm configmap thaum tib lub sijhawm siv cov cai txwv kev sib txuas ntawm cov ntim (pvc) thiab nyeem nkaus xwb hauv paus filesystem (qhov no kuj tshwm sim).

Siv NJS nruab nrab, peb tau txais lub sijhawm los hloov cov kev txwv tsis pub muaj nyob rau hauv nginx config siv cov kev hloov pauv ib puag ncig thiab ua qee qhov kev kuaj xyuas hauv tsab ntawv (piv txwv li, ib qho tsis raug teev tseg 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}

Feem ntau yuav lo lus nug yog brewing: -Vim li cas ho tsis siv npaj-ua modules? Txhua yam twb ua tiav lawm! Piv txwv li, var AWS = require('aws-sdk') thiab tsis tas yuav sau "tsheb tuam" nrog S3 authentication!

Cia peb mus rau qhov cons

Rau kuv, qhov tsis muaj peev xwm ntawm cov khoom siv sab nraud JS tau dhau los ua qhov tsis txaus siab, tab sis xav tau feature. Piav hauv qhov piv txwv saum toj no xav tau ('crypto') yog built-in modules thiab tsuas yog ua haujlwm rau lawv xwb. Kuj tsis muaj txoj hauv kev los rov siv cov lej los ntawm cov ntawv sau thiab koj yuav tsum luam thiab muab tso rau hauv cov ntaub ntawv sib txawv. Kuv vam tias muaj ib hnub no functionality yuav raug siv.

Compression kuj tseem yuav raug kaw rau qhov project tam sim no hauv Nginx gzip off;

Vim tias tsis muaj gzip module hauv NJS thiab nws tsis tuaj yeem txuas nws; yog li ntawd, tsis muaj txoj hauv kev los ua haujlwm nrog cov ntaub ntawv compressed. Muaj tseeb tiag, qhov no tsis yog qhov rho tawm tiag tiag rau rooj plaub no. Tsis muaj ntau cov ntawv nyeem, thiab cov ntaub ntawv hloov pauv twb tau compressed thiab compression ntxiv yuav tsis pab lawv ntau. Tsis tas li, qhov no tsis yog qhov kev pabcuam thauj khoom lossis tseem ceeb uas koj yuav tsum thab nrog xa cov ntsiab lus ob peb milliseconds sai dua.

Kev debugging tsab ntawv yuav siv sij hawm ntev thiab tsuas yog ua tau los ntawm "prints" hauv error.log. Nyob ntawm seb cov ntaub ntawv teev tseg theem, ceeb toom lossis yuam kev, nws tuaj yeem siv 3 txoj hauv kev r.log, r.warn, r.error feem. Kuv sim ua kom debug qee cov ntawv sau hauv Chrome (v8) lossis cov cuab yeej njs console, tab sis tsis yog txhua yam tuaj yeem tshawb xyuas muaj. Thaum debugging code, aka functional testing, keeb kwm zoo li no:

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

thiab tuaj yeem muaj ntau pua qhov sib lawv liag.

Kev sau cov lej siv cov lus nug thiab cov hloov pauv rau lawv hloov mus rau hauv tangled tangle. Qee lub sij hawm koj pib rushing nyob ib ncig ntawm IDE qhov rais sib txawv sim los txiav txim seb qhov sib lawv liag ntawm koj cov cai. Nws tsis nyuaj, tab sis qee zaum nws nyuaj heev.

Tsis muaj kev txhawb nqa tag nrho rau ES6.

Tej zaum yuav muaj qee qhov tsis txaus, tab sis kuv tsis tau ntsib lwm yam. Qhia tawm cov ntaub ntawv yog tias koj muaj kev tsis zoo siv NJS.

xaus

NJS yog ib tus neeg txhais lus qhib qhib uas tso cai rau koj los siv ntau yam JavaScript scripts hauv Nginx. Thaum nws txoj kev loj hlob, kev saib xyuas zoo tau them rau kev ua haujlwm. Tau kawg, tseem muaj ntau qhov ploj lawm, tab sis qhov project tab tom tsim los ntawm pab pawg me thiab lawv nquag ntxiv cov yam ntxwv tshiab thiab kho cov kab. Kuv vam tias muaj ib hnub NJS yuav tso cai rau koj los txuas cov modules sab nraud, uas yuav ua rau Nginx functionality yuav luag tsis txwv. Tab sis muaj NGINX Plus thiab feem ntau yuav tsis muaj cov yam ntxwv!

Repository nrog tag nrho cov cai rau kab lus

njs-pypi with AWS Sign v4 support

Kev piav qhia ntawm cov lus qhia ntawm ngx_http_js_module module

Official NJS repository ΠΈ cov ntaub ntawv

Piv txwv ntawm kev siv NJS los ntawm Dmitry Volintsev

njs - haiv JavaScript scripting hauv nginx / Hais lus los ntawm Dmitry Volnyev ntawm Saint HighLoad++ 2019

NJS hauv kev tsim khoom / Hais lus los ntawm Vasily Soshnikov ntawm HighLoad++ 2019

Kos npe thiab lees paub REST thov hauv AWS

Tau qhov twg los: www.hab.com