Skip to content

12. Javascript'teki HTTP işlevleri

Image

12.1. Bir kütüphane seçimi: HTTP

Burada iki kütüphane seçtik:

EcmaScript 6, HTTP adlı ve [fetch] olarak adlandırılan bir işlevi doğal olarak barındırır; ancak bu işlev [node.js] tarafından uygulanmamaktadır (Eylül 2019). Node ortamında [fetch] işlevini kullanmaya olanak tanıyan [node-fetch] adlı bir kütüphane mevcuttur. Bu kütüphane, [node.js]'e özgü bazı API'leri kullanır. Bu durumda, bir [node-fetch] kodu, örneğin bir tarayıcı gibi [node] dışındaki bir ortamda %100 taşınabilir olmayabilir;

Ayrıca, hem HTTP isteklerine hem de [node.js] ile tarayıcılara uyumlu olan [axios] adlı bir kütüphane de mevcuttur. Sonuçta kullanacağımız kütüphane budur.

Bu iki kütüphaneyle yazılmış aynı komut dosyasını sunarak, her ikisiyle de kodlama sürecinin benzer olduğunu göstereceğiz.

12.2. Çalışma ortamının kurulması

12.2.1. Vergi hesaplama sunucusunun kurulumu

Son olarak, aşağıdaki mimariye sahip bir web uygulaması yazacağız:

Image

JS: JavaScript

Javascript kodu istemci tarafındadır:

  • statik sayfalar veya parçalar hizmeti;
  • jSON hizmetinden;

Dolayısıyla JavaScript kodu bir istemcidir jSON ve bu sıfatla katmanlar halinde düzenlenebilir [UI, métier, dao] (UI: Kullanıcı Arayüzü) katmanlarına ayrılabilir; tıpkı PHP ile yazılmış jSON istemcilerimizde olduğu gibi.

Sunucu, daha önce 13 sürümünü yazdığımız vergi hesaplama sunucusu olacaktır. 14. sürümünü yazacağız. Bu nedenle, NetBeans altında sürüm 13’ün klasörünü sürüm 14’ün klasörüne kopyalayarak işe başlıyoruz:

Image

  • [6] olarak. 14. sürümdeki [config.json] dosyasını şu şekilde değiştiriyoruz:

{
    "databaseFilename": "Config/database.json",
    "rootDirectory": "C:/myprograms/laragon-lite/www/php7/scripts-web/impots/version-14",
    "relativeDependencies": [

        "/Entities/BaseEntity.php",
        "/Entities/Simulation.php",
        ...
    "vues": {
        "vue-authentification.php": [700, 221, 400],
        "vue-calcul-impot.php": [200, 300, 341, 350, 800],
        "vue-liste-simulations.php": [500, 600]
    },
    "vue-erreurs": "vue-erreurs.php"
}
  • 3. satırda, uygulamanın kök dizinini değiştiriyoruz;

Bu sunucuya erişmek için [Laragon] hizmetlerini başlatmak gerekir.

Bu işlem tamamlandıktan sonra, [Postman] (bkz. bağlantıdaki makale) ile, şimdilik sürüm 13 ile aynı olan bu yeni sunucu sürümünü test edebiliriz. Vergi hesaplama sunucusunun sürüm 12'sini test etmek için kullanılan istek koleksiyonunu kullanabiliriz:

Image

  • [1-4]'te, bir oturum başlatmak için [init-session-700] sorgusunu kullanın;
  • [4-5]'te, projenin 14. sürümünü test etmek için [version-12] yerine [version-14]'i girin;
  • çalıştırma sırasında sunucudan jS0N [6] yanıtını almamız gerekir;

Sunucunun 14. sürümü artık çalışır durumda. Bu sürümde küçük değişiklikler yapacağız. Bu sunucunun API değerini hatırlayalım:

Eylem
Rol
Yürütme bağlamı
init-session
İstenen yanıtların türünü (json, xml, html) belirlemek için kullanılır
GET main.php?action=init-session&type=x
herhangi bir zamanda gönderilebilir
kullanıcı-kimlik-doğrulama
Bir kullanıcının oturum açmasına izin verir veya vermez
POST main.php?action=authentifier-utilisateur isteği
İsteğin iki POST parametresi içermesi gerekir [user, password]
Yalnızca oturum türü (json, xml, html) biliniyorsa gönderilebilir
vergi-hesapla
Vergi hesaplaması simülasyonu yapar
İstek: POST main.php?action=calculer-impot
İstek, üç POST parametresine sahip olmalıdır: [marié, enfants, salaire]
Yalnızca oturum türü (json, xml, html) biliniyorsa ve kullanıcı kimliği doğrulanmışsa gönderilebilir
simülasyonları-listele
Oturumun başlangıcından itibaren gerçekleştirilen simülasyonların listesini görüntüleme isteği
İstek: GET main.php?action=lister-simulations
İstek başka hiçbir parametre kabul etmez
Yalnızca oturum türü (json, xml, html) biliniyorsa ve kullanıcı kimliği doğrulanmışsa gönderilebilir
simülasyonu sil
Simülasyonlar listesinden bir simülasyonu siler
İstek: GET main.php?action=lister-simulations&numéro=x
İstek başka hiçbir parametre kabul etmez
Yalnızca oturum türü (json, xml, html) biliniyor ve kullanıcı kimliği doğrulanmışsa gönderilebilir
oturumu-sonlandır
Simülasyon oturumunu sonlandırır.
Teknik olarak eski web oturumu silinir ve yeni bir oturum oluşturulur
Yalnızca oturum türü (json, xml, html) biliniyor ve kullanıcı kimliği doğrulanmışsa gönderilebilir

12.2.2. Javascript istemcisinin HTTP kütüphanelerinin kurulumu

İlk etapta, aşağıdaki mimariyle çalışacağız:

Image

  • [1]'te, bir konsol komut dosyası olan [node.js], vergi hesaplama sunucusu jSON'e HTTP isteği gönderir;
  • [4]'te bu yanıtı alır ve konsolda görüntüler;

1 numaralı örnekte, [node-fetch] ve [axios] kütüphanelerini kullanacağız; sonraki örnekler için ise sadece [axios]'i kullanmaya devam edeceğiz. Şimdi bu iki JavaScript kütüphanesini [VSCode] terminalinden kuruyoruz:

Image

Ayrıca, bir karakter dizisinin URL kodlamasını sağlayan [qs] kütüphanesini de kullanacağız. Bu kodlamanın, HTTP, GET veya POST isteklerinin parametrelerini kodlamak için kullanıldığını hatırlayalım.

Image

12.3. [fetch-01] betiği

[fetch-01] komut dosyası, [node-fetch] kütüphanesini kullanarak vergi hesaplama sunucusuyla bir jSON oturumu başlatır. Kod şu şekildedir:


'use strict';

// ithalatlar
import fetch from 'node-fetch';
import qs from 'qs';
import { sprintf } from 'sprintf-js';
import moment from 'moment';


// URL temel vergi hesaplama sunucusu
const baseUrl = 'http://localhost/php7/scripts-web/impots/version-14/main.php?';
// oturum başlatma
async function initSession() {
  // istek seçenekleri HHTP [get /main.php?action=init-session&type=json]
  const options = {
    method: "GET",
    timeout: 2000
  };
  // sorgunun yürütülmesi HTTP [get /main.php?action=init-session&type=json]
  let débutFetch;
  try {
    // asenkron istek - [fetch] bir söz verir
    débutFetch = moment(Date.now());
    const response = await fetch(baseUrl + qs.stringify({
      action: 'init-session',
      type: 'json'
    }), options);
    // [response], sunucudan gelen HTTP yanıtının tamamıdır (HTTP başlıkları + yanıtın kendisi)
    // bu yanıtın yapısını görmek için görüntülenir
    console.log(sprintf("réponse fetch formatée en json,=%j, %s", response, heure(débutFetch)));
    console.log("réponse fetch en javascript=", response);
    // HTTP başlıklarına ulaşılabilir
    console.log("entêtes de la réponse=", response.headers);
    // Yanıt application/json türündeyse, sunucunun json yanıtı [response.json()] asenkron işleviyle elde edilir
    // bu durumda çağıran kod, bir [Promise] nesnesi alır
    // [await], sunucunun sözü yerine [json] yanıtını almaya olanak tanır
    const débutJson = moment(Date.now());
    const objet = await response.json();
    console.log(sprintf("réponse json=%j, type=%s, %s", objet, typeof (objet), heure(débutJson)));
    return objet;
    // Yanıt türü text/plain ise, sunucudan gelen metin yanıtı [response.text()] ile alınır
    // bu durumda çağrı yapan kod, [Promise] nesnesini alır
    // [await], sunucunun sözü yerine [texte] yanıtını almaya olanak tanır
    // const text = await response.text();
    // console.log("metin yanıtı=", text);
    // text'i döndür;
  } catch (error) {
    // burada bulunmamızın nedeni, sunucunun boş bir gövdeyle birlikte [404 Not Found, ...] hata kodunu göndermiş olmasıdır — hatanın yapısını görmek için hatayı görüntülüyoruz
    // ya da [fetch] istemcisi bir istisna oluşturduğu için (ağa erişilemiyor, ...)
    // hatanın yapısı görüntülenir
    console.log(sprintf("error fetch en json=%j, %s", error, heure(débutFetch)));
    console.log("error fetch en javascript=", typeof (error), error);
    // alınan hata mesajı gönderilir
    throw error.message;
  }
}

// main işlevi, [initSession] asenkron işlevini yürütür
async function main() {
  try {
    console.log("requête HTTP vers le serveur en cours ---------------------------------------------");
    const response = await initSession();
    console.log("succès ---------------------------------------------");
    console.log("réponse=", response, typeof (response))
  } catch (error) {
    console.log("erreur ---------------------------------------------");
    console.log("erreur=", error, typeof (error));
  }
}

// test
main();

// saat ve süre görüntüleme yardımcı programı
function heure(début) {
  // geçerli saat
  const now = moment(Date.now());
  // saat biçimlendirme
  let result = "heure=" + now.format("HH:mm:ss:SSS");
  // süre hesaplanmalı mı?
  if (début) {
    const durée = now - début;
    const milliseconds = durée % 1000;
    const seconds = Math.floor(durée / 1000);
    // saat + süre biçimlendirme
    result = result + sprintf(", durée= %s seconde(s) et %s millisecondes", seconds, milliseconds);
  }
  // sonuç
  return result;
}

Açıklamalar

  • Javascript'teki HTTP işlevleri asenkron işlevlerdir. Burada önceki bölümde öğrendiklerimizi kullanıyoruz (bkz. bağlantı);
  • 24. satır: Asenkron [fetch] işlevinin yanıtının [node.js] olay döngüsünde yayınlanmasını beklemek için [await] anahtar sözcüğünü kullanıyoruz. Bu komutun, [async] anahtar sözcüğüyle başlayan bir kodda yer alması gerektiğini biliyoruz (13. satır);
  • 13-56. satırlar: HTTP kodunu [initSession] asenkron işlevi içine kapsülliyoruz;
  • 59-69. satırlar: [main] adlı ikinci bir asenkron işlev, [initSession] adlı asenkron işlevi engelleyici bir şekilde (async / await) çağırmak için kullanılır;
  • 72. satır: [main] asenkron işlevi çağrılır;
  • kodun tamamı senkron kod gibi görünse de, burada yürütülenler aslında asenkron işlevlerdir, ancak bunlar engelleyici bir şekilde yürütülmektedir;
  • 19. satır: Vergi hesaplama sunucusuyla bir jSON oturumu başlatmak için, ona HTTP [get /main.php?action=init-session&type=json] komutunu göndermek gerekir. 24-27. satırlardaki kod bunu yapar. [fetch] komutunun sözdizimi şöyledir: [fetch(URL, options)] ile:
    • [URL]: sorgulanan URL;
    • [options]: sorgu seçeneklerini tanımlayan bir nesne. Özellikle burada, hedef makineye göndermek istediğimiz HTTP başlıklarını tanımlıyoruz;
  • 15-18. satırlar: Yapmak istediğimiz sorgunun seçenekleri tanımlanır:
    • [method]: Bir GET sorgusu yapmak istiyoruz;
    • [timeout]: [fetch] istemcisinin sunucudan yanıtı 2 saniyeden fazla beklememesini istiyoruz. Bu süre aşılırsa, [fetch] bir istisna oluşturacaktır;
  • 24. satır: URL ve [/main.php?action=init-session&type=json] değerlerini elde etmek için, [qs] kütüphanesini kullanarak GET'in [action,type] parametrelerinin URL kodlamasını elde ederiz. Elde edilen dize, kendimiz de oluşturabileceğimiz [init-session&type=json]'tir. Amacımız sadece, kodlanmış bir URL dizesinin nasıl elde edileceğini göstermekti;
  • 24. satır: [await] anahtar sözcüğü, burada asenkron bir görevin başlatıldığını ve bu görevin yanıtını [node.js] olay döngüsüne yayınlamasının beklendiğini gösterir;
  • 24. satır: [response]'te, alınan HTTP yanıtının tamamını (başlıklar ve belge) tanımlayan karmaşık bir nesne elde edilir;
  • 30-31. satırlar: [response] nesnesini, önce bir karakter dizisi olarak, ardından bir JavaScript nesnesi olarak görüntüleyerek yapısını inceleriz;
  • satır 33: sunucu tarafından gönderilen HTTP başlıklarını görüntüleriz;
  • satır 38: Vergi hesaplama sunucusunun jSON dizesini göndereceğini biliyoruz. Bu dize, [response] nesnesinde kapsüllenmiştir. [response.json()] yöntemi ile bu dizeyi elde edebiliriz. Ancak bu yöntem asenkron çalışır. Bu nedenle, [await response.json()] yazarak, [node.js] olay döngüsünde yayınlanacak olan jSON dizesini elde ederiz. Aslında elde ettiğimiz jSON dizesi değil, bu dizeyle temsil edilen JavaScript nesnesidir;
  • 39. satır: Alınan jSON dizesi görüntülenir;
  • 40. satır: Alınan JavaScript nesnesi döndürülür;
  • 47. satır: [fetch] komutundan kaynaklanabilecek olası bir hata yakalanır. Bu komut, yalnızca HTTP işlemi başarısız olmuşsa ve sunucudan herhangi bir yanıt alınamamışsa bir istisna oluşturur. Bir yanıt alınmışsa, HTTP kodu [200 OK]'ten farklı olsa bile, [fetch] bir istisna oluşturmaz ve sunucudan gelen yanıt 38. satırda kullanılabilir hale gelir;
  • 51-52. satırlar: [catch] cümlesi tarafından alınan [error] nesnesi, önce jSON dizesi olarak, ardından bir JavaScript nesnesi olarak görüntülenir;
  • 54. satır: [fetch]'in hata mesajı, [error.message]'te bulunur;
  • 59-69. satırlar: [main] asenkron işlevi, [initSession] asenkron işlevini engelleyici bir şekilde başlatır (62. satırdaki await);
  • 72. satır: asenkron [main] işlevi başlatılır ve komut dosyasının ana kodu bu noktada sona erer. Başlatılan asenkron görevler sonuçlarını olay döngüsüne yayınladığında, genel komut dosyası da sona erer;

Çalıştırma sonuçları şunlardır:

Durum 1: Laragon sunucusu başlatılmamıştır


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\http\fetch-01.js"
requête HTTP vers le serveur en cours ---------------------------------------------
error fetch en json={"message":"network timeout at: http://localhost/php7/scripts-web/impots/version-14/main.php?action=init-session&type=json","type":"request-timeout"}, heure=10:08:48:180, durée= 2 seconde(s) et 62 millisecondes
error fetch en javascript= object { FetchError: network timeout at: http://localhost/php7/scripts-web/impots/version-14/main.php?action=init-session&type=json
    at Timeout.<anonymous> (c:\Data\st-2019\dev\es6\javascript\node_modules\node-fetch\lib\index.js:1448:13)
    at ontimeout (timers.js:436:11)
    at tryOnTimeout (timers.js:300:5)
    at listOnTimeout (timers.js:263:5)
    at Timer.processTimers (timers.js:223:10)
  message:
   'http://localhost/php7/scripts-web/impots/version-14/main.php?action=init-session&type=json adresinde ağ zaman aşımı',
  type: 'request-timeout' }
erreur ---------------------------------------------
erreur= network timeout at: http://localhost/php7/scripts-web/impots/version-14/main.php?action=init-session&type=json dize

[Done] exited with code=0 in 2.804 seconds

Yorumlar

  • 3. satır: HTTP isteği, HTTP isteğine uygulanan 2 saniyelik zaman aşımı nedeniyle 2 saniye 62 milisaniye sonra başarısız olur;
  • 4-9. satırlar: [catch(error)] cümlesi tarafından yakalanan [error] JavaScript nesnesi. Bu nesnenin iki özelliği vardır:
    • [FetchError]: 4. satır;
    • [message]: satır 10-12;
  • 14. satır: asenkron [main] işlevi tarafından alınan hata mesajı;

Durum 2: Laragon sunucusu başlatılır


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\http\fetch-01.js"
requête HTTP vers le serveur en cours ---------------------------------------------
réponse fetch formatée en json,={"size":0,"timeout":2000}, heure=10:13:50:814, durée= 0 seconde(s) et 375 millisecondes
réponse fetch en javascript= Response {
  size: 0,
  timeout: 2000,
  [Symbol(Body internals)]:
   { body:
      PassThrough {
        _readableState: [ReadableState],
        readable: true,
        domain: null,
        _events: [Object],
        _eventsCount: 2,
        _maxListeners: undefined,
        _writableState: [WritableState],
        writable: false,
        allowHalfOpen: true,
        _transformState: [Object] },
     disturbed: false,
     error: null },
  [Symbol(Response internals)]:
   { url:
      'http://localhost/php7/scripts-web/impots/version-14/main.php?action=init-session&type=json',
     status: 200,
     statusText: 'OK',
     headers: Headers { [Symbol(map)][Object] },
     counter: 0 } }
entêtes de la réponse= Headers {
  [Symbol(map)]:
   [Object: null prototype] {
     date: [ 'Sat, 14 Sep 2019 08:13:50 GMT' ],
     server: [ 'Apache/2.4.35 (Win64) OpenSSL/1.1.0i PHP/7.2.11' ],
     'x-powered-by': [ 'PHP/7.2.11' ],
     'cache-control': [ 'max-age=0, private, must-revalidate, no-cache, private' ],
     'set-cookie': [ 'PHPSESSID=99q2iinusmhl55fa600aie2mmu; path=/' ],
     'content-length': [ '86' ],
     connection: [ 'close' ],
     'content-type': [ 'application/json' ] } }
réponse json={"action":"init-session","état":700,"réponse":"session démarrée avec type [json]"}, type=object, heure=10:13:50:825, durée= 0 seconde(s) et 1 millisecondes
succès ---------------------------------------------
réponse= { action: 'init-session',
  'durum': 700,
  'yanıt': '[json] türüyle oturum başlatıldı' } nesne

[Done] exited with code=0 in 1.022 seconds

Açıklamalar

  • 3. satır: [fetch], 375 ms sonra sunucudan yanıt alır;
  • 4-39. satırlar: Sunucunun yanıtını kapsayan [response] JavaScript nesnesinin yapısı. Bu nesnenin özelliklerinden bazıları bizim için ilgi çekici olabilir:
    • [status] (satır 25): sunucu yanıtındaki HTTP kodu;
    • [statusText] (satır 26): bu koda ait metin;
    • [headers] (27. satır): sunucu yanıtının HTTP başlıkları;
    • [body] (satır 8): sunucu tarafından gönderilen belgeyi temsil eder. [fetch] komutu, bu belgeyi işlemek için yöntemler sunar;
  • 29-39. satırlar: sunucunun yanıtındaki HTTP başlıkları;
  • 40. satır: asenkron [response.json()] işlevi, 1 milisaniye sonra yanıtını yayınladı;
  • 42-44. satırlar: [main] asenkron işlevi tarafından alınan JavaScript nesnesi;

Durum 3: Laragon sunucusu başlatıldı ancak ona hatalı bir komut gönderildi:

Image

  • Yukarıda, 26. satırda, sunucuya hatalı bir oturum türü aktarılır;

Çalıştırma sonuçları şunlardır:


requête HTTP vers le serveur en cours ---------------------------------------------
réponse fetch formatée en json,={"size":0,"timeout":2000}, heure=10:27:54:114, durée= 0 seconde(s) et 136 millisecondes
réponse fetch en javascript= Response {
  size: 0,
  timeout: 2000,
  [Symbol(Body internals)]:
   { body:
      PassThrough {
        _readableState: [ReadableState],
        readable: true,
        domain: null,
        _events: [Object],
        _eventsCount: 2,
        _maxListeners: undefined,
        _writableState: [WritableState],
        writable: false,
        allowHalfOpen: true,
        _transformState: [Object] },
     disturbed: false,
     error: null },
  [Symbol(Response internals)]:
   { url:
      'http://localhost/php7/scripts-web/impots/version-14/main.php?action=init-session&type=x',
     status: 400,
     statusText: 'Bad Request',
     headers: Headers { [Symbol(map)][Object] },
     counter: 0 } }
entêtes de la réponse= Headers {
  [Symbol(map)]:
   [Object: null prototype] {
     date: [ 'Sat, 14 Sep 2019 08:27:54 GMT' ],
     server: [ 'Apache/2.4.35 (Win64) OpenSSL/1.1.0i PHP/7.2.11' ],
     'x-powered-by': [ 'PHP/7.2.11' ],
     'cache-control': [ 'max-age=0, private, must-revalidate, no-cache, private' ],
     'set-cookie': [ 'PHPSESSID=5ku9gfok81ikj98hia0meeum57; path=/' ],
     'content-length': [ '79' ],
     connection: [ 'close' ],
     'content-type': [ 'application/json' ] } }
réponse json={"action":"init-session","état":703,"réponse":"paramètre type=[x] invalide"}, type=object, heure=10:27:54:127, durée= 0 seconde(s) et 2 millisecondes
succès ---------------------------------------------
réponse= { action: 'init-session',
  'durum': 703,
  'yanıt': 'type=[x] parametresi geçersiz' } nesne

[Done] exited with code=0 in 0.712 seconds
  • sunucunun yanıtı 2. satırda alınır;
  • 24. satır: Sunucu yanıtındaki HTTP kodunun 400, yani bir hata kodu olduğu görülebilir. Bununla birlikte, [fetch] bir istisna oluşturmamıştır. [fetch], sunucudan bir yanıt aldığı sürece bu yanıtı işler ve istisna oluşturmaz;
  • 41-43. satırlar: asenkron [main] işlevi tarafından alınan yanıt;

12.4. [fetch-02] komut dosyası

Aşağıdaki komut dosyası, [fetch-01] komut dosyasını, gereksiz tüm ayrıntılardan arındırarak yeniden yazmaktadır:


'use strict';

// ithalatlar
import fetch from 'node-fetch';
import qs from 'qs';

// URL vergi hesaplama sunucusunun temel bileşeni
const baseUrl = 'http://localhost/php7/scripts-web/impots/version-14/main.php?';
// oturum başlatma
async function initSession() {
  // istek seçenekleri HHTP [get /main.php?action=init-session&type=json]
  const options = {
    method: "GET",
    timeout: 2000
  };
  // sorgunun yürütülmesi HTTP [get /main.php?action=init-session&type=json]
  const response = await fetch(baseUrl + qs.stringify({
    action: 'init-session',
    type: 'json'
  }), options);
  // jSON'te alınan sonuç
  return await response.json();
}

// main işlevi, [initSession] asenkron işlevini yürütür
async function main() {
  try {
    console.log("requête HTTP vers le serveur en cours ---------------------------------------------");
    const response = await initSession();
    console.log("succès ---------------------------------------------");
    console.log("réponse=", response)
  } catch (error) {
    console.log("erreur ---------------------------------------------");
    console.log("erreur=", error.message);
  }
}

// test
main();

Normal bir çalıştırma sonucu:


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\http\fetch-02.js"
requête HTTP vers le serveur en cours ---------------------------------------------
succès ---------------------------------------------
réponse= { action: 'init-session',
  'durum': 700,
  'yanıt: '[json] türüyle oturum başlatıldı' }

[Done] exited with code=0 in 0.56 seconds

Hata oluştuğunda (Laragon sunucusu durdurulduğunda) çalıştırma sonuçları:


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\http\fetch-02.js"
requête HTTP vers le serveur en cours ---------------------------------------------
erreur ---------------------------------------------
erreur= network timeout at: http://localhost/php7/scripts-web/impots/version-14/main.php?action=init-session&type=json

[Done] exited with code=0 in 2.701 seconds

12.5. [axios-01] komut dosyası

Burada, [fetch-01] komut dosyasını ele alıyoruz ve bunu [axios] kütüphanesi ile yeniden yazıyoruz. Bu kütüphaneye olan ilgimizin, [node.js] ortamı ile yaygın tarayıcı ortamları arasında taşınabilir olması olduğunu hatırlatırız. Bu, şunları sağlar:

  • 1. aşamada, komut dosyalarımızı [node.js] ortamında test etmemizi;
  • 2. aşamada, bunları bir tarayıcıya taşımak;

[axios-01] betiği, [fetch-01] betiğinin yapısını benimser:


''use strict';
import axios from 'axios';

// axios'un varsayılan yapılandırması
axios.defaults.timeout = 2000;
axios.defaults.baseURL = 'http://localhost/php7/scripts-web/impots/version-14';

// oturum başlatma
async function initSession(axios) {
  // istek seçenekleri HHTP [get /main.php?action=init-session&type=json]
  const options = {
    method: "GET",
    // URL parametreleri
    params: {
      action: 'init-session',
      type: 'json'
    }
  };
  // HTTP isteğinin yürütülmesi [get /main.php?action=init-session&type=json]
  try {
    // asenkron istek
    const response = await axios.request('main.php', options);
    // yanıt, sunucudan gelen HTTP yanıtının tamamıdır (HTTP başlıkları + yanıtın kendisi)
    // bu yanıtın yapısını görmek için görüntülenir
    console.log("réponse axios=", response);
    // sunucunun yanıtı [response.data] içinde yer almaktadır
    return response.data;
  } catch (error) {
    // burada bulunmamızın nedeni, sunucunun [404 Not Found, 500 Internal Server Error, ...] hata kodunu göndermiş olmasıdır
    // [error] parametresi bir istisna örneğidir - çeşitli biçimlerde olabilir
    // yapısını görmek için görüntülenir
    console.log("axios error=", typeof (error), error);
    if (error.response) {
      // sunucu, HTTP durum kodunda bir hata bildirdi, ancak aynı zamanda bir yanıt da gönderdi
      // bu yanıt [error.response.data] içinde bulunur
      // sunucunun {eylem, durum, yanıt} yapısına sahip jSON yanıtları gönderdiği biliniyor
      // ve hata durumunda hata mesajının [réponse] içinde olduğu bilinmektedir
      return error.response.data;
    } else {
      // hatayı tetikliyor
      throw error;
    }
  }
}

// main işlevi, [initSession] asenkron işlevini yürütür
async function main() {
  try {
    console.log("requête HTTP vers le serveur en cours ---------------------------------------------");
    const response = await initSession(axios);
    console.log("succès ---------------------------------------------");
    console.log("réponse=", response, typeof (response))
  } catch (error) {
    console.log("erreur ---------------------------------------------");
    console.log("erreur=", error.message);
  }
}

// test
main();

Açıklamalar

  • 2. satır: [axios] kütüphanesini içe aktarıyoruz;
  • 5-6. satırlar: HTTP istekleri için varsayılan yapılandırma. [axios.defaults] seçenekleri, [axios] nesnesi tarafından gönderilen tüm HTTP istekleri için geçerlidir; her yeni istekte bu seçenekleri yeniden belirtmeye gerek yoktur;
  • 5. satır: tüm istekler için 2 saniyelik zaman aşımı;
  • 6. satır: tüm URL'ler, temel URL'e göre ifade edilecektir;
  • 9. satır: [initSession] asenkron işlevi;
  • satır 11-18: gönderilecek HTTP isteğinin seçenekleri (satır 5-6'da zaten tanımlanmış olan varsayılan seçeneklere ek olarak);
  • satır 14-17: URL ve [action=init-session&type=json] parametreleri. [params] nesnesi otomatik olarak kodlanmış URL karakter dizisine dönüştürülecektir;
  • 22. satır: [axios.request] asenkron işlevinin engelleyici çağrısı. İlk parametre, 6. satırda tanımlanan temel URL nesnesine [main.php] nesnesinin eklenmesiyle oluşturulan hedef URL nesnesidir. İkinci parametre, 11-18. satırlardaki [options] nesnesidir;
  • 25. satır: [response], sunucudan gelen HTTP yanıtının tamamını (HTTP başlıkları + yanıt belgesi) kapsayan bir JavaScript nesnesidir. Yapısını görmek için görüntülenir;
  • 27. satır: Sunucu bir belge gönderdiyse, bu belge [response.data] içinde bulunur. Burada, sunucunun jSON yanıtını, HTTP ve [Content-type : application/json] başlıklarıyla birlikte gönderdiğini biliyoruz. Bu başlığın varlığı, [axios]'in [response.data]'i otomatik olarak bir JavaScript nesnesine dönüştürmesini sağlar;
  • 28. satır: [axios] işlevi bir istisna oluşturabilir. [axios]'in [fetch]'ten farklı olduğu nokta budur. Aşağıdaki durumlarda bir istisna oluşturulur:
    • HTTP isteği gönderilemedi (istemci tarafında hata);
    • sunucu, HTTP hata kodunu (400, 404, 500, …) gönderdi (bu ayar aslında değiştirilebilir). Hatırlatmak gerekirse, bu HTTP kodu bir yanıtla birlikte geliyorsa, [fetch] bir istisna oluşturmazken, [axios] bir istisna oluşturur. Bununla birlikte, HTTP hata kodu bir belgeyle birlikte gelirse, bu belge [error.response]'e yerleştirilir;
  • 32. satır: [error] nesnesinin JavaScript yapısı görüntülenir;
  • satır 33-38: [error] nesnesi bir [response] nesnesi içeriyorsa, çağıran koda bu yanıt verilir;
  • satır 39-42: diğer durumlarda, [error] nesnesi çağıran koda geri gönderilir;
  • satır 47-57: asenkron işlev [main];
  • satır 50: asenkron [initSession] işlevine engelleyici çağrı. Sunucudan gelen jSON yanıtı bir JavaScript nesnesi olarak alınır;
  • 53-56. satırlar: Olası hatanın yakalanması. Hata mesajı [error.message]'te bulunur;

Çalıştırma sonuçları şöyledir:

Durum 1: Laragon sunucusu başlatılmamış


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\http\axios-01.js"
requête HTTP vers le serveur en cours ---------------------------------------------
axios error= object { Error: timeout of 2000ms exceeded
    at createError (c:\Data\st-2019\dev\es6\javascript\node_modules\axios\lib\core\createError.js:16:15)
    at Timeout.handleRequestTimeout (c:\Data\st-2019\dev\es6\javascript\node_modules\axios\lib\adapters\http.js:252:16)
    at ontimeout (timers.js:436:11)
    at tryOnTimeout (timers.js:300:5)
    at listOnTimeout (timers.js:263:5)
    at Timer.processTimers (timers.js:223:10)
  config:
   { url:
      'http://localhost/php7/scripts-web/impots/version-14/main.php',
     method: 'get',
     params: { action: 'init-session', type: 'json' },
     headers:
      { Accept: 'application/json, text/plain, */*',
        'User-Agent': 'axios/0.19.0' },
     baseURL: 'http://localhost/php7/scripts-web/impots/version-14',
     transformRequest: [ [Function: transformRequest] ],
     transformResponse: [ [Function: transformResponse] ],
     timeout: 2000,
     adapter: [Function: httpAdapter],
     xsrfCookieName: 'XSRF-TOKEN',
     xsrfHeaderName: 'X-XSRF-TOKEN',
     maxContentLength: -1,
     validateStatus: [Function: validateStatus],
     data: undefined },
  code: 'ECONNABORTED',
  request:
   Writable {
     _writableState:
      WritableState {
        objectMode: false,
        highWaterMark: 16384,
        finalCalled: false,
        needDrain: false,
        ending: false,
        ended: false,
        finished: false,
        destroyed: false,
        decodeStrings: true,
        defaultEncoding: 'utf8',
        length: 0,
        writing: false,
        corked: 0,
        sync: true,
        bufferProcessing: false,
        onwrite: [Function: bound onwrite],
        writecb: null,
        writelen: 0,
        bufferedRequest: null,
        lastBufferedRequest: null,
        pendingcb: 0,
        prefinished: false,
        errorEmitted: false,
        emitClose: true,
        bufferedRequestCount: 0,
        corkedRequestsFree: [Object] },
     writable: true,
     domain: null,
     _events:
      [Object: null prototype] {
        response: [Function: handleResponse],
        error: [Function: handleRequestError] },
     _eventsCount: 2,
     _maxListeners: undefined,
     _options:
      { protocol: 'http:',
        maxRedirects: 21,
        maxBodyLength: 10485760,
        path:
         '/php7/scripts-web/impots/version-14/main.php?action=init-session&type=json',
        method: 'GET',
        headers: [Object],
        agent: undefined,
        auth: undefined,
        hostname: 'localhost',
        port: null,
        nativeProtocols: [Object],
        pathname: '/php7/scripts-web/impots/version-14/main.php',
        search: '?action=init-session&type=json' },
     _redirectCount: 0,
     _redirects: [],
     _requestBodyLength: 0,
     _requestBodyBuffers: [],
     _onNativeResponse: [Function],
     _currentRequest:
      ClientRequest {
        domain: null,
        _events: [Object],
        _eventsCount: 6,
        _maxListeners: undefined,
        output: [],
        outputEncodings: [],
        outputCallbacks: [],
        outputSize: 0,
        writable: true,
        _last: true,
        chunkedEncoding: false,
        shouldKeepAlive: false,
        useChunkedEncodingByDefault: false,
        sendDate: false,
        _removedConnection: false,
        _removedContLen: false,
        _removedTE: false,
        _contentLength: 0,
        _hasBody: true,
        _trailer: '',
        finished: true,
        _headerSent: true,
        socket: [Socket],
        connection: [Socket],
        _header:
         'GET /php7/scripts-web/impots/version-14/main.php?action=init-session&type=json HTTP/1.1\r\nAccept: application/json, text/plain, */*\r\nUser-Agent: axios/0.19.0\r\nHost: localhost\r\nConnection: close\r\n\r\n',
        _onPendingData: [Function: noopPendingOutput],
        agent: [Agent],
        socketPath: undefined,
        timeout: undefined,
        method: 'GET',
        path:
         '/php7/scripts-web/impots/version-14/main.php?action=init-session&type=json',
        _ended: false,
        res: null,
        aborted: 1568528450762,
        timeoutCb: null,
        upgradeOrConnect: false,
        parser: [HTTPParser],
        maxHeadersCount: null,
        _redirectable: [Circular],
        [Symbol(isCorked)]: false,
        [Symbol(outHeadersKey)][Object] },
     _currentUrl:
      'http://localhost/php7/scripts-web/impots/version-14/main.php?action=init-session&type=json' },
  response: undefined,
  isAxiosError: true,
  toJSON: [Function] }
erreur ---------------------------------------------
erreur= timeout of 2000ms exceeded

[Done] exited with code=0 in 2.784 seconds

Açıklamalar

  • 33-136. satırlar: [error] nesnesi birçok bilgi içerir;
    • [Error], satır 3-9: Meydana gelen hatanın açıklaması;
    • [config], satır 10-27: bu hataya yol açan HTTP isteğinin yapılandırması;
    • [config.url], satır 11-12: hedef URL;
    • [config.method], satır 13: sorgu yöntemi;
    • [config.params], 14. satır: URL'in parametreleri;
    • [config.headers], satır 16-17: HTTP sorgusunun başlıkları;
    • [config.baseURL], satır 18: hedef URL'in temel URL'i;
    • [config.timeout], satır 21: isteğin zaman aşımı;
    • [code], satır 28: bir hata kodu;
    • [request], satır 29-133: HTTP isteğinin ayrıntılı açıklaması. Çoğu özelliğin başında alt çizgi (_) işareti bulunduğu dikkat çekmektedir; bu da bunların [request] nesnesine ait dahili özellikler olduğunu ve geliştirici tarafından doğrudan kullanılmak üzere tasarlanmadıklarını göstermektedir;
    • [response], satır 134: sunucunun yanıtı; burada yanıt mevcut değildir;
  • 138. satır: [main] işlevi tarafından görüntülenen hata mesajı;

Durum 2: Laragon sunucusu başlatıldı


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\http\axios-01.js"
requête HTTP vers le serveur en cours ---------------------------------------------
réponse axios= { status: 200,
  statusText: 'OK',
  headers:
   { date: 'Sun, 15 Sep 2019 07:09:26 GMT',
     server: 'Apache/2.4.35 (Win64) OpenSSL/1.1.0i PHP/7.2.11',
     'x-powered-by': 'PHP/7.2.11',
     'cache-control': 'max-age=0, private, must-revalidate, no-cache, private',
     'set-cookie': [ 'PHPSESSID=uas6lugtblstktcifpd8e5irm6; path=/' ],
     'content-length': '86',
     connection: 'close',
     'content-type': 'application/json' },
  config:
   { url:
      'http://localhost/php7/scripts-web/impots/version-14/main.php',
     method: 'get',
     params: { action: 'init-session', type: 'json' },
     headers:
      { Accept: 'application/json, text/plain, */*',
        'User-Agent': 'axios/0.19.0' },
     baseURL: 'http://localhost/php7/scripts-web/impots/version-14',
     transformRequest: [ [Function: transformRequest] ],
     transformResponse: [ [Function: transformResponse] ],
     timeout: 2000,
     adapter: [Function: httpAdapter],
     xsrfCookieName: 'XSRF-TOKEN',
     xsrfHeaderName: 'X-XSRF-TOKEN',
     maxContentLength: -1,
     validateStatus: [Function: validateStatus],
     data: undefined },
  request:
   ClientRequest {
     domain: null,
     _events:
      [Object: null prototype] {
        socket: [Function],
        abort: [Function],
        aborted: [Function],
        error: [Function],
        timeout: [Function],
        prefinish: [Function: requestOnPrefinish] },
     _eventsCount: 6,
     _maxListeners: undefined,
     output: [],
     outputEncodings: [],
     outputCallbacks: [],
     outputSize: 0,
     writable: true,
     _last: true,
     chunkedEncoding: false,
     shouldKeepAlive: false,
     useChunkedEncodingByDefault: false,
     sendDate: false,
     _removedConnection: false,
     _removedContLen: false,
     _removedTE: false,
     _contentLength: 0,
     _hasBody: true,
     _trailer: '',
     finished: true,
     _headerSent: true,
     socket:
      Socket {
        connecting: false,
        _hadError: false,
        _handle: [TCP],
        _parent: null,
        _host: 'localhost',
        _readableState: [ReadableState],
        readable: true,
        domain: null,
        _events: [Object],
        _eventsCount: 7,
        _maxListeners: undefined,
        _writableState: [WritableState],
        writable: false,
        allowHalfOpen: false,
        _sockname: null,
        _pendingData: null,
        _pendingEncoding: '',
        server: null,
        _server: null,
        parser: null,
        _httpMessage: [Circular],
        [Symbol(asyncId)]: 6,
        [Symbol(lastWriteQueueSize)]: 0,
        [Symbol(timeout)]: null,
        [Symbol(kBytesRead)]: 0,
        [Symbol(kBytesWritten)]: 0 },
     connection:
      Socket {
        connecting: false,
        _hadError: false,
        _handle: [TCP],
        _parent: null,
        _host: 'localhost',
        _readableState: [ReadableState],
        readable: true,
        domain: null,
        _events: [Object],
        _eventsCount: 7,
        _maxListeners: undefined,
        _writableState: [WritableState],
        writable: false,
        allowHalfOpen: false,
        _sockname: null,
        _pendingData: null,
        _pendingEncoding: '',
        server: null,
        _server: null,
        parser: null,
        _httpMessage: [Circular],
        [Symbol(asyncId)]: 6,
        [Symbol(lastWriteQueueSize)]: 0,
        [Symbol(timeout)]: null,
        [Symbol(kBytesRead)]: 0,
        [Symbol(kBytesWritten)]: 0 },
     _header:
      'GET /php7/scripts-web/impots/version-14/main.php?action=init-session&type=json HTTP/1.1\r\nAccept: application/json, text/plain, */*\r\nUser-Agent: axios/0.19.0\r\nHost: localhost\r\nConnection: close\r\n\r\n',
     _onPendingData: [Function: noopPendingOutput],
     agent:
      Agent {
        domain: null,
        _events: [Object],
        _eventsCount: 1,
        _maxListeners: undefined,
        defaultPort: 80,
        protocol: 'http:',
        options: [Object],
        requests: {},
        sockets: [Object],
        freeSockets: {},
        keepAliveMsecs: 1000,
        keepAlive: false,
        maxSockets: Infinity,
        maxFreeSockets: 256 },
     socketPath: undefined,
     timeout: undefined,
     method: 'GET',
     path:
      '/php7/scripts-web/impots/version-14/main.php?action=init-session&type=json',
     _ended: true,
     res:
      IncomingMessage {
        _readableState: [ReadableState],
        readable: false,
        domain: null,
        _events: [Object],
        _eventsCount: 3,
        _maxListeners: undefined,
        socket: [Socket],
        connection: [Socket],
        httpVersionMajor: 1,
        httpVersionMinor: 0,
        httpVersion: '1.0',
        complete: true,
        headers: [Object],
        rawHeaders: [Array],
        trailers: {},
        rawTrailers: [],
        aborted: false,
        upgrade: false,
        url: '',
        method: null,
        statusCode: 200,
        statusMessage: 'OK',
        client: [Socket],
        _consuming: false,
        _dumped: false,
        req: [Circular],
        responseUrl:
         'http://localhost/php7/scripts-web/impots/version-14/main.php?action=init-session&type=json',
        redirects: [] },
     aborted: undefined,
     timeoutCb: null,
     upgradeOrConnect: false,
     parser: null,
     maxHeadersCount: null,
     _redirectable:
      Writable {
        _writableState: [WritableState],
        writable: true,
        domain: null,
        _events: [Object],
        _eventsCount: 2,
        _maxListeners: undefined,
        _options: [Object],
        _redirectCount: 0,
        _redirects: [],
        _requestBodyLength: 0,
        _requestBodyBuffers: [],
        _onNativeResponse: [Function],
        _currentRequest: [Circular],
        _currentUrl:
         'http://localhost/php7/scripts-web/impots/version-14/main.php?action=init-session&type=json' },
     [Symbol(isCorked)]: false,
     [Symbol(outHeadersKey)]:
      [Object: null prototype] { accept: [Array], 'user-agent': [Array], host: [Array] } },
  data:
   { action: 'init-session',
     'durum': 700,
     'yanıt': '[json] türüyle oturum başlatıldı' } }
succès ---------------------------------------------
réponse= { action: 'init-session',
  'durum': 700,
  'yanıt': '[json] türüyle oturum başlatıldı' } nesne

[Done] exited with code=0 in 1.115 seconds

Açıklamalar

  • satır 3-203: sunucunun HTTP yanıtını kapsayan [response] JavaScript nesnesi;
  • 3. satır, [status]: yanıtın HTTP kodu;
  • 4. satır, [statusText]: önceki HTTP koduyla ilişkili metin;
  • satır 5-13, [headers]: yanıtın HTTP başlıkları:
    • 10. satır, [Set-Cookie]: oturum çerezi;
    • satır 13, [Content-Type]: sunucu tarafından gönderilen belgenin türü;
  • satır 14-31, [config]: gönderilen HTTP isteğinin yapılandırması;
  • satır 32-199, [request]: gönderilen HTTP isteğini detaylandıran JavaScript nesnesi;
  • satır 200-203, [request.data]: sunucudan gelen jSON yanıtını kapsayan JavaScript nesnesi;
  • satır 205-207: asenkron [main] işlevi tarafından alınan yanıt;

Durum 3: Laragon sunucusuna hatalı bir [init-session] isteği gönderilir;

Image

Çalıştırma sonuçları şunlardır:


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\http\axios-01.js"
requête HTTP vers le serveur en cours ---------------------------------------------
axios error= object { Error: Request failed with status code 400
   ...
  config:
   { url:
      'http://localhost/php7/scripts-web/impots/version-14/main.php',
     ...
     data: undefined },
  request:
   ...
     [Symbol(outHeadersKey)]:
      [Object: null prototype] { accept: [Array], 'user-agent': [Array], host: [Array] } },
  response:
   { status: 400,
     statusText: 'Bad Request',
     headers:
      { date: 'Sun, 15 Sep 2019 07:25:58 GMT',
        server: 'Apache/2.4.35 (Win64) OpenSSL/1.1.0i PHP/7.2.11',
        'x-powered-by': 'PHP/7.2.11',
        'cache-control': 'max-age=0, private, must-revalidate, no-cache, private',
        'set-cookie': [Array],
        'content-length': '79',
        connection: 'close',
        'content-type': 'application/json' },
     config:
      { url:
         '"http://localhost/php7/scripts-web/impots/version-14/main.php",
        ...
        data: undefined },
     request:
      ...
        [Symbol(outHeadersKey)][Object] },
     data:
      { action: 'init-session',
        'durum': 703,
        'yanıt': 'type=[x] parametresi geçersiz' } },
  isAxiosError: true,
  toJSON: [Function] }
succès ---------------------------------------------
réponse= { action: 'init-session',
  'durum': 703,
  'yanıt': 'type=[x] parametresi geçersiz' } nesne

[Done] exited with code=0 in 0.69 seconds

Sunucu 400 kodlu bir yanıt (satır 15) gönderdiği için, HTTP, [axios] bir istisna oluşturdu (bu davranış da yine yapılandırılabilir). [axios] bir istisna oluşturmuş olsa da, [error.response]'te (satır 14) sunucudan HTTP yanıtını ve [error.response.data]'e gönderilen jSON belgesini (satır 34) başarıyla alıyoruz. 41-43. satırlar: [main] işlevi, sunucudan jSON yanıtını doğru bir şekilde alır.

12.6. [axios-02] komut dosyası

Artık [axios] kütüphanesi tarafından bir HTTP isteği sırasında işlenen nesneleri ayrıntılı olarak incelediğimize göre, [axios-01] komut dosyasını şu şekilde yeniden yazabiliriz:


''use strict';
import axios from 'axios';

// axios'un varsayılan yapılandırması
axios.defaults.timeout = 2000;
axios.defaults.baseURL = 'http://localhost/php7/scripts-web/impots/version-14';

// oturum başlatma
async function initSession(axios) {
  // istek seçenekleri HHTP [get /main.php?action=init-session&type=json]
  const options = {
    method: "GET",
    // URL parametreleri
    params: {
      action: 'init-session',
      type: 'json'
    }
  };
  try {
    // HTTP sorgusunun yürütülmesi [get /main.php?action=init-session&type=json]
    const response = await axios.request('main.php', options);
    // sunucu yanıtı [response.data]'te
    return response.data;
  } catch (error) {
    // sunucunun yanıtı
    if (error.response) {
      // jSON yanıtı [error.response.data] içinde yer almaktadır
      return error.response.data;
    } else {
      // hata yeniden gönderiliyor
      throw error;
    }
  }
}

// main işlevi, [initSession] asenkron işlevini çalıştırıyor
async function main() {
  try {
    console.log("requête HTTP vers le serveur en cours ---------------------------------------------");
    const response = await initSession(axios);
    console.log("succès ---------------------------------------------");
    console.log("réponse=", response, typeof (response))
  } catch (error) {
    console.log("erreur ---------------------------------------------");
    console.log("erreur=", error.message);
  }
}

// test
main();

12.7. [axios-03] betiği

[axios-03] komut dosyası, [axios-02] komut dosyasının metodolojisini kullanır. Bu sefer, POST kullanılarak sunucuya HTTP [authentifier-utilisateur] isteği eklenir:


'use strict';
import axios from 'axios';
import qs from 'qs'

// axios yapılandırması
axios.defaults.timeout = 2000;
axios.defaults.baseURL = 'http://localhost/php7/scripts-web/impots/version-14';


// oturum başlatma
async function initSession(axios) {
  // istek seçenekleri HHTP [get /main.php?action=init-session&type=json]
  const options = {
    method: "GET",
    // URL parametreleri
    params: {
      action: 'init-session',
      type: 'json'
    }
  };
  try {
    // isteğin yürütülmesi HTTP [get /main.php?action=init-session&type=json]
    const response = await axios.request('main.php', options);
    // sunucu yanıtı [response.data]'te
    return response.data;
  } catch (error) {
    // sunucunun yanıtı
    if (error.response) {
      // jSON yanıtı [error.response.data] içinde yer almaktadır
      return error.response.data;
    } else {
      // hata yeniden gönderiliyor
      throw error;
    }
  }
}

async function authentifierUtilisateur(axios, user, password) {
  // istek seçenekleri: HHTP [POST /main.php?action=authentifier-utilisateur]
  const options = {
    method: "POST",
    headers: {
      'Content-type': 'application/x-www-form-urlencoded',
    },
    // POST'in gövdesi
    data: qs.stringify({
      user: user,
      password: password
    }),
    // URL parametreleri
    params: {
      action: 'authentifier-utilisateur'
    }
  };
  try {
    // HTTP isteğinin yürütülmesi [post /main.php?action=authentifier-utilisateur]
    const response = await axios.request('main.php', options);
    // sunucu yanıtı [response.data]'te yer almaktadır
    return response.data;
  } catch (error) {
    // sunucunun yanıtı
    if (error.response) {
      // jSON yanıtı [error.response.data] içinde yer almaktadır
      return error.response.data;
    } else {
      // hata yeniden gönderiliyor
      throw error;
    }
  }
}

// main işlevi, asenkron işlevleri tek tek yürütür
async function main() {
  try {
    // init-session
    console.log("action init-session en cours ---------------------------------------------");
    const response1 = await initSession(axios);
    console.log("succès ---------------------------------------------");
    console.log("réponse=", response1);
    // kullanıcı-kimlik-doğrulama
    console.log("action authentifier-utilisateur en cours ---------------------------------------------");
    const response2 = await authentifierUtilisateur(axios, 'admin', 'admin');
    console.log("succès ---------------------------------------------");
    console.log("réponse=", response2)
  } catch (error) {
    console.log("erreur ---------------------------------------------");
    console.log("erreur=", error);
  }
}

// test
main();

Açıklamalar

  • 38-70. satırlar: asenkron [authentifierUtilisateur] işlevi;
  • 39. satır: [POST /main.php?action=authentifier-utilisateur] isteği yapılmalıdır;
  • 40-54. satırlar: HTTP isteğinin seçenekleri;
  • 41. satır: Bu bir POST'tir;
  • satır 42-44: POST'in parametreleri, müşterinin isteğiyle birlikte gönderdiği bir belgeye URL olarak kodlanacaktır;
  • satır 46-49: [data] özelliği, POST URL dizesini kodlanmış olarak içermelidir. Bunun için burada 3. satırda içe aktarılan [qs] kütüphanesi kullanılır;
  • 55-69. satırlar: Sorgunun yürütülmesi için, [initSession] yöntemindekiyle aynı kod kullanılır;
  • 73-89. satırlar: [asynchrone] yöntemi, 77. ve 82. satırlardaki [initSession, authentifierUtilisateur] yöntemlerini art arda, engelleyici bir şekilde çağırır;
  • 82. satır: (admin, admin) çifti, oturum açma kimlik bilgileri olarak kullanılır. Bunların sunucu tarafından tanındığı bilinmektedir;

Çalıştırma sonuçları şöyledir:


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\http\axios-03.js"
action init-session en cours ---------------------------------------------
succès ---------------------------------------------
réponse= { action: 'init-session',
  'durum': 700,
  'yanıt': '[json] türüyle oturum başlatıldı' }
action authentifier-utilisateur en cours ---------------------------------------------
succès ---------------------------------------------
réponse= { action: 'authentifier-utilisateur',
  'durum': 103,
  'yanıt':
   [ 'pas de session en cours. Commencer par action [init-session]' ] }

[Done] exited with code=0 in 0.834 seconds
  • 9-12. satırlar: kullanıcı kimlik doğrulaması başarısız olur: sunucu, jSON oturumunun başlatıldığını kaydetmemiştir. Bunun nedeni, ilk istek [init-session]'e yanıt olarak gönderilen oturum çerezinin geri gönderilmemiş olmasıdır;

12.8. [axios-04] komut dosyası

[axios-04] komut dosyası, [axios-03] komut dosyasına iki iyileştirme getiriyor:

  • oturum çerezini yönetir;
  • [initSession] ve [authentifierUtilisateur] işlevlerinde ortak olan kısımları [getRemoteData] işlevinde birleştirir;

''use strict';
import axios from 'axios';
import qs from 'qs'

// axios yapılandırması
axios.defaults.timeout = 2000;
axios.defaults.baseURL = 'http://localhost/php7/scripts-web/impots/version-14';

// oturum çerezi
const sessionCookieName = "PHPSESSID";
let sessionCookie = '';

// oturum başlatma
async function initSession(axios) {
  // istek seçenekleri HHTP [get /main.php?action=init-session&type=json]
  const options = {
    method: "GET",
    // URL parametreleri
    params: {
      action: 'init-session',
      type: 'json'
    }
  };
  // HTTP sorgusunun yürütülmesi
  return await getRemoteData(axios, options);
}

async function authentifierUtilisateur(axios, user, password) {
  // HHTP isteğinin seçenekleri [post /main.php?action=authentifier-utilisateur]
  const options = {
    method: "POST",
    headers: {
      'Content-type': 'application/x-www-form-urlencoded',
    },
    // POST'in gövdesi
    data: qs.stringify({
      user: user,
      password: password
    }),
    // URL'in parametreleri
    params: {
      action: 'authentifier-utilisateur'
    }
  };
  // HTTP isteğinin yürütülmesi
  return await getRemoteData(axios, options);
}

async function getRemoteData(axios, options) {
  // oturum çerezi için
  if (!options.headers) {
    options.headers = {};
  }
  options.headers.Cookie = sessionCookie;
  // HTTP isteğinin yürütülmesi
  let response;
  try {
    // asenkron istek
    response = await axios.request('main.php', options);
  } catch (error) {
    // [error] parametresi bir istisna örneğidir - çeşitli biçimlerde olabilir
    if (error.response) {
      // sunucunun yanıtı [error.response]'tedir
      response = error.response;
    } else {
      // hata yeniden gönderiliyor
      throw error;
    }
  }
  // response, sunucudan gelen HTTP yanıtının tamamıdır (HTTP başlıkları + yanıtın kendisi)
  // varsa oturum çerezi alınır
  const setCookie = response.headers['set-cookie'];
  if (setCookie) {
    // setCookie bir dizidir
    // bu dizide oturum çerezi aranır
    let trouvé = false;
    let i = 0;
    while (!trouvé && i < setCookie.length) {
      // oturum çerezi aranır
      const results = RegExp('^(' + sessionCookieName + '.+?);').exec(setCookie[i]);
      if (results) {
        // oturum çerezi kaydedilir
        // eslint-disable-next-line require-atomic-updates
        sessionCookie = results[1];
        // bulundu
        trouvé = true;
      } else {
        // sonraki öğe
        i++;
      }
    }
  }
  // sunucu yanıtı şurada: [response.data]
  return response.data;
}

// main işlevi, asenkron işlevleri tek tek yürütür
async function main() {
  try {
    // init-session
    console.log("action init-session en cours ---------------------------------------------");
    const response1 = await initSession(axios);
    console.log("succès ---------------------------------------------");
    console.log("réponse=", response1);
    // kullanıcı-kimlik-doğrulama
    console.log("action authentifier-utilisateur en cours ---------------------------------------------");
    const response2 = await authentifierUtilisateur(axios, 'admin', 'admin');
    console.log("succès ---------------------------------------------");
    console.log("réponse=", response2)
  } catch (error) {
    console.log("erreur ---------------------------------------------");
    console.log("erreur=", error.message);
  }
}

// test
main();

Açıklamalar

  • 14-26. satırlar: [initSession] fonksiyonu. Artık sadece sunucuya gönderilecek HTTP isteğini hazırlamakla yetiniyor, ancak bunu yürütmüyor. Bu görevi 49-95. satırlardaki [getRemoteDate] yöntemine devrediyor;
  • 28-47. satırlar: [authentifierUtilisateur] işlevi de aynı süreci izler;
  • 49. satır: [getRemoteData] işlevi, HTTP isteğini yürütmesini sağlayan iki bilgiyi alır:
    • [axios], isteği gönderecek ve yanıtı alacak olan nesne;
    • [options], sunucuya gönderilecek isteğin yapılandırma seçenekleri;
  • 59. satır: isteğin yürütülmesi ve yanıtın (jSON) blokajlı olarak beklenmesi;
  • satır 60-68: Olası istisnanın yönetimi;
  • 64. satır: hata nesnesinde kapsüllenmiş olabilecek yanıtın alınması;
  • 67. satır: sunucu, sunucu yanıtını içermeyen bir istisna oluşturduysa, alınan hata çağrı yapan koda iletilir;
  • [getRemoteData] işlevi oturum çerezini yönetir:
    • Bunu ilk kez aldığında [sessionCookie] değişkenine kaydeder (11. satır);
    • daha sonra her yeni HTTP isteğinde bunu geri gönderir;
  • 72-92. satırlar: [getRemoteData], sunucunun her yanıtını analiz ederek HTTP ve [Set-Cookie] başlıklarını gönderip göndermediğini kontrol eder. Sunucunun [PHPSESSID] adlı bir oturum çerezi gönderdiği bilinmektedir (satır 10). Dolayısıyla aranan çerez budur (satır 10);
  • 72. satır: Varsa HTTP ve [Set-Cookie] başlıklarını alıyoruz (büyük/küçük harf fark etmez). Aslında birden fazla [Set-Cookie] başlığı olabilir ve bu nedenle bir dizi olarak alınır;
  • 73. satır: Bir çerez dizisi elde edilmişse;
  • 78-90. satırlar: dizideki tüm çerezler arasından oturum çerezini ararız;
  • 80. satır: i numaralı çerez içinde oturum çerezini aramayı sağlayan ilişkisel ifade;
  • satır 81: karşılaştırma sonuç vermişse;
  • 84. satır: results[1] içinde, ilişkisel ifadenin şablonundaki ilk parantez, yani (PHPSESSID=xxxx) ile oturum çerezini sonlandıran ; (dahil edilmez) arasındaki kısım bulunur;
  • satır 50-54: her istekte, oturum çerezi isteğin HTTP başlıklarına eklenir. İlk seferde bu çerez boştur ve sunucu tarafından yok sayılır;

Çalıştırma sonuçları şöyledir:


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\http\axios-04.js"
action init-session en cours ---------------------------------------------
succès ---------------------------------------------
réponse= { action: 'init-session',
  'durum': 700,
  'yanıt': '[json] türüyle oturum başlatıldı' }
action authentifier-utilisateur en cours ---------------------------------------------
succès ---------------------------------------------
réponse= { action: 'authentifier-utilisateur',
  'durum': 200,
  'yanıt': 'Kimlik doğrulama başarılı [admin, admin]' }

[Done] exited with code=0 in 0.982 seconds