ما د اختیار او S3 سره خپل د PyPI ذخیره جوړه کړه. په Nginx کې

پدې مقاله کې زه غواړم خپله تجربه د NJS سره شریکه کړم، د Nginx لپاره د جاواسکریپټ ژباړونکي د Nginx Inc لخوا رامینځته شوی، د اصلي مثال په کارولو سره د هغې اصلي وړتیاوې بیانوي. NJS د جاواسکریپټ فرعي سیټ دی چې تاسو ته اجازه درکوي د Nginx فعالیت وغزوي. پوښتنې ته ولې ستا خپل ترجمان؟؟؟ دیمتري Volyntsev په تفصیل سره ځواب ورکړ. په لنډه توګه: NJS د نګینکس لاره ده، او جاواسکریپټ ډیر پرمختللی دی، "اصلي" او د GC پرته، د لوا برعکس.

ډیر وخت دمخه…

زما په وروستي دنده کې، ما د یو شمیر موټلي CI/CD پایپ لاینونو سره د ډاکر-کمپوز، ډینډ او نورو خوښیو سره ګیټلاب په میراث ترلاسه کړ، کوم چې د کانیکو ریلونو ته لیږدول شوي. هغه انځورونه چې پخوا په CI کې کارول شوي وو په خپل اصلي بڼه کې لیږدول شوي. دوی تر هغه ورځې پورې په سمه توګه کار کاوه کله چې زموږ ګیټلاب IP بدل شو او CI په کدو بدل شو. ستونزه دا وه چې یو د ډاکر عکسونو څخه چې په CI کې یې برخه اخیستې وه git درلود ، کوم چې د Python ماډلونه د ssh له لارې راوباسي. د ssh لپاره تاسو شخصي کیلي ته اړتیا لرئ او ... دا د پیژندل شوي_هوسټ سره په عکس کې و. او کوم CI د اصلي تایید کولو غلطۍ سره ناکام شو د اصلي IP او په پیژندل شوي_hosts کې مشخص شوي یو تر مینځ د توپیر له امله. یو نوی عکس په چټکۍ سره د موجوده ډاک فایلونو څخه راټول شو او اختیار اضافه شو StrictHostKeyChecking no. مګر بد خوند پاتې شو او لیبونه د PyPI شخصي ذخیره ته لیږدولو لیوالتیا وه. یو اضافي بونس، د شخصي PyPI ته د بدلولو وروسته، یو ساده پایپ لاین او د اړتیاو نورمال توضیحات وو.txt

انتخاب شوی دی، ښاغلو!

موږ هرڅه په بادلونو او کبرنیټس کې پرمخ وړو، او په پای کې موږ غوښتل یو کوچنی خدمت ترلاسه کړو چې د بهرني ذخیره کولو سره بې ریاسته کانتینر و. ښه، ځکه چې موږ S3 کاروو، لومړیتوب دې ته ورکړل شوی و. او ، که امکان ولري ، په ګیټلاب کې د تصدیق سره (تاسو کولی شئ دا پخپله اضافه کړئ که اړتیا وي).

ګړندي لټون ډیری پایلې ترلاسه کړې: s3pypi، pypicloud او د شلغمونو لپاره د html فایلونو "د لاسي" جوړولو سره یو اختیار. وروستی اختیار پخپله ورک شو.

s3pypi: دا د S3 کوربه کولو کارولو لپاره کلی دی. موږ فایلونه اپلوډ کوو، html پیدا کوو او ورته بالټ ته یې پورته کوو. د کور کارولو لپاره مناسب.

pypicloud: دا د یوې په زړه پورې پروژې په څیر بریښي ، مګر د اسنادو لوستلو وروسته زه مایوسه شوم. د ښه اسنادو او ستاسو د اړتیاو سره سم د پراخولو وړتیا سره سره، په حقیقت کې دا بې ځایه او تنظیم کول ستونزمن و. ستاسو د دندو سره سم د کوډ اصلاح کول، د هغه وخت د اټکلونو سره سم، به 3-5 ورځې وخت ونیسي. خدمت هم ډیټابیس ته اړتیا لري. موږ یې پریښودل که چیرې موږ نور څه ونه موندلو.

یو ډیر ژور لټون د Nginx، ngx_aws_auth لپاره یو ماډل ترلاسه کړ. د هغه د ازموینې پایله په براوزر کې ښودل شوې XML وه، کوم چې د S3 بالټ مینځپانګې ښودلې. د لټون په وخت کې وروستۍ ژمنه یو کال دمخه وه. ذخیره ورکه ښکاریده.

سرچینې ته د تګ او لوستلو له لارې PEP-503 ما پوهیده چې XML په الوتنه کې HTML ته بدل کیدی شي او پایپ ته ورکړل شي. د نګینکس او S3 په اړه یو څه نور ګوګل کولو وروسته ، زه په S3 کې د تصدیق مثال په JS کې د Nginx لپاره لیکل شوی. په دې توګه ما د NJS سره ولیدل.

د دې مثال په توګه اخیستل، یو ساعت وروسته ما په خپل براوزر کې ورته XML ولید لکه څنګه چې د ngx_aws_auth ماډل کارول، مګر هرڅه دمخه په JS کې لیکل شوي و.

ما واقعیا د نګینکس حل خوښ کړ. لومړی ، ښه اسناد او ډیری مثالونه ، دوهم ، موږ د فایلونو سره کار کولو لپاره د نګینکس ټولې ښېګڼې ترلاسه کوو (د بکس څخه بهر) ، دریم ، هرڅوک چې پوهیږي چې څنګه د نګینکس لپاره تشکیلات ولیکئ هغه به وکولی شي معلومه کړي چې څه شی دی. Minimalism زما لپاره هم یو پلس دی، د Python یا Go په پرتله (که له سکریچ څخه لیکل شوی وي)، نه د Nexus ذکر کول.

TL؛ DR د 2 ورځو وروسته، د PyPi ازموینې نسخه دمخه په CI کې کارول شوې وه.

دا څنګه کار کوي؟

ماډل په Nginx کې بار شوی ngx_http_js_module، په رسمي ډاکر عکس کې شامل دی. موږ د لارښود په کارولو سره زموږ سکریپټ واردوو js_importد Nginx ترتیب ته. فعالیت د لارښود لخوا ویل کیږي js_content. لارښود د متغیرونو تنظیم کولو لپاره کارول کیږي js_set، کوم چې د دلیل په توګه یوازې هغه فعالیت اخلي چې په سکریپټ کې بیان شوی. مګر موږ کولی شو په NJS کې فرعي پوښتنې یوازې د Nginx په کارولو سره اجرا کړو، نه د XMLHttpRequest. د دې کولو لپاره، اړونده ځای باید د 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، یو ځانګړی ډول تار تولید شوی، کوم چې د 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-request او aiohttp-requests او که غوښتنه مشخصه کړي /?prefix=aiohttp-requestبیا ځواب به د دواړو لارښودونو مینځپانګه ولري. که په پای کې سلیش وي، /?prefix=aiohttp-request/، بیا ځواب به یوازې اړین لارښود ولري. او که موږ د دوتنې غوښتنه وکړو، نو پایله شوې uri باید د اصلي څخه توپیر ونلري.

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 په توګه یې لیږل کیږي، لومړی یې د متن/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="/ps/${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 لارښود په کارولو سره ، موږ به د تصدیق ډاټا یوې فرعي غوښتنې ته واړوو چې په سکریپټ کې د فنکشن کال لري. سکریپټ به د ګیټلاب یو آر ایل ته بل فرعي غوښتنه وکړي او که چیرې د تصدیق کولو ډاټا په سمه توګه مشخص شوې وي ، نو ګیټلاب به کوډ 200 بیرته راولي او د کڅوړې اپلوډ / ډاونلوډ ته به اجازه ورکړل شي. ولې یوه فرعي پوښتنه نه کاروئ او سمدلاسه ډیټا ګیټلاب ته واستوئ؟ ځکه چې بیا به موږ هرکله چې موږ په واک کې کوم بدلون راوړو د نګینکس ترتیب کولو فایل ترمیم کړو ، او دا یو ډیر ستړیدونکی کار دی. همچنان ، که Kubernetes یوازې د لوستلو لپاره د روټ فایل سیسټم پالیسي کاروي ، نو دا نور پیچلتیا زیاتوي کله چې د nginx.conf د configmap له لارې ځای په ځای کول. او دا د configmap له لارې د نګینکس تنظیم کول په بشپړ ډول ناممکن کیږي پداسې حال کې چې په ورته وخت کې د حجمونو (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 ماډلونو واردولو کې ناتوانۍ یو ناخوښه، مګر تمه کیده ځانګړتیا شوه. په پورته مثال کې تشریح شوي اړتیا ('crypto') ده جوړ شوي ماډلونه او یوازې د دوی لپاره کار ته اړتیا لري. د سکریپټونو څخه د کوډ بیا کارولو لپاره هیڅ لاره هم شتون نلري او تاسو باید دا په مختلف فایلونو کې کاپي او پیسټ کړئ. زه امید لرم چې یوه ورځ به دا فعالیت پلي شي.

کمپریشن باید په نینګکس کې د اوسني پروژې لپاره هم غیر فعال شي gzip off;

ځکه چې په NJS کې د gzip ماډل شتون نلري او د دې سره نښلول ناممکن دي؛ له همدې امله د کمپریس شوي ډیټا سره د کار کولو کومه لاره نشته. ریښتیا، دا واقعیا د دې قضیې لپاره منفي ندی. دلته ډیر متن شتون نلري ، او لیږدول شوي فایلونه دمخه کمپریس شوي او اضافي کمپریشن به دوی سره ډیره مرسته ونکړي. همچنان ، دا دومره بار شوی یا مهم خدمت ندی چې تاسو باید د څو ملی ثانیو ګړندي مینځپانګې وړاندې کولو کې زحمت وکړئ.

د سکریپټ ډیبګ کول ډیر وخت نیسي او یوازې په error.log کې د "پرنټ" له لارې امکان لري. د ټاکل شوي لاګنګ کچې معلوماتو پورې اړه لري، خبرداری یا خطا، دا ممکنه ده چې په ترتیب سره 3 میتودونه r.log، r.warn، r.error وکاروئ. زه هڅه کوم چې په کروم (v8) یا د njs کنسول وسیلې کې ځینې سکریپټونه ډیبګ کړم ، مګر هرڅه هلته نشي چیک کیدی. کله چې د کوډ ډیبګ کول، عرف فعال ازموینه، تاریخ یو څه داسې ښکاري:

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

او کیدای شي په سلګونو داسې سلسلې وي.

د دوی لپاره د فرعي پوښتنو او متغیرونو په کارولو سره د کوډ لیکل په یو پیچلي ټنګ کې بدلیږي. ځینې ​​​​وختونه تاسو د مختلف IDE کړکۍ شاوخوا ګړندي پیل کوئ چې هڅه وکړئ ستاسو د کوډ د عملونو ترتیب معلوم کړئ. دا ستونزمن نه دی، مګر ځینې وختونه دا خورا ځورونکي وي.

د ES6 لپاره بشپړ ملاتړ شتون نلري.

کېدای شي ځینې نورې نیمګړتیاوې هم وي، مګر ما نور څه نه دي لیدلي. معلومات شریک کړئ که تاسو د NJS کارولو منفي تجربه لرئ.

پایلې

NJS یو د سپک وزن خلاص سرچینې ژباړونکی دی چې تاسو ته اجازه درکوي په نګینکس کې مختلف جاواسکریپټ سکریپټونه پلي کړئ. د هغې د پراختیا په جریان کې، فعالیت ته ډیره پاملرنه شوې. البته ، لاهم ډیر څه ورک دي ، مګر پروژه د کوچني ټیم لخوا رامینځته کیږي او دوی په فعاله توګه نوي ځانګړتیاوې اضافه کوي او کیګونه حل کوي. زه امید لرم چې یوه ورځ NJS به تاسو ته اجازه درکړي چې بهرني ماډلونه وصل کړئ ، کوم چې به د Nginx فعالیت تقریبا لامحدود کړي. مګر د NGINX پلس شتون لري او ډیری احتمال به هیڅ ځانګړتیاوې نه وي!

د مقالې لپاره د بشپړ کوډ سره ذخیره

njs-pypi د AWS نښه v4 ملاتړ سره

د ngx_http_js_module ماډل د لارښوونو توضیحات

د NJS رسمي ذخیره и اسناد

د دمیتري Volintsev څخه د NJS کارولو مثالونه

njs - په nginx کې اصلي جاواسکریپټ سکریپټ / په سینټ های لوډ++ 2019 کې د دیمیتري والنییف وینا

NJS په تولید کې / په HighLoad++ 2019 کې د واسیلي سوشنیکوف وینا

په AWS کې د REST غوښتنو لاسلیک کول او تصدیق کول

سرچینه: www.habr.com