Rinn mi an stòr PyPI agam fhìn le cead agus S3. Air Nginx

San artaigil seo bu mhath leam an t-eòlas agam a bhith ag obair le NJS, eadar-theangair JavaScript airson Nginx a leasachadh le Nginx Inc a cho-roinn, a’ toirt cunntas air na prìomh chomasan aige a’ cleachdadh fìor eisimpleir. Tha NJS na fho-sheata de JavaScript a leigeas leat comas-gnìomh Nginx a leudachadh. Chun na ceist carson a tha an t-eadar-theangair agad fhèin??? Fhreagair Dmitry Volyntsev gu mionaideach. Ann an ùine ghoirid: tha NJS nginx-way, agus tha JavaScript nas adhartaiche, “dùthchasach” agus às aonais GC, eu-coltach ri Lua.

O chionn ùine mhòr…

Aig an obair mu dheireadh agam, shealbhaich mi gitlab le grunn phìoban motley CI / CD le docker-compose, dind agus toileachasan eile, a chaidh a ghluasad gu rèilichean kaniko. Chaidh na h-ìomhaighean a chaidh a chleachdadh roimhe seo ann an CI a ghluasad anns a’ chruth thùsail aca. Dh'obraich iad gu ceart gus an latha nuair a dh'atharraich ar gitlab IP agus thionndaidh CI gu bhith na phumpag. B ’e an duilgheadas a bh’ ann gun robh git aig aon de na h-ìomhaighean docker a ghabh pàirt ann an CI, a tharraing modalan Python tro ssh. Airson ssh feumaidh tu iuchair phrìobhaideach agus ... bha e san ìomhaigh còmhla ri known_hosts. Agus dh’ fhàillig CI sam bith le prìomh mhearachd dearbhaidh mar thoradh air mì-chothromachadh eadar an fhìor IP agus am fear a chaidh a shònrachadh ann an known_hosts. Chaidh ìomhaigh ùr a chruinneachadh gu sgiobalta bho na Dockfiles a th’ ann agus chaidh an roghainn a chuir ris StrictHostKeyChecking no. Ach dh'fhuirich an droch bhlas agus bha miann ann na libs a ghluasad gu ionad prìobhaideach PyPI. B’ e buannachd a bharrachd, às deidh atharrachadh gu PyPI prìobhaideach, loidhne-phìoban nas sìmplidh agus tuairisgeul àbhaisteach air riatanasan.txt

Tha an roghainn air a dhèanamh, A dhaoine uaisle!

Bidh sinn a 'ruith a h-uile càil anns na sgòthan agus Kubernetes, agus aig a' cheann thall bha sinn airson seirbheis bheag fhaighinn a bha na ghobhar gun stàit le stòradh a-muigh. Uill, leis gu bheil sinn a’ cleachdadh S3, chaidh prìomhachas a thoirt dha. Agus, ma ghabhas e dèanamh, le dearbhadh ann an gitlab (faodaidh tu fhèin a chur ris ma tha sin riatanach).

Fhuair rannsachadh sgiobalta grunn thoraidhean: s3pypi, pypicloud agus roghainn le cruthachadh “le làimh” de fhaidhlichean html airson snèapan. Chaidh an roghainn mu dheireadh à sealladh leis fhèin.

s3pypi: Seo cli airson a bhith a’ cleachdadh aoigheachd S3. Bidh sinn a’ luchdachadh suas na faidhlichean, a’ gineadh an html agus ga luchdachadh suas chun aon bhucaid. Freagarrach airson cleachdadh dachaigh.

pypicloud: Bha e coltach gur e pròiseact inntinneach a bh’ ann, ach às deidh dhomh na sgrìobhainnean a leughadh bha mi tàmailteach. A dh 'aindeoin deagh sgrìobhainnean agus an comas leudachadh a rèir do fheumalachdan, ann an da-rìribh bha e gun fheum agus duilich a rèiteachadh. Bhiodh ceartachadh a’ chòd a rèir do ghnìomhan, a rèir tuairmsean aig an àm sin, air 3-5 latha a thoirt. Feumaidh an t-seirbheis stòr-dàta cuideachd. Dh’fhàg sinn e gun fhios nach lorg sinn dad eile.

Thug sgrùdadh nas doimhne modal airson Nginx, ngx_aws_auth. B’ e toradh an deuchainn aige XML air a thaisbeanadh sa bhrobhsair, a sheall susbaint a’ bhucaid S3. Bha an gealladh mu dheireadh aig àm an sgrùdaidh bliadhna air ais. Bha coltas gu robh an stòr air a thrèigsinn.

Le bhith a’ dol chun stòr agus a’ leughadh PEP-503 Thuig mi gum faodar XML a thionndadh gu HTML air an itealan agus a thoirt dha pip. Às deidh dhomh beagan a bharrachd a dhèanamh mu Nginx agus S3, thàinig mi tarsainn air eisimpleir de dhearbhadh ann an S3 sgrìobhte ann an JS airson Nginx. Sin mar a choinnich mi ri NJS.

A’ gabhail an eisimpleir seo mar bhunait, uair a-thìde às deidh sin chunnaic mi anns a’ bhrobhsair agam an aon XML ri nuair a bha mi a’ cleachdadh modal ngx_aws_auth, ach bha a h-uile dad sgrìobhte ann an JS mu thràth.

Chòrd am fuasgladh nginx rium gu mòr. An toiseach, deagh sgrìobhainnean agus mòran eisimpleirean, san dàrna àite, gheibh sinn a h-uile rud math bho Nginx airson a bhith ag obair le faidhlichean (a-mach às a ’bhogsa), san treas àite, bidh e comasach dha neach sam bith aig a bheil fios mar a sgrìobhas iad configs airson Nginx faighinn a-mach dè a th’ ann. Tha minimalism cuideachd na bhuannachd dhomh, an taca ri Python no Go (ma tha e sgrìobhte bhon toiseach), gun luaidh air nexus.

TL; DR Às deidh 2 latha, chaidh an dreach deuchainn de PyPi a chleachdadh mu thràth ann an CI.

Ciamar a dh'obraicheas e?

Tha am modal air a luchdachadh a-steach do Nginx ngx_http_js_module, air a ghabhail a-steach san ìomhaigh oifigeil docker. Bidh sinn a’ toirt a-steach an sgriobt againn a’ cleachdadh an stiùiridh js_importgu rèiteachadh Nginx. Tha an gnìomh air a ghairm le stiùireadh js_content. Tha an stiùireadh air a chleachdadh gus caochladairean a shuidheachadh js_set, a tha a’ gabhail mar argamaid a-mhàin an gnìomh a tha air a mhìneachadh san sgriobt. Ach is urrainn dhuinn subqueries a chuir an gnìomh ann an NJS a-mhàin a’ cleachdadh Nginx, chan e XMLHttpRequest sam bith. Gus seo a dhèanamh, feumar an t-àite co-fhreagarrach a chur ri rèiteachadh Nginx. Agus feumaidh an sgriobt cunntas a thoirt air fo-iarrtas chun an àite seo. Gus faighinn gu gnìomh bho config Nginx, feumaidh an t-ainm gnìomh a bhith air a thoirt a-mach san sgriobt fhèin 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}

Nuair a thèid iarraidh sa bhrobhsair http://localhost:8080/ sinn a steach location /anns a bheil an stiuradh js_content gairm gnìomh request air a mhìneachadh anns an sgriobtar againn script.js. Ann an tionndadh, ann an gnìomh request tha subquery air a dhèanamh gu location = /sub-query, le modh (san eisimpleir làithreach GET) a gheibhear bhon argamaid (r), air a dhol seachad gu soilleir nuair a chanar ris a’ ghnìomh seo. Thèid am freagairt fo-iarrtas a phròiseasadh san ghnìomh call_back.

A' feuchainn ri S3

Gus iarrtas a dhèanamh gu stòradh prìobhaideach S3, feumaidh sinn:

ACCESS_KEY

SECRET_KEY

S3_BUCKET

Bhon dòigh http a chleachdar, an ceann-latha/àm làithreach, S3_NAME agus URI, thèid seòrsa sònraichte de shreang a chruthachadh, a tha air a shoidhnigeadh (HMAC_SHA1) a’ cleachdadh SECRET_KEY. An ath rud tha loidhne coltach ris AWS $ACCESS_KEY:$HASH, faodar a chleachdadh anns a’ cheann ùghdarrais. Feumar an aon cheann-latha/ùine a chaidh a chleachdadh gus an t-sreang a ghineadh sa cheum roimhe a chur ris a’ bhann-cinn X-amz-date. Ann an còd tha e coltach mar seo:

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(eisimpleir ceadachaidh AWS Sign v2, air atharrachadh gu inbhe nach deach a mholadh)

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}

Beagan mìneachaidh mu dheidhinn _subrequest_uri: is e caochladair a tha seo a tha, a rèir a’ chiad uri, a’ dèanamh iarrtas gu S3. Ma dh'fheumas tu susbaint an "root" fhaighinn, feumaidh tu iarrtas uri a chruthachadh a 'sealltainn an delimiter delimiter, a thilleas liosta de na h-eileamaidean xml CommonPrefixes gu lèir, a rèir clàran (a thaobh PyPI, liosta de na pacaidean uile). Ma dh’ fheumas tu liosta de shusbaint fhaighinn ann an eòlaire sònraichte (liosta de gach dreach pacaid), feumaidh raon ro-leasachan a bhith san iarrtas uri le ainm an eòlaire (pasgan) gu riatanach a’ crìochnachadh le slash / . Rud eile, bidh tubaistean comasach nuair a dh’ iarrar susbaint eòlaire, mar eisimpleir. Tha clàran ann aiohttp-request agus aiohttp-requests agus ma tha an t-iarrtas a’ sònrachadh /?prefix=aiohttp-request, an uairsin bidh susbaint an dà chlàr anns an fhreagairt. Ma tha slais aig an deireadh, /?prefix=aiohttp-request/, an uairsin cha bhi anns an fhreagairt ach an eòlaire a tha a dhìth. Agus ma dh’ iarras sinn faidhle, cha bu chòir don uri a thig às a sin a bhith eadar-dhealaichte bhon fhear thùsail.

Sàbhail agus ath-thòiseachadh Nginx. Anns a’ bhrobhsair cuiridh sinn a-steach seòladh ar Nginx, is e toradh an iarrtais XML, mar eisimpleir:

Liosta de chlàran

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

Bhon liosta de chlàran cha bhith feum agad ach air na h-eileamaidean CommonPrefixes.

Le bhith a’ cur an eòlaire a dh’ fheumas sinn ris an t-seòladh againn sa bhrobhsair, gheibh sinn cuideachd na tha ann ann an cruth XML:

Liosta de na faidhlichean ann an eòlaire

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

Bhon liosta fhaidhlichean cha toir sinn ach eileamaidean Key.

Chan eil air fhàgail ach an XML a thig às a pharsadh agus a chuir a-mach mar HTML, às deidh dhut teacsa / html a chuir an àite bann-cinn Content-Type.

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="/gd/${reValue.groups.v}">${a_text}</a>`);
    }
  }

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

A 'feuchainn ri PyPI

Bidh sinn a’ dèanamh cinnteach nach bi dad a’ briseadh an àite sam bith air pacaidean a tha fios gu bheil iad ag obair.

# Создаем для тестов новое окружение
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

Bidh sinn a-rithist le ar bilean.

# Создаем для тестов новое окружение
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

Ann an CI, tha cruthachadh agus luchdachadh pasgan a’ coimhead mar seo:

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

Dearbhadh

Ann an Gitlab tha e comasach JWT a chleachdadh airson seirbheisean taobh a-muigh a dhearbhadh / ùghdarrasachadh. A’ cleachdadh an stiùiridh auth_request ann an Nginx, bidh sinn ag ath-stiùireadh an dàta dearbhaidh gu fo-iarrtas anns a bheil gairm gnìomh san sgriobt. Nì an sgriobt fo-iarrtas eile don url Gitlab agus ma chaidh an dàta dearbhaidh a shònrachadh gu ceart, an uairsin tillidh Gitlab còd 200 agus bidh cead luchdachadh suas / luchdachadh sìos a’ phacaid. Carson nach cleachd thu aon subquery agus an dàta a chuir gu Gitlab sa bhad? Air sgàth sin feumaidh sinn am faidhle rèiteachaidh Nginx a dheasachadh a h-uile uair a nì sinn atharrachaidhean sam bith ann an ùghdarras, agus is e obair caran duilich a tha seo. Cuideachd, ma bhios Kubernetes a’ cleachdadh poileasaidh siostam faidhle freumha a tha ri leughadh a-mhàin, cuiridh seo eadhon nas iom-fhillteachd nuair a thèid a chur an àite nginx.conf tro configmap. Agus bidh e gu tur eu-comasach Nginx a rèiteachadh tro configmap agus aig an aon àm a’ cleachdadh phoileasaidhean a tha a’ toirmeasg ceangal leabhraichean (pvc) agus siostam freumhaich leughaidh a-mhàin (bidh seo a’ tachairt cuideachd).

A’ cleachdadh an eadar-mheadhanach NJS, gheibh sinn an cothrom na paramadairean ainmichte ann an config nginx atharrachadh a’ cleachdadh caochladairean àrainneachd agus cuid de sgrùdaidhean a dhèanamh san sgriobt (mar eisimpleir, URL a chaidh a shònrachadh gu ceàrr).

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}

Is coltaiche gur e grùdaireachd a’ cheist: -Carson nach cleachd thu modalan deiseil? Tha a h-uile càil air a dhèanamh ann mu thràth! Mar eisimpleir, var AWS = feum ('aws-sdk') agus chan eil feum air "baidhsagal" a sgrìobhadh le dearbhadh S3!

Gluaisidh sinn air adhart gu na h-eas-bhuannachdan

Dhòmhsa, dh’ fhàs neo-chomas modalan JS taobh a-muigh a thoirt a-steach na fheart mì-thlachdmhor, ach ris an robh dùil. Air a mhìneachadh san eisimpleir gu h-àrd tha feum ('crypto'). modalan togail a-steach agus a dh' fheumas oibribh a mhàin air an son. Chan eil dòigh ann cuideachd còd ath-chleachdadh bho sgriobtaichean agus feumaidh tu a chopaigeadh agus a phasgadh a-steach do dhiofar fhaidhlichean. Tha mi an dòchas gum bi an gnìomh seo air a chuir an gnìomh uaireigin.

Feumaidh teannachadh cuideachd a bhith ciorramach airson a’ phròiseict gnàthach ann an Nginx gzip off;

Leis nach eil modal gzip ann an NJS agus gu bheil e do-dhèanta a cheangal; mar sin, chan eil dòigh ann a bhith ag obair le dàta teann. Gu dearbh, chan e fìor dhuilgheadas a tha seo airson a 'chùis seo. Chan eil mòran teacsa ann, agus tha na faidhlichean a chaidh a ghluasad mar-thà air an teannachadh agus cha chuidich teannachadh a bharrachd iad gu mòr. Cuideachd, chan e seirbheis cho luchdaichte no cho èiginneach a tha seo gum feum thu dragh a chuir air lìbhrigeadh susbaint beagan mhilleanan diog nas luaithe.

Bheir dì-bhugachadh an sgriobt ùine mhòr agus chan eil e comasach ach tro “clò-bhualaidhean” ann an error.log. A rèir an fhiosrachaidh ìre logaidh suidhichte, rabhadh no mearachd, tha e comasach 3 dòighean a chleachdadh r.log, r.warn, r.error fa leth. Feuchaidh mi ri cuid de sgriobtaichean a dhì-cheadachadh ann an Chrome (v8) no an inneal tòcan njs, ach chan urrainnear a h-uile dad a sgrùdadh an sin. Nuair a bhios tu a’ dì-bhugachadh còd, ris an canar deuchainn gnìomh, tha eachdraidh a’ coimhead rudeigin mar seo:

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

agus faodaidh na ceudan de shreathan mar sin a bhith ann.

Bidh còd sgrìobhaidh le bhith a’ cleachdadh fo-cheistean agus caochladairean dhaibh a’ tionndadh gu bhith na thangle ceangailte. Aig amannan tòisichidh tu a’ ruith timcheall diofar uinneagan IDE a’ feuchainn ri sreath ghnìomhan a’ chòd agad obrachadh a-mach. Chan eil e duilich, ach uaireannan tha e gu math duilich.

Chan eil làn thaic ann airson ES6.

Is dòcha gu bheil easbhaidhean eile ann, ach cha do thachair mi ri dad sam bith eile. Roinn fiosrachadh ma tha eòlas àicheil agad a’ cleachdadh NJS.

co-dhùnadh

Tha NJS na eadar-theangair stòr fosgailte aotrom a leigeas leat diofar sgriobtaichean JavaScript a chuir an gnìomh ann an Nginx. Rè a leasachadh, chaidh aire mhòr a thoirt do choileanadh. Gu dearbh, tha tòrr a dhìth fhathast, ach tha am pròiseact ga leasachadh le sgioba beag agus tha iad gu gnìomhach a 'cur feartan ùra ris agus a' càradh bhiteagan. Tha mi an dòchas gun leig NJS leat modalan taobh a-muigh a cheangal, a nì comas-gnìomh Nginx cha mhòr gun chrìoch. Ach tha NGINX Plus ann agus is coltaiche nach bi feartan ann!

Stòr-tasgaidh le còd slàn airson an artaigil

njs-pypi le taic AWS Sign v4

Tuairisgeul air stiùiridhean modal ngx_http_js_module

Stòr-tasgaidh oifigeil NJS и na sgrìobhainnean

Eisimpleirean de chleachdadh NJS bho Dmitry Volintsev

njs - sgriobtadh JavaScript dùthchasach ann an nginx / Òraid le Dmitry Volnyev aig Saint HighLoad ++ 2019

NJS ann an riochdachadh / Òraid le Vasily Soshnikov aig HighLoad ++ 2019

A’ soidhnigeadh agus a’ dearbhadh iarrtasan REST ann an AWS

Source: www.habr.com