Skip to content

15. [nuxt-12] örneği: axios ile HTTP istekleri

15.1. Présentation

Bu yeni örnekte, [asyncData] işlevlerinde [axios] kütüphanesini kullanarak HTTP isteklerinin nasıl yapılabileceğini göreceğiz. Ayrıca, daha önce öğrendiğimiz kavramları da kullanacağız:

  • [nuxt-06] örneğindeki eklentilerin kullanımı:
  • [nuxt-06] örneğindeki oturum çerezinde deponun kalıcılığı;
  • [nuxt-09] örneğindeki middleware'lerle navigasyon kontrolü;
  • [nuxt-11] örneğindeki hata yönetimi;

Örneğin mimarisi şu şekilde olacaktır:

Image

  • [nuxt] uygulaması, [node.js] ve [3] sunucularında depolanacak, [1] tarayıcısı tarafından indirilecek ve ardından bu tarayıcı tarafından çalıştırılacaktır;
  • hem [nuxt] [1] istemcisi hem de [nuxt] [3] sunucusu, HTTP isteklerini [2] sunucusuna HTTP istekleri gönderecektir. Bu sunucu, 7. bölümde geliştirilen vergi hesaplama sunucusu olacaktır. CORS isteklerinin izin verildiği en son sürümü olan 14. sürümü kullanacağız;

Örneğin mimarisi şu şekilde basitleştirilebilir:

Image

  • [1]'te, [node.js] sunucusu, [nuxt] sayfalarını [2] tarayıcısına gönderir. Bu sayfaları sunan, sunucunun [web] – [8] katmanıdır. Sayfayı sunmak için sunucu, [3] veri sunucusundan harici veriler talep etmiş olabilir. Gerekli HTTP isteklerini yapan, [DAO] – [9] katmanıdır;
  • [node.js][1] sunucusuna her sayfa çağrısında, [2] tarayıcısı, [nuxt] uygulamasının tamamını alır ve uygulama daha sonra SPA modunda çalışır. [UI] (Kullanıcı Arayüzü) bloğu, [4] kullanıcıya [vue.js] sayfalarını sunar. Bu bloktaki eylemler veya sayfaların doğal yaşam döngüsü, [3] veri sunucusuna harici veri çağrılarına neden olabilir. Bu durumda, gerekli HTTP isteklerini [DAO] ve [5] katmanları gerçekleştirir;

15.2. Proje ağacı

Image

15.3. [nuxt.config.js] yapılandırma dosyası

Proje, aşağıdaki [nuxt.config.js] dosyası tarafından kontrol edilecektir:


export default {
  mode: 'universal',
  /*
   ** Headers of the page
   */
  head: {
    title: 'Introduction à [nuxt.js]',
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      {
        hid: 'description',
        name: 'description',
        content: 'ssr routing loading asyncdata middleware plugins store'
      }
    ],
    link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }]
  },
  /*
   ** Customize the progress-bar color
   */
  loading: false,

  /*
   ** Global CSS
   */
  css: [],
  /*
   ** Plugins to load before mounting the App
   */
  plugins: [
    { src: '@/plugins/client/plgSession', mode: 'client' },
    { src: '@/plugins/server/plgSession', mode: 'server' },
    { src: '@/plugins/client/plgDao', mode: 'client' },
    { src: '@/plugins/server/plgDao', mode: 'server' },
    { src: '@/plugins/client/plgEventBus', mode: 'client' }
  ],
  /*
   ** Nuxt.js dev-modules
   */
  buildModules: [
    // Belge: https://github.com/nuxt-community/eslint-module
    '@nuxtjs/eslint-module'
  ],
  /*
   ** Nuxt.js modules
   */
  modules: [
    // Belge: https://bootstrap-vue.js.org
    'bootstrap-vue/nuxt',
    // Belge: https://axios.nuxtjs.org/usage
    '@nuxtjs/axios',
    // https://www.npmjs.com/package/cookie-universal-nuxt
    'cookie-universal-nuxt'
  ],
  /*
   ** Axios module configuration
   ** See https://axios.nuxtjs.org/options
   */
  axios: {},
  /*
   ** Build configuration
   */
  build: {
    /*
     ** You can extend webpack config here
     */
    extend(config, ctx) { }
  },
  // kaynak kod dizini
  srcDir: 'nuxt-12',
  // yönlendirici
  router: {
    // uygulamanın URL kökü
    base: '/nuxt-12/',
    // yönlendirme ara yazılımı
    middleware: ['routing']
  },
  // sunucu
  server: {
    // hizmet bağlantı noktası, varsayılan olarak 3000
    port: 81,
    // dinlenen ağ adresleri, varsayılan olarak localhost: 127.0.0.1
    // 0.0.0.0 = makinedeki tüm ağ adresleri
    host: 'localhost'
  },
  // ortam
  env: {
    // axios yapılandırması
    timeout: 2000,
    withCredentials: true,
    baseURL: 'http://localhost/php7/scripts-web/impots/version-14',
    // oturum çerezi yapılandırması [nuxt]
    maxAge: 60 * 5
  }
}
  • 22. satır: Asenkron bir eylemin sona ermesini bekleme uyarısını kendimiz yönetiyoruz;
  • 31. satır: İster istemciye, ister sunucuya özel olacak, ancak her ikisine birden değil, çeşitli eklentiler kullanacağız;
  • 52. satır: [axios] modülü, [nuxt]'e entegre edilmiştir. Bunun sonucunda, [axios] nesnesi,[nuxt] uygulamasından vergi hesaplama sunucusu PHP’e gönderecek olan [axios] nesnesi, [context.$axios]’te kullanılabilir hale gelecektir;
  • 54. satır: [cookie-universal-nuxt] modülü, [nuxt] oturumunu bir çerezde kaydetmemizi sağlayacaktır;
  • 60. satır: [axios] özelliği, 52. satırdaki [@nuxtjs/axios] modülünü yapılandırmamızı sağlar. Bu seçeneği kullanmayacağız; bunun yerine 88. satırdaki [env] özelliğini tercih edeceğiz;
  • 90. satır: vergi hesaplama sunucusundan yanıt alınması için maksimum bekleme süresi;
  • satır 91: [nuxt] istemcisi için gereklidir – vergi hesaplama sunucusuyla yapılan iletişimde çerezlerin kullanımına izin verir;
  • satır 92: vergi hesaplama sunucusunun temel URL'i;
  • satır 94: nuxt oturumunun süresi (5 dakika);
  • satır 77: [nuxt] istemcisi ve sunucusu arasındaki iletişim, bir yönlendirme ara yazılımı tarafından kontrol edilecektir;

15.4. Uygulamanın [UI] katmanı

Image

[nuxt] uygulamasına, aşağıdaki görünüm aracılığıyla vergi hesaplama sunucusundaki API'e erişim izni vereceğiz:

Image

  • [2]'te, vergi hesaplama sunucusundaki API'e erişim sağlayan menü:
    • [Authentification]: [authentification] sayfasına karşılık gelir. Bu sayfa, şu anda yetkilendirilmiş tek kimlik bilgileri olan [admin, admin] ile vergi hesaplama sunucusuna bir kimlik doğrulama isteği gönderir. Görüntülenen sonuç, [3] sayfasına benzerdir;
    • [Requête AdminData]: [get-admindata] sayfasına karşılık gelir. Bu sayfa, vergi hesaplama sunucusundan, burada [adminData] olarak adlandırılan ve vergi hesaplamasına olanak tanıyan verileri ister. Görüntülenen sonuç, [3] sayfasına benzerdir;
    • [Fin session impôt]: [fin-session] sayfasına karşılık gelir. Bu sayfa, vergi hesaplama sunucusuna PHP oturum sonlandırma isteği gönderir. Sunucu daha sonra mevcut PHP oturumunu sonlandırır ve yeni bir boş oturum başlatır;

15.5. [nuxt] uygulamasının [dao] katmanları

Yukarıda belirtildiği gibi, [nuxt] uygulamasının mimarisi şu şekilde olacaktır:

Image

  • [1]'te, [node.js] sunucusu, [nuxt] sayfalarını [2] tarayıcısına gönderir. Bu sayfaları sunan, sunucunun [web] – [8] katmanıdır. Sayfayı sunmak için sunucu, [3] veri sunucusundan harici veriler talep etmiş olabilir. Gerekli HTTP isteklerini yapan, [DAO] – [9] katmanıdır;
  • [node.js][1] sunucusuna her sayfa çağrısında, [2] tarayıcısı, [nuxt] uygulamasının tamamını alır ve uygulama daha sonra SPA modunda çalışır. [UI] (Kullanıcı Arayüzü) bloğu, [4] bloğu aracılığıyla kullanıcıya [vue.js] sayfalarını sunar. Bu bloğun eylemleri veya sayfaların yaşam döngüsü, [3] veri sunucusuna harici veri çağrılarına neden olabilir. Bu durumda, gerekli HTTP isteklerini [DAO] ve [5] katmanları gerçekleştirir;

|Introduction au langage PHP7 par l’exemple| belgesinde geliştirilen vergi hesaplama sunucusunun 14. sürümünü kullanacağız. Bu sunucunun API (Uygulama Programlama Arayüzü) jSON bölümünün yalnızca bir kısmını kullanacağız:

İstek
Yanıt
1
2
3
4
5
6
[initialisation d’une session jSON avec le
serveur de calcul de l’impôt]
[une session PHP est créée avec le serveur de
calcul de l’impôt]

GET main.php?action=init-session&type=json

{
    "action": "init-session",
    "état"700,
    "réponse": "session démarrée avec type [json]"
}

[authentification de l’utilisateur]
[l’authentification est stockée dans la
session PHP]

POST main.php?action=authentifier-utilisateur
paramètres postés : user, admin

{
    "action": "authentifier-utilisateur",
    "état"200,
    "réponse": "Authentification réussie [admin, admin]"
}

[demande des données de l’administration
fiscale]
[les données reçues sont stockées dans la
session PHP]

GET main.php?action=get-admindata

{
    "action": "get-admindata",
    "état"1000,
    "réponse": {
        "limites": [
            9964,
            27519,
            73779,
            156244,
            0
        ],
        "coeffR": [
            0,
            0.14,
            0.3,
            0.41,
            0.45
        ],
        "coeffN": [
            0,
            1394.96,
            5798,
            13913.69,
            20163.45
        ],
        "plafondQfDemiPart": 1551,
        "plafondRevenusCelibatairePourReduction": 21037,
        "plafondRevenusCouplePourReduction": 42074,
        "valeurReducDemiPart": 3797,
        "plafondDecoteCelibataire": 1196,
        "plafondDecoteCouple": 1970,
        "plafondImpotCouplePourDecote": 2627,
        "plafondImpotCelibatairePourDecote": 1595,
        "abattementDixPourcentMax": 12502,
        "abattementDixPourcentMin": 437
    }
}

[fin de la session PHP avec le serveur de
calcul de l’impôt]
[supprime la session PHP courante et crée une
nouvelle session PHP. Dans celle-ci, la
session jSON reste activée, mais l’utilisateur
n’est plus authentifié]

GET main.php?action=fin-session

{
    "action": "fin-session",
    "état"400,
    "réponse": "session supprimée"
}

15.5.1. [nuxt] sunucusunun [dao] katmanı

Image

[node.js] [1] sunucusu, |Introduction au framework VUE.JS par l’exemple| belgesinde açıklanan [dao] katmanını kullanacaktır. Burada kodunu tekrar hatırlatıyoruz:


'use strict';

// ithalatlar
import qs from 'qs'

class Dao {

  // yapıcı
  constructor(axios) {
    this.axios = axios;
    // oturum çerezi
    this.sessionCookieName = "PHPSESSID";
    this.sessionCookie = '';
  }

  // oturumu başlat
  async  initSession() {
    // 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 this.getRemoteData(options);
  }

  async  authentifierUtilisateur(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 this.getRemoteData(options);
  }

  async getAdminData() {
    // HHTP sorgusunun seçenekleri [get /main.php?action=get-admindata]
    const options = {
      method: "GET",
      // URL sorgusunun parametreleri
      params: {
        action: 'get-admindata'
      }
    };
    // HTTP sorgusunun yürütülmesi
    const data = await this.getRemoteData(options);
    // sonuç
    return data;
  }

  async  getRemoteData(options) {
    // oturum çerezi için
    if (!options.headers) {
      options.headers = {};
    }
    options.headers.Cookie = this.sessionCookie;
    // HTTP isteğinin yürütülmesi
    let response;
    try {
      // asenkron istek
      response = await this.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;
      }
    }
    // yanıt, 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('^(' + this.sessionCookieName + '.+?);').exec(setCookie[i]);
        if (results) {
          // oturum çerezi kaydedilir
          // eslint-disable-next-line require-atomic-updates
          this.sessionCookie = results[1];
          // bulundu
          trouvé = true;
        } else {
          // sonraki öğe
          i++;
        }
      }
    }
    // sunucu yanıtı şurada: [response.data]
    return response.data;
  }
}

// sınıfın dışa aktarımı
export default Dao;
  • [dao] katmanındaki tüm yöntemler, [{action : ‘xx’, état : nn, réponse : {...}] veri sunucusu tarafından gönderilen nesneyi şu şekilde döndürür:
    • [action]: veri sunucusu tarafından yürütülen eylemin adı;
    • [état]: sayısal gösterge:
      • [initSession]: hatasız yanıt için durum=700;
      • [authentifierUtilisateur]: hatasız yanıt için durum=200;
      • [getAdminData]: hatasız yanıt için durum=1000;
      • [fin-session]: hatasız yanıt için durum=400;
    • [réponse]: [état] sayısal göstergesine ilişkin yanıt. Bu sayısal göstergeye göre değişiklik gösterebilir;

[Dao] sınıfının oluşturucusunu inceleyelim:


// yapıcı
  constructor(axios) {
    this.axios = axios;
    // oturum çerezi
    this.sessionCookieName = "PHPSESSID";
    this.sessionCookie = '';
}
  • 2. satır: Oluşturucuya argüman olarak verilen [axios] nesnesi, çağıran kod tarafından sağlanır. HTTP isteklerini gerçekleştirecek olan da budur;
  • 5. satır: Veri sunucusu tarafından gönderilen oturum çereğinin adı, PHP olarak yazılmıştır;
  • 6. satır: [dao] katmanı ile veri sunucusu arasında alışverişi yapılan oturum çerezi. Bu çerez, 67-113. satırlardaki [getRemoteData] işlevi tarafından başlatılır;

Oturum çerezi için, iki ayrı [dao] katmanını dikkate almamız gerekir:

  • tarayıcı katmanı;
  • sunucu katmanı;

Üç oturum çerezini yönetmemiz gerekecek:

  1. [nuxt] istemcisi ile PHP 7 sunucusu arasında alışverişi yapılan çerez;
  2. [nuxt] sunucusu ile PHP 7 sunucusu arasında alışverişi yapılan;
  3. [nuxt] istemcisi ile [nuxt] sunucusu arasında alışverişi yapılan çerez;

PHP sunucusuyla olan oturum çerezinin, hem istemci hem de [nuxt] sunucusu için aynı olmasını sağlayacağız. Bu çereze PHP oturum çerezi adını vereceğiz. Bu çerez, 1. ve 2. durumlara aittir. 3. durumdaki çereze ise [nuxt] oturum çerezi adını vereceğiz. Dolayısıyla iki oturumumuz olacak:

  • PHP oturum çerezi ile PHP oturumu;
  • [nuxt] oturum çerezi ile [nuxt] oturumu;

Neden istemcinin PHP oturumu ile tarayıcının [nuxt] oturumu için aynı çerez kullanılıyor? Uygulamanın, ister istemci ister [nuxt] sunucusu olsun, PHP sunucusuyla sorunsuz bir şekilde iletişim kurabilmesini istiyoruz:

  • [nuxt] sunucusundaki bir A eylemi, PHP sunucusunu E durumuna geçirirse, bu durum PHP sunucusu tarafından yönetilen PHP oturumuna da yansıtılır;
  • Sunucuyla aynı PHP oturum çerezini kullanarak, [nuxt] sunucusunun A eylemini takip eden [nuxt] istemcisinin B eylemi, PHP sunucusunu[nuxt] sunucusu tarafından bırakılan E durumunu bulabilir ve böylece [nuxt] sunucusu tarafından halihazırda yapılmış olan çalışmadan yararlanabilir;
  • eğer istemci [nuxt]’in B eyleminin ardından, sunucu [nuxt]’in C eylemi gelirse, daha önce olduğu gibi bu eylem de istemci [nuxt]’in B eylemi tarafından yapılan çalışmaya dayanabilecektir;

[nuxt] istemcisinin tarayıcısının, vergi hesaplama sunucusu PHP ile iletişim kurabilmesi için, etki alanları arası çağrılara izin veren bu sunucunun 14. sürümünü kullanacağız, yani bir tarayıcıdan PHP sunucusuna yapılan çağrılar. [nuxt] sunucusundan PHP sunucusuna yapılan çağrılar ise etki alanları arası çağrılar değildir. Bu kavram yalnızca bir tarayıcıdan yapılan çağrılar için geçerlidir.

Önceki [Dao] sınıfının oluşturucu koduna geri dönelim:


// oluşturucu
  constructor(axios) {
    this.axios = axios;
    // oturum çerezi
    this.sessionCookieName = "PHPSESSID";
    this.sessionCookie = '';
}
  • 5. ve 6. satırlar, vergi hesaplama sunucusuyla olan PHP oturum çerezine karşılık gelir;

Yukarıdaki PHP oturum çerezinin yönetimi, [nuxt] sunucusu için uygun değildir: [dao] katmanı, [nuxt] sunucusuna yapılan her yeni istekle birlikte örneklenir. Hatırlanacağı üzere, [nuxt] sunucusundan bir sayfa istemek, [nuxt] uygulamasını sıfırlamakla eşdeğerdir. Dolayısıyla, [nuxt] sunucusu tarafından veri sunucusuna yapılan ilk isteğin ardından, [dao] katmanına ait PHP oturum çerezi sıfırlandığında, aynı [nuxt] sunucusundan gelen bir sonraki HTTP isteği sırasında bu değer kaybolur, çünkü bu arada [dao] katmanı yeniden oluşturulmuş, oluşturucu yeniden çalıştırılmış ve PHP oturum çerezi boş dizeyle sıfırlanmıştır (6. satır);

Bir çözüm, sunucunun [dao] katmanı için başka bir oluşturucu kullanmaktır:


// oluşturucu
  constructor(axios, phpSessionCookie) {
    // axios kütüphanesi
    this.axios = axios
    // oturum çereğinin değeri
    this.phpSessionCookie = phpSessionCookie
    // sunucunun oturum çerezinin adı PHP
    this.phpSessionCookieName = 'PHPSESSID'
  }
  • 2. satır: Bu sefer PHP oturum çerezi, veri sunucusunun [dao] katmanının oluşturucusuna sağlanacaktır;

[nuxt] sunucusu, bu PHP oturum çerezini kendi [dao] katmanının oluşturucusuna nasıl sağlayabilir? PHP oturum çerezini, tarayıcı ile [nuxt] sunucusu arasında alışverişi yapılan [nuxt] oturum çerezinde depolayacağız. Süreç şu şekildedir:

  1. [nuxt] uygulaması başlatılır;
  2. [nuxt] sunucusu, PHP sunucusuna HTTP numaralı ilk isteğini gönderdiğinde, aldığı PHP oturum çerezini, [nuxt] istemcisiyle değiş tokuş ettiği [nuxt] oturum çerezine kaydeder;
  3. [nuxt] istemcisini barındıran tarayıcı, bu [nuxt] oturum çerezini alır ve dolayısıyla [nuxt] sunucusuna yapılan her yeni istekte bunu sistematik olarak geri gönderir;
  4. [nuxt] sunucusu, PHP sunucusuna yeni bir istek göndermek zorunda kaldığında, tarayıcının kendisine gönderdiği [nuxt] oturum çerezinde PHP oturum çerezini bulacaktır. Ardından bunu PHP sunucusuna gönderecektir;

Burada iki oturum çerezi vardır ve bunları karıştırmamak gerekir:

  • [nuxt] sunucusu ile [nuxt] istemci tarayıcısı arasında alışverişi yapılan [nuxt] oturum çerezi;
  • PHP oturum çerezi, [nuxt] sunucusu ile PHP sunucusu arasında veya [nuxt] istemcisi ile PHP sunucusu arasında alışverişe konu olurX;

Şimdi [Dao] sınıfının yöntem koduna geri dönelim. Bu kodda, vergi hesaplama sunucusuyla olan PHP oturumunu kapatan bir işlev bulunmamaktadır. Bunu ekliyoruz:


// vergi hesaplama oturumunun sonu
  async finSession() {
    // istek seçenekleri HHTP  [get /main.php?action=fin-session]
    const options = {
      method: 'GET',
      // URL parametreleri
      params: {
        action: 'fin-session'
      }
    }
    // HTTP sorgusunun yürütülmesi
    const data = await this.getRemoteData(options)
    // sonuç
    return data
  }

Testler sırasında, 12. satırda çağrılan [getRemoteData] işlevinin [finSession] yöntemi için uygun olmadığı ortaya çıkıyor:


async  getRemoteData(options) {
    // oturum çerezi için
    if (!options.headers) {
      options.headers = {};
    }
    options.headers.Cookie = this.sessionCookie;
    // HTTP isteğinin yürütülmesi
    let response;
    try {
      // asenkron istek
      response = await this.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;
      }
    }
    // yanıt, 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 tabloda oturum çerezi aranıyor
      let trouvé = false;
      let i = 0;
      while (!trouvé && i < setCookie.length) {
        // oturum çerezi aranıyor
        const results = RegExp('^(' + this.sessionCookieName + '.+?);').exec(setCookie[i]);
        if (results) {
          // oturum çerezini kaydediyoruz
          // eslint-disable-next-line require-atomic-updates
          this.sessionCookie = results[1];
          // bulundu
          trouvé = true;
        } else {
          // sonraki öğe
          i++;
        }
      }
    }
    // sunucu yanıtı [response.data]'te
    return response.data;
  }
  • 30-43. satırlar: [PHPSESSID=xxx] çerezi aranır. Bulunursa, sınıfa kaydedilir (36. satır);

Bu kod, yeni [finSession] yöntemine uygun değildir; çünkü [fin-session] eyleminde, PHP sunucusu [PHPSESSID] adında iki çerez gönderir. Aşağıda, [Postman] istemcisiyle elde edilen bir örnek yer almaktadır:

Image

  • [1]'te, [Postman] istemcisinin isteği;
  • [3]'e, PHP sunucusunun yanıtı;
  • [4]'te, sunucunun yanıtının başlıkları HTTP, sunucunun yanıtı ise PHP;

Image

  • [5]'te, PHP sunucusu önce mevcut PHP oturumunu sildiğini belirtir;
  • [6]'te, PHP sunucusu yeni oturumun çerezini (PHP) gönderir;

Mevcut kodda, [getRemoteData] işlevi [5] çerezini alıyor, oysa kaydedilmesi gereken çerez [6]'tir.

Bu nedenle, [getRemoteData] işlevinin kodunda değişiklik yapılması gerekir:


async getRemoteData(options) {
    // PHP oturum çerezi var mı?
    if (this.phpSessionCookie) {
      // Başlıklar var mı?
      if (!options.headers) {
        // boş bir nesne oluşturuluyor
        options.headers = {}
      }
      // PHP oturum çerezinin başlığı
      options.headers.Cookie = this.phpSessionCookie
    }
    // isteğin yürütülmesi HTTP
    let response
    try {
      // asenkron istek
      response = await this.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
      }
    }
    // yanıt, sunucudan gelen HTTP yanıtının tamamıdır (HTTP başlıkları + yanıtın kendisi)
    // Alınan çerezler arasında PHP oturum çerezi aranıyor
    // alınan tüm çerezler
    const cookies = response.headers['set-cookie']
    if (cookies) {
      // çerezler bir dizidir
      // bu dizide PHP oturum çerezi aranıyor
      let trouvé = false
      let i = 0
      while (!trouvé && i < cookies.length) {
        // PHP oturum çerezi aranıyor
        const results = RegExp('^(' + this.phpSessionCookieName + '.+?)$').exec(cookies[i])
        if (results) {
          // PHP oturum çerezi kaydediliyor
          const phpSessionCookie = results[1]
          // içinde [deleted] kelimesi var mı?
          const results2 = RegExp(this.phpSessionCookieName + '=deleted').exec(phpSessionCookie)
          if (!results2) {
            // Doğru oturum çerezi PHP var
            this.phpSessionCookie = phpSessionCookie
            // bulundu
            trouvé = true
          } else {
            // aşağıdaki öğe
            i++
          }
        } else {
          // sonraki öğe
          i++
        }
      }
    }
    // sunucunun yanıtı [response.data]'te
    return response.data
  }
  • 41. satır: [PHPSESSID] adlı bir çerez bulundu. Bu çerez yerel olarak kaydedilir;
  • 43. satır: Kaydedilen çerezde [PHPSESSID=deleted] dizesi olup olmadığına bakılır;
  • 46. satır: Cevap hayır ise, doğru çerez olan [PHPSESSID] bulunmuştur. Bu çerez sınıfa kaydedilir;

[getRemoteData] işlevinden sonra, PHP oturum çerezi sınıfta, [this.phpSessionCookie]'te saklanır. HTTP sınıfının, [nuxt] sunucusundan gelen her yeni istekle birlikte örneklendiği belirtilmişti. Dolayısıyla, PHP oturum çerezi sınıftan çıkarılmalıdır. Bunun için sınıfa yeni bir yöntem eklenir:


// oturum çerezine erişim PHP
  getPhpSessionCookie() {
    return this.phpSessionCookie
}
  • [nuxt] sunucusu, [dao] katmanından bir eylem talep eder ve varsa, PHP oturum çerezini bu katmanın oluşturucusuna sağlar;
  • eylem gerçekleştirildikten sonra, [nuxt] sunucusu, önceki [getPhpSessionCookie] yöntemini kullanarak [dao] katmanı tarafından saklanan PHP oturum çerezini alır. Bu çerez, öncekiyle aynı olabilir veya farklı olabilir. İkinci durum iki durumda ortaya çıkar:
    • [initSession] yönteminin yürütülmesi sırasında (daha önce PHP oturum çerezi yoktu);
    • [finSession] yönteminin yürütülmesi sırasında (PHP sunucusu, PHP oturum çerezini değiştirir);

PHP oturum çerezi ile ilgili bir özelliğe dikkat çekelim. [nuxt] sunucusu, bu çerezi PHP sunucusundan her zaman almaz. Aslında, bu sunucu çerezi yalnızca bir kez gönderir. Daha sonra bir daha göndermez. [getRemoteData] ve [getPhpSessionCookie] kodlarına bakıldığında, PHP sunucusu oturum çerezi göndermediğinde, [getPhpSessionCookie] işlevi, yapıcıya sağlanan PHP oturum çerezini geri gönderir. Böylelikle sunucu, PHP sunucusuna her zaman, bu sunucunun kendisine gönderdiği en son oturum çerezi olan PHP’i gönderir.

15.5.2. [nuxt] istemcisinin [dao] katmanı

Image

Tarayıcıda çalışan [nuxt] müşterisi için, |Introduction au framework VUE.JS par l’exemple| belgesindeki [Dao] sınıfının kodunu kullanıyoruz:


"use strict";

// ithalatlar
import qs from "qs";

class Dao {
  // oluşturucu
  constructor(axios) {
    this.axios = axios;
  }

  // oturumu başlat
  async initSession() {
    // 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 this.getRemoteData(options);
  }

  async authentifierUtilisateur(user, password) {
    // HHTP sorgusunun 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 parametreleri
      params: {
        action: "authentifier-utilisateur"
      }
    };
    // HTTP sorgusunun yürütülmesi
    return await this.getRemoteData(options);
  }

  async getAdminData() {
    // HHTP sorgusunun seçenekleri  [get /main.php?action=get-admindata]
    const options = {
      method: "GET",
      // URL parametreleri
      params: {
        action: "get-admindata"
      }
    };
    // HTTP isteğinin yürütülmesi
    const data = await this.getRemoteData(options);
    // sonuç
    return data;
  }

  async getRemoteData(options) {
    // HTTP sorgusunun yürütülmesi
    let response;
    try {
      // asenkron istek
      response = await this.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önderilir
        throw error;
      }
    }
    // response, sunucudan gelen HTTP yanıtının tamamıdır (HTTP başlıkları + yanıtın kendisi)
    // sunucunun yanıtı [response.data] içinde yer alıyor
    return response.data;
  }
}

// sınıfın dışa aktarımı
export default Dao;

Bu kod, [nuxt] sunucusunun [dao] katmanından, PHP oturum çerezini vergi hesaplama sunucusuyla yönetmemesi bakımından farklıdır: bunu tarayıcı yapar.

[nuxt] sunucusunun [dao] katmanında yaptığımız gibi, bir [finSession] yöntemi ekleyeceğiz:


// vergi hesaplama oturumunun sonu
  async finSession() {
    // istek seçenekleri HHTP  [get /main.php?action=fin-session]
    const options = {
      method: 'GET',
      // URL parametreleri
      params: {
        action: 'fin-session'
      }
    }
    // HTTP isteğinin yürütülmesi
    const data = await this.getRemoteData(options)
    // sonuç
    return data
  }

[nuxt] istemcisi bu yöntemi çalıştırdığında, [nuxt] sunucusu gibi iki adet PHP oturum çerezi alır. Aslında bunları alan tarayıcıdır ve durumu doğru bir şekilde yönetir: yalnızca vergi hesaplama sunucusu tarafından başlatılan yeni oturum çerezi olan PHP’i saklar. Dolayısıyla, [nuxt] istemcisinin PHP sunucusuna yapacağı bir sonraki işlemde, PHP oturum çerezi doğru olacaktır; çünkü bunu gönderen tarayıcıdır. Ancak bir sorun var: [nuxt] sunucusu, PHP oturum çerezinin değiştiğinden haberdar değildir. PHP sunucusuyla yaptığı iletişimde, artık mevcut olmayan PHP oturum çerezini gönderecek ve bu da sorunlara yol açacaktır. [nuxt] istemcisinin, [nuxt] sunucusuna PHP oturum çerezinin değiştiğini bildirmesi ve bu çerezi sunucuya iletmesi gerekir. Bunu nasıl yapabileceğini biliyoruz: [nuxt] oturum çerezi aracılığıyla; bu çerez, istemci ile sunucu arasında [nuxt] olarak paylaşılan çerezdir. [nuxt] istemcisinin, yeni oturum çerezi PHP'i elde etmenin en az iki yolu vardır:

  1. tarayıcıdan talep ederek;
  2. yeni oturum çerezini (PHP) nasıl alacağını bilen sunucunun [getRemoteData] yöntemini kullanarak;

Zaten hazır olduğu için ikinci çözümü kullanacağız. [nuxt] istemcisinin [getRemoteData] yöntemi şu şekilde olur:


async getRemoteData(options) {
    // HTTP isteğinin yürütülmesi
    let response
    try {
      // asenkron istek
      response = await this.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
      }
    }
    // yanıt, sunucudan gelen HTTP yanıtının tamamıdır (HTTP başlıkları + yanıtın kendisi)
    // Alınan çerezler arasında PHP oturum çerezi aranıyor
    // alınan tüm çerezler
    const cookies = response.headers['set-cookie']
    if (cookies) {
      // çerezler bir dizidir
      // bu dizide PHP oturum çerezi aranıyor
      let trouvé = false
      let i = 0
      while (!trouvé && i < cookies.length) {
        // PHP oturum çerezi aranıyor
        const results = RegExp('^(' + this.phpSessionCookieName + '.+?)$').exec(cookies[i])
        if (results) {
          // PHP oturum çerezi kaydediliyor
          const phpSessionCookie = results[1]
          // içinde [deleted] kelimesi var mı?
          const results2 = RegExp(this.phpSessionCookieName + '=deleted').exec(phpSessionCookie)
          if (!results2) {
            // Doğru oturum çerezi PHP var
            this.phpSessionCookie = phpSessionCookie
            // bulundu
            trouvé = true
          } else {
            // aşağıdaki öğe
            i++
          }
        } else {
          // sonraki öğe
          i++
        }
      }
    }
    // sunucunun yanıtı [response.data]'te
    return response.data
  }

[getRemoteData]'te, yalnızca PHP sunucusunun PHP oturum çerezini arama yanıtını işleyen kodu tuttuk. PHP oturum çerezini PHP sunucusuna yapılan isteğe dahil eden kod korunmamıştır, çünkü bu işlemi [nuxt] istemcisini barındıran tarayıcı üstlenmektedir.

PHP oturum çerezi, [nuxt] istemcisi tarafından alındığında, [nuxt] sunucusunun bundan yararlanabilmesi için bu çerez [nuxt] oturumuna eklenmelidir. Bunu gerçekleştiren [dao] katmanı değildir; ancak bu katman, sakladığı PHP oturum çerezine bir yöntem aracılığıyla erişim sağlar:


// oturum çerezine erişim PHP
  getPhpSessionCookie() {
    return this.phpSessionCookie
}

[getPhpSessionCookie] işlevi her zaman geçerli bir oturum çerezi döndürmez:

  • burada, [nuxt] istemcisinin [dao] katmanının kalıcı olduğunu unutmamak gerekir. Bu katman bir kez oluşturulduktan sonra bellekte kalır;
  • PHP sunucusu, PHP oturum çerezini [nuxt] istemcisine göndermediği sürece, [nuxt] istemcisinin [getPhpSessionCookie] işlevi, [undefined] değerini döndürür;
  • PHP sunucusu, PHP oturum çerezini [nuxt] istemcisine gönderdiğinde, bu çerez [this.phpSessionCookie]'te saklanır ve PHP sunucusu tarafından gönderilen yeni bir oturum çerezi PHP ile değiştirilene kadar orada kalır. [nuxt] istemcisinin [getPhpSessionCookie] işlevi, bu durumda en son alınan PHP oturum çerezini döndürür;

[nuxt] istemcisinin [dao] katmanı, [nuxt] sunucusunkinden yalnızca bir noktada farklılık gösterir: PHP oturum çerezini kendisi göndermez, çünkü bunu tarayıcı yapar. Bununla birlikte, bunların yazılma mantıkları farklı olduğu için iki ayrı [dao] katmanını korumayı tercih ettik.

15.6. [nuxt] oturumu

Image

[nuxt] oturumu (istemci ile Nuxt sunucusu arasında), aşağıdaki [session] nesnesine kapsüllenecektir:


/* eslint-disable no-console */
// oturum tanımı
const session = {
  // oturum içeriği
  value: {
    // başlatılmamış depo
    initStoreDone: false,
    // Vuex depolama alanı değeri
    store: ''
  },
  // oturumun çerezde kaydedilmesi
  save(context) {
    // depolama alanının oturuma kaydedilmesi
    this.value.store = context.store.state
    console.log('nuxt-session save=', this.value)
    // oturum değerinin kaydedilmesi
    context.app.$cookies.set('nuxt-session', this.value, { path: context.base, maxAge: context.env.maxAge })
  },
  // oturumun sıfırlanması
  reset(context) {
    console.log('nuxt-session reset')
    // depolama alanının sıfırlanması
    context.store.commit('reset')
    // yeni deponun oturumda kaydedilmesi ve oturumun kaydedilmesi
    this.save(context)
  }
}
// oturumun dışa aktarılması
export default session
  • 5-10. satırlar: oturumun tek bir [value] özelliği vardır ve bu özelliğin iki alt özelliği bulunur:
    • [initStoreDone], deponun başlatılıp başlatılmadığını gösterir;
    • [store]: Uygulamanın Vuex depolama alanının [store.state] değeri;
  • 12-18. satırlar: [save] yöntemi, [nuxt] oturumunu bir çerezde kaydetmek için kullanılır. Burada çerezi yönetmek için [cookie-universal-nuxt] kütüphanesi kullanılır. [nuxt] oturum çerezinin adının [nuxt-session] olduğu dikkatinizi çekecektir (17. satır);
  • 20-26. satırlar: [reset] yöntemi, [nuxt] oturumunu sıfırlar;
    • 23. satır: Vuex depolama alanı sıfırlanır ve ardından oturumda kaydedilir (25. satır);

15.7. [nuxt] oturum yönetimi eklentileri

Image

15.7.1. serveur'in oturum yönetimi eklentisi [nuxt] [nuxt]

Uygulama başlatıldığında, ilk olarak [nuxt] sunucusu çalışır. Dolayısıyla, [nuxt] oturumunu başlatacak olan da bu sunucudur. [server/plgSession] komut dosyası şöyledir:


/* eslint-disable no-console */

// oturumun içe aktarılması
import session from '@/entities/session'

export default (context, inject) => {
  // sunucu oturum yönetimi
  console.log('[plugin server plgSession]')

  // mevcut bir oturum var mı?
  const value = context.app.$cookies.get('nuxt-session')
  if (!value) {
    // yeni oturum
    console.log("[plugin server plgSession], démarrage d'une nouvelle session")
  } else {
    // mevcut oturum
    console.log("[plugin server plgSession], reprise d'une session existante")
    session.value = value
  }

  // [context, Vue] içine, oturumu geçerli hale getirecek bir işlev enjekte ediliyor
  inject('session', () => session)
}
  • 4. satır: [nuxt] oturum kodunu içe aktarıyoruz;
  • 11. satır: [nuxt] oturum çerezinin değeri alınır;
  • 12-15. satırlar: [nuxt] oturum çerezi mevcut değilse, 4. satırda içe aktarılan [nuxt] oturumu yeterlidir. Yapılacak başka bir şey yoktur;
  • satır 15-19: [nuxt] oturum çerezi mevcutsa, 18. satırda bu çerezin değeri 4. satırda içe aktarılan oturuma kaydedilir;
  • 22. satır: Oturum ya başlatıldı ya da geri yüklendi. [$session] işlevi aracılığıyla kullanılabilir hale getirilir;

15.7.2. [nuxt] istemcisinin oturum yönetimi eklentisi [nuxt]

[client/plgSession] komut dosyası şu şekildedir:


/* eslint-disable no-console */

// oturumun içe aktarılması
import session from '@/entities/session'

export default (context, inject) => {
  // istemci oturumunun yönetimi
  console.log('[plugin client plgSession], reprise de la session [nuxt] du serveur')
  // Nuxt sunucusundan mevcut oturumu alıyoruz
  session.value = context.app.$cookies.get('nuxt-session')

  // [context, Vue] dosyasına, oturumu geçerli hale getirecek bir işlev ekleniyor
  inject('session', () => session)
}
  • 4. satır: [nuxt] oturumu içe aktarılır;
  • 10. satır: [nuxt-session] çerezinden geçerli [nuxt] oturumu alınır;
  • 13. satır: 4. satırda içe aktarılan [nuxt] oturumu, enjekte edilen [$session] işlevi aracılığıyla geri verilir;

15.8. [dao] katmanlarının eklentileri

Image

15.8.1. [nuxt] istemcisinin [dao] katman eklentisi

[client/plgDao] komut dosyası şöyledir:


/* eslint-disable no-console */
// [Dao] katmanına bir erişim noktası oluşturuluyor
import Dao from '@/api/client/Dao'
export default (context, inject) => {
  // axios yapılandırması
  context.$axios.defaults.timeout = context.env.timeout
  context.$axios.defaults.baseURL = context.env.baseURL
  context.$axios.defaults.withCredentials = context.env.withCredentials
  // katmanın örneklenmesi [dao]
  const dao = new Dao(context.$axios)
  // [$dao] işlevinin bağlama enjeksiyonu
  inject('dao', () => dao)
  // günlük
  console.log('[fonction client $dao créée]')
}
  • 3. satır: [nuxt] istemcisinin [dao] katmanı içe aktarılır;
  • 6-8. satırlar:[context.$axios] nesnesi yapılandırılır; bu nesne, [nuxt] istemcisinin [dao] katmanından gelen HTTP isteklerini, [nuxt.config] dosyasındaki bilgilerle gerçekleştirecektir:

// ortam
  env: {
    // axios yapılandırması
    timeout: 2000,
    withCredentials: true,
    baseURL: 'http://localhost/php7/scripts-web/impots/version-14',
    // oturum çerezi yapılandırması [nuxt]
    maxAge: 60 * 5
  }
  • 10. satır: [nuxt] istemcisinin [dao] katmanı örneklenir;
  • 12. satır: [$dao] işlevi, bağlam ve istemci sayfalarına eklenir. Bu işlev, 10. satırdaki [dao] katmanına erişim sağlar;

Dolayısıyla, [nuxt] istemcisinin çalıştırılması sırasında [dao] katmanına erişmek için şu komutu yazmamız gerekir:

  • [context.app.$dao()] (bağlamın bilindiği durumlarda);
  • [this.$dao()], [Vue.js] sayfasında;

15.8.2. serveur ve [nuxt]'in [dao] katman eklentisi

[server/plgDao] komut dosyası şöyledir:


/* eslint-disable no-console */
// [Dao] katmanına bir erişim noktası oluşturuluyor
import Dao from '@/api/server/Dao'
export default (context, inject) => {
  // axios yapılandırması
  context.$axios.defaults.timeout = context.env.timeout
  context.$axios.defaults.baseURL = context.env.baseURL
  // oturum çerezi alınır
  const store = context.app.$session().value.store
  const phpSessionCookie = store ? store.phpSessionCookie : ''
  console.log('session=', context.app.$session().value, 'phpSessionCookie=', phpSessionCookie)
  // [dao] katmanının örneklenmesi
  const dao = new Dao(context.$axios, phpSessionCookie)
  // [$dao] işlevinin bağlama enjeksiyonu
  inject('dao', () => dao)
  // günlük kaydı
  console.log('[fonction server $dao créée]')
}
  • 3. satır: [nuxt] sunucusundaki [dao] katmanı içe aktarılır;
  • 6-7. satırlar:[context.$axios] nesnesi yapılandırılır; bu nesne, [nuxt] sunucusundaki [dao] katmanından gelen HTTP isteklerini, [nuxt.config] dosyasındaki bilgilerle gerçekleştirecektir:

// ortam
  env: {
    // axios yapılandırması
    timeout: 2000,
    withCredentials: true,
    baseURL: 'http://localhost/php7/scripts-web/impots/version-14',
    // oturum çerezi yapılandırması [nuxt]
    maxAge: 60 * 5
  }
  • 9. satır: [nuxt] uygulamasının depolama alanını alırız;
  • 10. satır: Mağaza varsa, PHP oturum çerezini alınır; çünkü bu çereze, [nuxt] sunucusundaki [dao] katmanını oluşturmak için ihtiyaç vardır;
  • 13. satır: [nuxt] sunucusunun [dao] katmanını oluştururuz;
  • 15. satır: [$dao] işlevi, [nuxt] sunucusunun bağlamına ve sayfalarına enjekte edilir. Bu işlev, 13. satırdaki [dao] katmanına erişim sağlar;

Dolayısıyla, [nuxt] sunucusu çalıştırıldığında bu sunucunun [dao] katmanına erişmek için şunu yazacağız:

  • [context.app.$dao()] (bağlamın bilindiği durumlarda);
  • [this.$dao()], bir [Vue.js] sayfasında;

15.9. Vuex deposu

Image

[Vuex] depolama alanı, [pages, client, serveur] uygulamasının farklı bileşenleri tarafından paylaşılması gereken tüm verileri, bu verilerin reaktif olması gerekmeksizin depolayacaktır.


/* eslint-disable no-console */

// mağaza durumu
export const state = () => ({
  // jSON oturumu başlatıldı
  jsonSessionStarted: false,
  // kullanıcı kimliği doğrulandı
  userAuthenticated: false,
  // oturum çerezi PHP
  phpSessionCookie: '',
  // adminData
  adminData: ''
})

// depo değişiklikleri
export const mutations = {
  // durumun değiştirilmesi
  replace(state, newState) {
    for (const attr in newState) {
      state[attr] = newState[attr]
    }
  },
  // depolama alanının sıfırlanması
  reset() {
    this.commit('replace', { jsonSessionStarted: false, userAuthenticated: false, phpSessionCookie: '', adminData: '' })
  }
}

// depolama işlemleri
export const actions = {
  nuxtServerInit(store, context) {
    // bu kodu kim yürütür?
    console.log('nuxtServerInit, client=', process.client, 'serveur=', process.server, 'env=', context.env)
    // oturum başlatma
    initStore(store, context)
  }
}

function initStore(store, context) {
  // başlatılacak depo
  // oturum alınır
  const session = context.app.$session()
  // oturum daha önce başlatılmış mı?
  if (!session.value.initStoreDone) {
    // yeni bir depo başlatılıyor
    console.log("nuxtServerInit, initialisation d'une nouvelle session")
    // depolama alanı oturuma ekleniyor
    session.value.store = store.state
    // depolama alanı artık başlatıldı
    session.value.initStoreDone = true
  } else {
    console.log("nuxtServerInit, reprise d'un store existant")
    // depolama alanı, oturumdaki depolama alanıyla güncelleniyor
    store.commit('replace', session.value.store)
  }
  // oturum kaydediliyor
  session.save(context)
  // günlük
  console.log('initStore terminé, store=', store.state)
}

Depoda saklanan veriler şunlardır:

  • 6. satır: [jsonSessionStarted], jSON oturumunun PHP sunucusuyla başlatılması başarılı olur olmaz, bu başlatma işlemi ister istemci ister [nuxt] sunucusu tarafından yapılmış olsun. Bu başlatma işleminin tamamlanmasının ardından, PHP sunucusuyla olan oturum çerezi alınacak ve 10. satırdaki [phpSessionCookie] özelliğine yerleştirilecektir;
  • 8. satır: [userAuthenticated], PHP sunucusuna yapılan kimlik doğrulama başarılı olur olmaz, bu işlem ister istemci ister [nuxt] sunucusu tarafından yapılmış olsun, "true" olarak ayarlanacaktır;
  • 12. satır: [adminData], kimlik doğrulama başarılı olduktan sonra PHP sunucusundan alınan [adminData] değeri olacaktır;
  • satır 18-22: [replace] ataması, önceki özellikleri parametre olarak geçirilen bir nesnenin özellikleriyle başlatır;
  • satır 24-26: [reset] mutasyonu, deponun özelliklerini başlangıç değerlerine geri döndürür;
  • satır 31-37: [nuxtServerInit] işlevi, görevini [initStore] işlevine devreder;
  • satır 39-60: [initStore] işlevinin iki görevi vardır:
    • eğer depo henüz başlatılmamışsa, başlatılır ve oturuma eklenir;
    • depolama alanı daha önce başlatılmışsa, değeri [nuxt] oturumundan alınır;
  • satır 42: nuxt oturumu alınır;
  • 44. satır: deponun başlatılıp başlatılmadığına bakılır:
    • değilse, başlangıç store'u oturuma eklenir (satır 48);
    • ardından 50. satırda, deponun başlatıldığını belirtilir;
  • satır 51-55: depo başlatılmışsa, satır 54'te bu depo kullanılarak oturumda bulunan değere göre depo başlatılır;
  • 57. satır: her durumda, oturum, içerdiği depolama alanı ile birlikte [nuxt-session] çerezine kaydedilir;

15.10. [plgEventBus] eklentisi

Image

Bu eklenti, [nuxt] istemcisinin bağlamına enjekte edilen [$eventBus] işlevi aracılığıyla [nuxt] istemcisine bir olay veriyolunu erişilebilir hale getirmeyi amaçlamaktadır. Bunu [nuxt] sunucu bağlamına enjekte etmenin bir anlamı yoktur, çünkü bu sunucu olayları yönetemez. Bununla birlikte, sunucu tarafında enjekte edip kullanmanın bir hata oluşturmadığını daha önce görmüştük.


/* eslint-disable no-console */
// görünümler arasında bir olay veriyolu oluşturulur
import Vue from 'vue'
export default (context, inject) => {
  // olay veriyolu
  const eventBus = new Vue()
  // [$eventBus] işlevinin bağlama enjeksiyonu
  inject('eventBus', () => eventBus)
  // günlük kaydı
  console.log('[fonction $eventBus créée]')
}

Bu eklentiyle daha önce “bağlantı” başlıklı paragrafta karşılaşmıştık. [$eventBus] işlevi, bağlamın mevcut olduğu yerlerde şu notasyonlar aracılığıyla istemcide kullanılabilir olacaktır:

  • [context.app.$eventBus()] (bağlam mevcut olduğunda);
  • [this.$eventBus()], istemcinin [Vue.js] sayfalarında;

15.11. [nuxt] uygulamasının bileşenleri

Image

[layout] bileşeni, önceki örneklerdeki bileşendir:


<!-- görünümlerin düzenlenmesi -->
<template>
  <!-- satır -->
  <div>
    <b-row>
      <!-- üç sütunlu alan -->
      <b-col v-if="left" cols="3">
        <slot name="left" />
      </b-col>
      <!-- dokuz sütunlu alan -->
      <b-col v-if="right" cols="9">
        <slot name="right" />
      </b-col>
    </b-row>
  </div>
</template>

<script>
export default {
  // ayarlar
  props: {
    left: {
      type: Boolean
    },
    right: {
      type: Boolean
    }
  }
}
</script>

[navigation] bileşeni şöyledir:


<template>
  <!-- üç seçenekli Bootstrap menüsü -->
  <b-nav vertical>
    <b-nav-item to="/authentification" exact exact-active-class="active">
      Authentification
    </b-nav-item>
    <b-nav-item to="/get-admindata" exact exact-active-class="active">
      Requête AdminData
    </b-nav-item>
    <b-nav-item to="/fin-session" exact exact-active-class="active">
      Fin session impôt
    </b-nav-item>
  </b-nav>
</template>

15.12. [nuxt] uygulamasının düzenleri

Image

15.12.1. [default]

[default] düzeni, bağlantı paragrafındaki [nuxt-11] örneği için kullanılan düzenidir:


<template>
  <div class="container">
    <b-card>
      <!-- bir mesaj -->
      <b-alert show variant="success" align="center">
        <h4>[nuxt-12] : requêtes HTTP avec axios</h4>
      </b-alert>
      <!-- yönlendirmenin geçerli görünümü -->
      <nuxt />
      <!-- bekleme mesajı -->
      <b-alert v-if="showLoading" show variant="light">
        <strong>Requête au serveur de données en cours...</strong>
        <div class="spinner-border ml-auto" role="status" aria-hidden="true"></div>
      </b-alert>
      <!-- asenkron işlem hatası -->
      <b-alert v-if="showErrorLoading" show variant="danger">
        <strong>La requête au serveur de données a échoué : {{ errorLoadingMessage }}</strong>
      </b-alert>
    </b-card>
  </div>
</template>

<script>
/* eslint-disable no-console */
export default {
  name: 'App',
  data() {
    return {
      showLoading: false,
      showErrorLoading: false
    }
  },
  // yaşam döngüsü
  beforeCreate() {
    console.log('[default beforeCreate]')
  },
  created() {
    console.log('[default created]')
    if (process.client) {
      // [loading] olayını dinliyoruz
      this.$eventBus().$on('loading', this.mShowLoading)
      // ve [errorLoadingMessage] olayını dinliyoruz
      this.$eventBus().$on('errorLoading', this.mShowErrorLoading)
    }
  },
  beforeMount() {
    console.log('[default beforeMount]')
  },
  mounted() {
    console.log('[default mounted]')
  },
  methods: {
    // bekleyen mesaj yönetimi
    mShowLoading(value) {
      console.log('[default mShowLoading], showLoading=', value)
      this.showLoading = value
    },
    // asenkron işlem hatası
    mShowErrorLoading(value, errorLoadingMessage) {
      console.log('[default mShowErrorLoading], showErrorLoading=', value, 'errorLoadingMessage=', errorLoadingMessage)
      this.showErrorLoading = value
      this.errorLoadingMessage = errorLoadingMessage
    }
  }
}
</script>
  • 10-14. satırlar: [nuxt] istemcisinin asenkron işleminin tamamlanmasını bekleme mesajını görüntüler;
  • 15-18. satırlar: asenkron işlemin olası hata mesajını görüntüler;
  • 37. satır: [default] sayfasındaki [created] işlevi, sayfaların [mounted] işlevinden önce yürütülür;
  • satır 39: Yürütücü [nuxt] istemcisi ise, [default] sayfası olayları dinlemeye başlar:
    • [loading], bir bekleme durumunun başlangıcını veya sonunu bildirir. Bu durumda [mShowLoading] işlevi yürütülür;
    • [errorLoading], bir hata mesajının görüntülenmesi gerektiğini bildirir. Bu durumda [mShowErrorLoading] işlevi yürütülür;
  • [nuxt] sayfaları:
    • olay veriyolunda [‘loading’, true] olayını yayınlayarak bekleme mesajını görüntüler;
    • olay veriyolunda [‘loading’, false] olayını yayınlayarak bekleme mesajını gizler;
    • olay veriyolunda [‘errorLoading’, true] olayını yayınlayarak bir hata mesajı görüntüler;
    • olay veriyolunda [‘errorLoading’, false] olayını yayınlayarak hata mesajını gizler;

15.12.2. [error]

[error] düzeni, bir sistem hata mesajı (geliştirici tarafından yönetilmeyen) görüntüler:


<!-- HTML görünümünün tanımı -->
<template>
  <!-- sayfa düzeni -->
  <Layout :left="true" :right="true">
    <!-- sağ sütundaki uyarı -->
    <template slot="right">
      <!-- pembe arka planlı mesaj -->
      <b-alert show variant="danger" align="center">
        <h4>L'erreur suivante s'est produite : {{ JSON.stringify(error) }}</h4>
      </b-alert>
    </template>
    <!-- sol sütundaki gezinme menüsü -->
    <Navigation slot="left" />
  </Layout>
</template>

<script>
/* eslint-disable no-undef */
/* eslint-disable no-console */
/* eslint-disable nuxt/no-env-in-hooks */

import Layout from '@/components/layout'
import Navigation from '@/components/navigation'

export default {
  name: 'Error',
  // kullanılan bileşenler
  components: {
    Layout,
    Navigation
  },
  // özellik [props]
  props: { error: { type: Object, default: () => 'waiting ...' } },
  // yaşam döngüsü
  beforeCreate() {
    // istemci ve sunucu
    console.log('[error beforeCreate]')
  },
  created() {
    // istemci ve sunucu
    console.log('[error created, error=]', this.error)
  },
  beforeMount() {
    // sadece istemci
    console.log('[error beforeMount]')
  },
  mounted() {
    // sadece istemci
    console.log('[error mounted]')
  }
}
</script>

15.13. [nuxt] sunucusu tarafından yürütülen [index] sayfası

Image

[index.vue] sayfası, yalnızca [nuxt] sunucusu üzerinden erişilebilir olma özelliğine sahiptir. Kullanıcıya, [nuxt] istemcisi üzerinden bu sayfaya erişebilmesi için herhangi bir bağlantı sunulmamaktadır. Sayfanın kodu şöyledir:


<!-- ana sayfa -->
<template>
  <Layout :left="true" :right="true">
    <!-- gezinme -->
    <Navigation slot="left" />
    <!-- mesaj-->
    <b-alert slot="right" show variant="warning">Initialisation de la session avec le serveur de calcul de l'impôt : {{ result }} </b-alert>
  </Layout>
</template>

<script>
/* eslint-disable no-console */

import Navigation from '@/components/navigation'
import Layout from '@/components/layout'

export default {
  name: 'InitSession',
  // kullanılan bileşenler
  components: {
    Layout,
    Navigation
  },
  // asenkron veriler
  async asyncData(context) {
    // günlük
    console.log('[index asyncData started]')
    try {
      // bir oturum başlatılıyor jSON
      const dao = context.app.$dao()
      const response = await dao.initSession()
      // günlük
      console.log('[index asyncData response=]', response)
      // sonraki istekler için PHP oturum çerezi alınır
      const phpSessionCookie = dao.getPhpSessionCookie()
      // PHP oturum çerezi, [nuxt] oturumunda saklanıyor
      context.store.commit('replace', { phpSessionCookie })
      // Bir hata mı oluştu?
      if (response.état !== 700) {
        // hata response.réponse'te bulunuyor
        throw new Error(response.réponse)
      }
      // jSON oturumunun başladığı belirtilmiştir
      context.store.commit('replace', { jsonSessionStarted: true })
      // sonuç veriliyor
      return { result: '[succès]' }
    } catch (e) {
      // günlüğe kaydediliyor
      console.log('[index asyncData error=]', e)
      // jSON oturumunun başlamadığı kaydedilir
      context.store.commit('replace', { jsonSessionStarted: false })
      // hata bildiriliyor
      return { result: '[échec]', showErrorLoading: true, errorLoadingMessage: e.message }
    } finally {
      // depolama alanı kaydedilir
      const session = context.app.$session()
      session.save(context)
      // günlük
      console.log('[index asyncData finished]')
    }
  },
  // yaşam döngüsü
  beforeCreate() {
    console.log('[index beforeCreate]')
  },
  created() {
    console.log('[index created]')
  },
  beforeMount() {
    console.log('[index beforeMount]')
  },
  mounted() {
    console.log('[index mounted]')
    // sadece istemci
    if (this.showErrorLoading) {
      console.log('[index mounted, showErrorLoading=true]')
      this.$eventBus().$emit('errorLoading', true, this.errorLoadingMessage)
    }
  }
}
</script>
  • 7. satır: Sayfa, asenkron bir isteğin (46. ve 51. satırlar) sonucunu [result] olarak görüntüler;
  • 31. satır: Asenkron işlem, vergi hesaplama sunucusuyla bir oturum açılmasıdır (jSON);
  • 25. satır: Sayfanın doğrudan sunucuya [nuxt] olarak talep edildiğinde, [asyncData] işlevinin yalnızca sunucu tarafından yürütüldüğü ve tarayıcının [nuxt] sunucusundan yanıtı aldığında çalışan [nuxt] istemcisi tarafından yürütülmediği bilinmektedir;
  • 30. satır: [nuxt] sunucusunun bağlamından [dao] katmanı alınır;
  • 35. satır: Sunucu, vergi hesaplama sunucusuna henüz bir istek göndermemişse, ilk oturum çerezi PHP'i alır; aksi takdirde, daha önce aldığı son oturum çerezi PHP'i alır ([nuxt] sunucusunun [dao] katmanındaki kodu, bağlantı paragrafında inceleyin);
  • 37. satır: Bu PHP oturum çerezi depoya kaydedilir;
  • satır 39-42: işlemin başarılı olup olmadığına bakılır. Başarılı değilse, bir istisna atılır ve bu istisna 47. satırdaki [catch] tarafından yakalanır;
  • 44. satır: jSON sunucusuyla PHP sunucusu arasındaki oturumun başlatıldığı, depoya kaydedilir;
  • 46. satır: [result] sonucu döndürülür ve 7. satırda görüntülenir;
  • 47-54. satırlar: Olası bir istisna işlenir. Bu istisna iki türde olabilir:
    • 31. satırdaki HTTP işlemi, [nuxt] sunucusu ile PHP sunucusu arasındaki bir iletişim hatası nedeniyle başarısız olmuştur;
    • 31. satırdaki HTTP işlemi başarılı oldu ancak alınan sonuçta bir hata bildirildi (39-42. satırlar);
  • 51. satır: jSON oturumunun PHP sunucusuyla başlatılmadığı görülmektedir;
  • 53. satır: 7. satırda görüntülenen [result] sonucu döndürülür. Ayrıca, [nuxt] istemcisinin, [nuxt] sunucusu tarafından gönderilen sayfayı aldığında bir hata mesajı görüntülemek için kullanacağı [showErrorLoading] ve [errorLoadingMessage] özellikleri ayarlanır (72-79. satırlar);
  • 54-60. satırlar: her durumda (başarılı ya da başarısız) yürütülen kod;
  • satır 56: [nuxt] sunucusunun bağlamında [nuxt] oturumu alınır;
  • satır 57: oturum kaydedilir;
  • satır 63-68: [asyncData] işlevi tamamlandığında, [nuxt] sunucusu [beforeCreate] ve [create] işlevlerini yürütür;

Not: [nuxt] sunucusu tarafından [index] sayfasının yürütülmesi, örneğin [nuxt] uygulaması başlatıldığında vergi hesaplama sunucusu çalışır durumda değilse başarısız olabilir:

Image

Bu durumda, gezinme menüsünde vergi hesaplama sunucusuyla bir jSON oturumu başlatma seçeneği bulunmadığından, tek çözüm vergi hesaplama sunucusunu ve ardından [nuxt] uygulamasını başlatmaktır;

15.14. [nuxt] istemcisi tarafından çalıştırılan [index] sayfası

[index] sayfası, [nuxt] istemcisi tarafından ancak [nuxt] sunucusu tarafından kendisine gönderildikten sonra çalıştırılır. Sunucu, [result] bilgilerini ve muhtemelen [showErrorLoading] ile [errorLoadingMessage] bilgilerini de ona göndermiştir.

[asyncData] işlevinin çalıştırılmayacağı bilinmektedir. Geriye yaşam döngüsü işlevleri ve özellikle [mounted] işlevi kalmaktadır:


mounted() {
    console.log('[index mounted]')
    // sadece istemci
    if (this.showErrorLoading) {
      console.log('[index mounted, showErrorLoading=true]')
      this.$eventBus().$emit('errorLoading', true, this.errorLoadingMessage)
    }
}
  • [nuxt] istemcisi, [nuxt] sunucusu tarafından kendisine gönderilen [result] ve gerekirse [showErrorLoading, errorLoadingMessage] öğelerini sayfanın özelliklerine otomatik olarak ekler:
  • [result] özelliği 7. satırda görüntülenir;
  • [showErrorLoading, errorLoadingMessage] özellikleri, [mounted] yöntemi tarafından kullanılır: 4. satırda, [showErrorLoading] özelliği test edilir. Eğer doğruysa, 6. satırda, [nuxt] istemcisinin olay veriyolu kullanılarak görüntülenmesi gereken bir hata mesajı olduğu bildirilir;
  • 6. satırda tetiklenen [errorLoading] olayı, “bağlantı” başlıklı paragrafta açıklanan [layouts/default] sayfası tarafından yakalanır;

15.15. [nuxt] sunucusu tarafından çalıştırılan [authentification] sayfası

[authentification] sayfası, vergi hesaplama sunucusunda bir kullanıcıyı tanımlamakla görevlidir. Kod şöyledir:


<!-- kimlik doğrulama sayfası -->
<template>
  <Layout :left="true" :right="true">
    <!-- gezinme -->
    <Navigation slot="left" />
    <!-- mesaj-->
    <b-alert slot="right" show variant="warning">Authentification auprès du serveur de calcul de l'impôt : {{ result }} </b-alert>
  </Layout>
</template>

<script>
/* eslint-disable no-console */

import Navigation from '@/components/navigation'
import Layout from '@/components/layout'

export default {
  name: 'Authentification',
  // kullanılan bileşenler
  components: {
    Layout,
    Navigation
  },
  // asenkron veriler
  async asyncData(context) {
    // günlük
    console.log('[authentification asyncData started]')
    if (process.client) {
      // istemci bekleme başlangıcı [nuxt]
      context.app.$eventBus().$emit('loading', true)
      // hata yok
      context.app.$eventBus().$emit('errorLoading', false)
    }
    try {
      // sunucuya kimlik doğrulaması yapılıyor
      const dao = context.app.$dao()
      const response = await dao.authentifierUtilisateur('admin', 'admin')
      // günlük
      console.log('[authentification asyncData response=]', response)
      // sonuç
      const userAuthenticated = response.état === 200
      // kullanıcının kimliği doğrulanıp doğrulanmadığını not ediyoruz
      context.store.commit('replace', { userAuthenticated })
      // devrede depolama alanı kaydedilir [nuxt]
      const session = context.app.$session()
      session.save(context)
      // kimlik doğrulama hatası mı?
      if (!userAuthenticated) {
        // hata response.réponse'te bulunur
        throw new Error(response.réponse)
      }
      // sonuç veriliyor
      return { result: '[succès]' }
    } catch (e) {
      // hata bildiriliyor
      return { result: '[échec]', showErrorLoading: true, errorLoadingMessage: e.message }
    } finally {
      // günlük
      console.log('[authentification asyncData finished]')
      if (process.client) {
        // istemci beklemesi sona erdi [nuxt]
        context.app.$eventBus().$emit('loading', false)
      }
    }
  },
  // yaşam döngüsü
  beforeCreate() {
    console.log('[authentification beforeCreate]')
  },
  created() {
    console.log('[authentification created]')
  },
  beforeMount() {
    console.log('[authentification beforeMount]')
  },
  mounted() {
    console.log('[authentification mounted]')
    // sadece müşteri
    if (this.showErrorLoading) {
      console.log('[authentification mounted, showErrorLoading=true]')
      this.$eventBus().$emit('errorLoading', true, this.errorLoadingMessage)
    }
  }
}
</script>
  • 7. satır: Sayfa, 25-65. satırlardaki [asyncData] asenkron isteğinin sonucunu [result] olarak görüntüler;
  • 28-33. satırlar: Sunucu, [nuxt] istemcisine yönelik bu satırları yürütmez;
  • satır 36: [nuxt] sunucusundan [dao] katmanı alınır;
  • satır 37: vergi hesaplama sunucusunda, vergi hesaplama sunucusu tarafından kabul edilen tek kimlik bilgileri olan [admin, admin] test kimlik bilgileriyle kimlik doğrulaması yapılır;
  • satır 41: Yalnızca durum kodu 200 olan yanıt gelirse kimlik doğrulama işlemi başarılı olur;
  • satır 43: [userAuthenticated] özelliği depoya kaydedilir;
  • satır 44-46: depo, [nuxt] oturumuna kaydedilir;
  • satır 48-51: Kimlik doğrulama başarısız olursa, vergi hesaplama sunucusunun gönderdiği hata mesajıyla bir istisna tetiklenir;
  • aksi takdirde 53. satırda, 7. satırda görüntülenecek bir başarı sonucu döndürülür;
  • 54-57. satırlar: Hata durumunda, [result, showErrorLoading, errorLoadingMessage] sayfasının üç özelliği ayarlanır. [result] özelliği 7. satırda görüntülenir. Üç özellik de [nuxt] istemcisine gönderilir;
  • 60-63. satırlar: [nuxt] sunucusu tarafından yürütülmez;
  • [asyncData] sonucu döndürdüğünde, bu sonuç 7. satırda görüntülenir. Ardından [beforeCreate] (67-69. satırlar) ve [created] (70-72. satırlar) yöntemleri yürütülür;
  • işlem tamamlandı;

Not: [nuxt] sunucusu tarafından [authentification] sayfasının yürütülmesi, örneğin vergi hesaplama sunucusuyla olan jSON oturumu başlatılmamışsa başarısız olabilir. Bunu şu şekilde yapabilirsiniz:

  • tarayıcınızdan PHP oturum çerezini silin (sıfırdan başlamak için):

Image

  • hesaplama sunucusu başlatılmamışken [nuxt] uygulamasını başlatın: bir hata mesajı alırsınız;
  • vergi hesaplama sunucusunu başlatın;
  • URL [/authentification] adresini doğrudan tarayıcının adres çubuğuna girin:

Image

Bu durumda tek çözüm, [index] sayfasını yeniden yüklemektir.

15.16. [authentification] sayfası, [nuxt] istemcisi tarafından çalıştırılır

Sayfanın koduna tekrar bakalım:


<!-- kimlik doğrulama sayfası -->
<template>
  <Layout :left="true" :right="true">
    <!-- gezinme -->
    <Navigation slot="left" />
    <!-- mesaj-->
    <b-alert slot="right" show variant="warning">Authentification auprès du serveur de calcul de l'impôt : {{ result }} </b-alert>
  </Layout>
</template>

<script>
/* eslint-disable no-console */

import Navigation from '@/components/navigation'
import Layout from '@/components/layout'

export default {
  name: 'Authentification',
  // kullanılan bileşenler
  components: {
    Layout,
    Navigation
  },
  // asenkron veriler
  async asyncData(context) {
    // günlük
    console.log('[authentification asyncData started]')
    if (process.client) {
      // istemci bekleme başlangıcı [nuxt]
      context.app.$eventBus().$emit('loading', true)
      // hata yok
      context.app.$eventBus().$emit('errorLoading', false)
    }
    try {
      // sunucuya kimlik doğrulaması yapılıyor
      const dao = context.app.$dao()
      const response = await dao.authentifierUtilisateur('admin', 'admin')
      // günlük
      console.log('[authentification asyncData response=]', response)
      // sonuç
      const userAuthenticated = response.état === 200
      // kullanıcının kimliği doğrulanmış olup olmadığı kaydediliyor
      context.store.commit('replace', { userAuthenticated })
      // devrede depolama alanı kaydedilir [nuxt]
      const session = context.app.$session()
      session.save(context)
      // kimlik doğrulama hatası mı?
      if (!userAuthenticated) {
        // hata response.réponse adresinde bulunur
        throw new Error(response.réponse)
      }
      // sonuç veriliyor
      return { result: '[succès]' }
    } catch (e) {
      // hata bildiriliyor
      return { result: '[échec]', showErrorLoading: true, errorLoadingMessage: e.message }
    } finally {
      // günlük
      console.log('[authentification asyncData finished]')
      if (process.client) {
        // istemci beklemesi sona erdi [nuxt]
        context.app.$eventBus().$emit('loading', false)
      }
    }
  },
  // yaşam döngüsü
  beforeCreate() {
    console.log('[authentification beforeCreate]')
  },
  created() {
    console.log('[authentification created]')
  },
  beforeMount() {
    console.log('[authentification beforeMount]')
  },
  mounted() {
    console.log('[authentification mounted]')
    // sadece müşteri
    if (this.showErrorLoading) {
      console.log('[authentification mounted, showErrorLoading=true]')
      this.$eventBus().$emit('errorLoading', true, this.errorLoadingMessage)
    }
  }
}
</script>

[nuxt] istemcisi tarafından [authentification] sayfasının çalıştırılmasının iki durumu vardır:

  1. [nuxt] istemcisi, [nuxt] sunucusunun [nuxt] istemcisinin tarayıcısına [authentification] sayfasını göndermesinin ardından çalışır;
  2. [nuxt] istemcisi, kullanıcının gezinme menüsündeki [Authentification] bağlantısına tıklaması nedeniyle çalışır:

Image

Öncelikle ilk durumu inceleyelim. Bu durumda, [nuxt] istemcisi [asyncData] işlevini çalıştırmaz. Sayfa özelliklerine, [nuxt] sunucusu tarafından kendisine gönderilen [result] ve muhtemelen [showErrorLoading, errorLoadingMessage] öğelerini ekler:

  • [result] özelliği 7. satırda görüntülenir;
  • [showErrorLoading, errorLoadingMessage] özellikleri, [mounted] yöntemi tarafından kullanılır: 79. satırda, [showErrorLoading] özelliği test edilir. Eğer bu özellik doğruysa, 81. satırda [nuxt] istemcisinin olay veriyolu kullanılarak görüntülenmesi gereken bir hata mesajı olduğu bildirilir;

Hata mesajının görüntülenme mekanizması, [index] sayfası için “bağlantı” başlıklı paragrafta açıklanmıştır.

Durum 2, kullanıcı [Authentification] bağlantısına tıkladığında çalıştırılan [nuxt] istemcisiyle ilgilidir. Bu durumda, [nuxt] istemcisi, [nuxt] sunucusundan sonra değil, bağımsız olarak çalışır. Ardından [asyncData] işlevi yürütülür. Burada, [nuxt] sunucusu tarafından çalıştırılan sayfaya ilişkin açıklamalardan farklı olan ayrıntıları veriyoruz:

  • 28-33. satırlar: [nuxt] istemcisi, bekleme mesajının görüntülenmesini ve daha önce görüntülenmiş olabilecek bir hata mesajının kaldırılmasını ister;
  • 36. satır: Artık burada [nuxt] istemcisinin [dao] katmanı elde edilmektedir;
  • 60-63. satırlar: [nuxt] istemcisi, bekleme mesajının görüntülenmesinin sonlandırılmasını talep eder;
  • [asyncData] tamamlandığında, sayfanın yaşam döngüsü başlayacaktır. 76-83. satırlardaki [mounted] işlevi çalıştırılacaktır. Hata oluşmuşsa, hata mesajı görüntülenecektir;

Not: Hata oluşturmak için, bağlantı paragrafının sonunda [nuxt] sunucusu için açıklanan prosedürü izleyin, ancak adres çubuğuna URL yazarak [authentification] sayfasını çağırmak yerine, gezinme menüsündeki [Authentification] bağlantısını kullanın. Böylece [nuxt] istemcisi çalıştırılır.

15.17. [get-admindata] sayfası

[get-admindata] sayfasının kodu şöyledir:


<!-- get-admindata görünümü -->
<template>
  <Layout :left="true" :right="true">
    <!-- gezinti -->
    <Navigation slot="left" />
    <!-- mesaj -->
    <b-alert slot="right" show variant="secondary"> Demande de [adminData] au serveur de calcul de l'impôt : {{ result }} </b-alert>
  </Layout>
</template>

<script>
/* eslint-disable no-console */

import Navigation from '@/components/navigation'
import Layout from '@/components/layout'

export default {
  name: 'GetAdmindata',
  // kullanılan bileşenler
  components: {
    Layout,
    Navigation
  },
  // asenkron veriler
  async asyncData(context) {
    // günlük
    console.log('[get-admindata asyncData started]')
    if (process.client) {
      // bekleme başlangıcı
      context.app.$eventBus().$emit('loading', true)
      // hata yok
      context.app.$eventBus().$emit('errorLoading', false)
    }
    try {
      // veri isteniyor [admindata]
      const response = await context.app.$dao().getAdminData()
      // günlük
      console.log('[get-admindata asyncData response=]', response)
      // sonuç
      const adminData = response.état === 1000 ? response.réponse : ''
      // veri depoya kaydediliyor
      context.store.commit('replace', { adminData })
      // depolama alanı oturuma kaydediliyor [nuxt]
      const session = context.app.$session()
      session.save(context)
      // hata oluştu mu?
      if (!adminData) {
        // hata response.réponse adresinde bulunuyor
        throw new Error(response.réponse)
      }
      // alınan değer geri veriliyor
      return { result: adminData }
    } catch (e) {
      // hatayı bildiriyoruz
      return { result: '[échec]', showErrorLoading: true, errorLoadingMessage: e.message }
    } finally {
      // günlük
      console.log('[get-admindata asyncData finished]')
      if (process.client) {
        // bekleme sonu
        context.app.$eventBus().$emit('loading', false)
      }
    }
  },
  // yaşam döngüsü
  beforeCreate() {
    console.log('[get-admindata beforeCreate]')
  },
  created() {
    console.log('[get-admindata created]')
  },
  beforeMount() {
    console.log('[get-admindata beforeMount]')
  },
  mounted() {
    console.log('[get-admindata mounted]')
    // müşteri
    if (this.showErrorLoading) {
      console.log('[get-admindata mounted, showErrorLoading=true]')
      this.$eventBus().$emit('errorLoading', true, this.errorLoadingMessage)
    }
  }
}
</script>

Bu sayfa, [authentification] sayfasına çok benzemektedir. Açıklamalar, hem [nuxt] sunucusu tarafından çalıştırılması hem de [nuxt] istemcisi tarafından çalıştırılması için benzerdir. Ancak, 7. satırda önceki gibi başarı / başarısızlık bilgisi değil, vergi hesaplama sunucusundan alınan verinin değeri (52. satır) görüntülenir:

Image

Yukarıdaki sonuç, hem sunucu hem de [nuxt] istemcisi ile elde edilir. Bir hata oluşturmak için, kimlik doğrulaması yapmadan sunucu veya [nuxt] istemcisi aracılığıyla [get-admindata] sayfasını isteyin:

Image

15.18. [fin-session] sayfası

Sayfanın kodu şöyledir:


<!-- ana sayfa -->
<template>
  <Layout :left="true" :right="true">
    <!-- gezinme -->
    <Navigation slot="left" />
    <!-- mesaj-->
    <b-alert slot="right" show variant="warning">Fin de la session avec le serveur de calcul de l'impôt : {{ result }} </b-alert>
  </Layout>
</template>

<script>
/* eslint-disable no-console */

import Navigation from '@/components/navigation'
import Layout from '@/components/layout'

export default {
  name: 'FinSession',
  // kullanılan bileşenler
  components: {
    Layout,
    Navigation
  },
  // asenkron veriler
  async asyncData(context) {
    // günlük
    console.log('[fin-session asyncData started]')
    // müşteri örneği [nuxt]
    if (process.client) {
      // bekleme başlangıcı
      context.app.$eventBus().$emit('loading', true)
      // hata yok
      context.app.$eventBus().$emit('errorLoading', false)
    }
    try {
      // vergi hesaplama sunucusundan PHP oturumu talep ediliyor
      const dao = context.app.$dao()
      const response = await dao.finSession()
      // günlük
      console.log('[fin-session asyncData response=]', response)
      // hata mı oluştu?
      if (response.état !== 400) {
        // hata response.réponse'te bulunuyor
        throw new Error(response.réponse)
      }
      // sunucu yeni bir oturum çerezi gönderdi: PHP
      // Bu çerez hem sunucu hem de Nuxt istemcisi tarafından alınır
      // Bu kod [nuxt] istemcisi tarafından çalıştırılırsa, PHP oturum çerezi nuxt oturumuna eklenmelidir
      // böylece [nuxt] sunucusundaki [plgDao] eklentisi bunu alabilir ve [dao] katmanını
      // bu kod [nuxt] sunucusu tarafından çalıştırılırsa, PHP oturum çerezi nuxt oturumuna eklenmelidir
      // oturumuna eklenmelidir; böylece [nuxt] istemcisinin yönlendirme işlemi bunu alıp tarayıcıya iletebilir
      const phpSessionCookie = dao.getPhpSessionCookie()
      // de jSON oturumunun başlatıldığı bilgisi depoya kaydedilir ve PHP oturum çerezi saklanır
      context.store.commit('replace', { jsonSessionStarted: true, phpSessionCookie, userAuthenticated: false, adminData: '' })
      // depolama alanı, [nuxt] oturumuna kaydedilir
      const session = context.app.$session()
      session.save(context)
      // sonuç döndürülür
      return { result: "[succès]. La session jSON reste initialisée mais vous n'êtes plus authentifié(e)." }
    } catch (e) {
      // günlüğe kaydedilir
      console.log('[fin-session asyncData error=]', e)
      // hata bildirilir
      return { result: '[échec]', showErrorLoading: true, errorLoadingMessage: e.message }
    } finally {
      // günlük
      console.log('[fin-session asyncData finished]')
      if (process.client) {
        // bekleme sona erdi
        context.app.$eventBus().$emit('loading', false)
      }
    }
  },
  // yaşam döngüsü
  beforeCreate() {
    console.log('[fin-session beforeCreate]')
  },
  created() {
    console.log('[fin-session created]')
  },
  beforeMount() {
    console.log('[fin-session beforeMount]')
  },
  mounted() {
    console.log('[fin-session mounted]')
    // sadece istemci
    if (this.showErrorLoading) {
      console.log('[fin-session mounted, showErrorLoading=true]')
      this.$eventBus().$emit('errorLoading', true, this.errorLoadingMessage)
    }
  }
}
</script>

Kod, önceki sayfaların koduna çok benzemektedir ve açıklamalar da aynıdır. Sadece bir noktaya dikkat etmek gerekir: 38. satırdaki asenkron işlem, vergi hesaplama sunucusunun yeni bir oturum çerezi olan PHP'i göndermesine neden olur. Bu çerezin yönetimi ile ilgili açıklamalar, kodu çalıştıranın sunucu mu yoksa [nuxt] istemcisi mi olduğuna göre farklılık gösterir.

Önce [nuxt] sunucusundan başlayalım:

  • 37. satır: [nuxt] sunucusunun [dao] katmanı örneklenir. Oluşturucusunun kodunu hatırlayalım:

// yapıcı
  constructor(axios, phpSessionCookie) {
    // axios kütüphanesi
    this.axios = axios
    // oturum çerezi değeri
    this.phpSessionCookie = phpSessionCookie
    // sunucunun oturum çerezinin adı PHP
    this.phpSessionCookieName = 'PHPSESSID'
}
  1. satırda görüldüğü gibi, oluşturucu o anda geçerli olan, ister sunucu ister [nuxt] istemcisi tarafından alınmış olsun, en son alınan PHP oturum çerezine ihtiyaç duyar;
  • 52. satır: [nuxt] sunucusu, yeni oturum çerezini (PHP) veya oturum sonlandırma işlemi başarısız olmuşsa eski çerezi alır;
  • 54. satır: PHP oturum çerezi depoya yerleştirilir ve ardından 56-57. satırlarda [nuxt] oturumuna kaydedilir;
  • sunucudan sonra, [nuxt] adlı istemci, sunucu tarafından gönderilen verilerle [fin-session] sayfasını çalıştırır. Bu istemcinin [asyncData] işlevini çalıştırmayacağı bilinmektedir;
  • sonuç olarak, sunucu ve [nuxt] istemcisi işlerini tamamladıktan sonra, vergi hesaplama sunucusuyla iletişim için gerekli olan PHP çerezinin [nuxt] oturumunda bulunduğu bilinmektedir;

PHP çerezinin [nuxt] oturumunda bulunması sunucu için yeterlidir, çünkü [dao] katmanı bu çerezi buradan alacaktır. Sunucunun [dao] katmanını başlatan [server/plgDao] eklentisinde şunlar yazılmıştır:


/* eslint-disable no-console */
// [Dao] katmanına bir erişim noktası oluşturuluyor
import Dao from '@/api/server/Dao'
export default (context, inject) => {
  // axios yapılandırması
  context.$axios.defaults.timeout = context.env.timeout
  context.$axios.defaults.baseURL = context.env.baseURL
  // oturum çerezi alınır
  const store = context.app.$session().value.store
  const phpSessionCookie = store ? store.phpSessionCookie : ''
  console.log('session=', context.app.$session().value, 'phpSessionCookie=', phpSessionCookie)
  // [dao] katmanının örneklenmesi
  const dao = new Dao(context.$axios, phpSessionCookie)
  // [$dao] işlevinin bağlama enjeksiyonu
  inject('dao', () => dao)
  // günlük kaydı
  console.log('[fonction server $dao créée]')
}
  • 13. satırda, [nuxt] sunucusunun [dao] katmanı, 9-10. satırlarda [nuxt] oturumundan alınan PHP oturum çerezi ile örneklenir;

[nuxt] istemcisi için ise durum farklıdır. Aslında çerezi gönderen o değil, onu çalıştıran tarayıcıdır. Ancak bu tarayıcı, [nuxt] sunucusu tarafından alınan yeni oturum çerezi PHP'i tanımıyor. [3] gezinme menüsündeki bağlantılar kullanılırsa:

Image

Vergi hesaplama sunucusu, tarayıcıdan geçerliliğini yitirmiş PHP oturum çerezini alacak ve bu çereze jSON oturumunun eşleştirilmediğini bildirecektir. Tarayıcıya yeni PHP oturum çerezini iletmenin bir yolunu bulmamız gerekiyor.

Bunu yapmak için bir yönlendirme ara yazılımı kullanabiliriz:

Image

[client/routing] komut dosyası, [nuxt.config] dosyasında tanımlanan yönlendirme ara yazılımıdır:


// yönlendirici
  router: {
    // uygulamanın URL kökü
    base: '/nuxt-12/',
    // yönlendirme ara yazılımı
    middleware: ['routing']
},

[middleware/routing] komut dosyası şöyledir:


/* eslint-disable no-console */

// istemci ara yazılımını içe aktarıyoruz
import clientRouting from './client/routing'

export default function(context) {
  // Bu kodu kim çalıştırıyor?
  console.log('[middleware], process.server', process.server, ', process.client=', process.client)
  if (process.client) {
    // istemci yönlendirmesi
    clientRouting(context)
  }
}
  • 9-12. satırlar: Yalnızca 4. satırda içe aktarılan bir işlevle istemci yönlendirilir;

[middleware/client/routing] komut dosyası şöyledir:


/* eslint-disable no-console */
export default function(context) {
  // Bu kodu kim çalıştırıyor?
  console.log('[middleware client], process.server', process.server, ', process.client=', process.client)
  // tarayıcıdaki PHP oturum çerezinin yönetimi
  // tarayıcıdaki PHP oturum çerezi, nuxt oturumunda bulunanla aynı olmalıdır
  // [fin-session] eylemi, yeni bir PHP çerezi alır (hem sunucu hem de Nuxt istemcisi)
  // eğer bunu alan sunucuysa, istemci bunu tarayıcıya iletmelidir
  // sunucuyla kendi iletişimi için PHP
  // burada bir istemci yönlendirmesi söz konusudur

  // oturum çerezini alıyoruz PHP
  const phpSessionCookie = context.store.state.phpSessionCookie
  if (phpSessionCookie) {
    // varsa, PHP oturum çerezini tarayıcıya atanır
    document.cookie = phpSessionCookie
  }
}

[nuxt] sunucusu tarafından [fin-session] sayfasının yürütülmesinden hemen sonraki duruma geri dönelim:

Image

[3] menüsündeki bağlantılardan birine tıklandığında, [nuxt] istemcisi devreye girecektir. Sayfa değişimi olacağı için, istemcinin yönlendirme komut dosyası çalışacaktır:

  • 13. satır: PHP oturum çerezi, [nuxt] uygulamasının depolama alanında bulunur;
  • 14. satır: Çerez boş değilse, tarayıcıya iletilir (16. satır). Bu andan itibaren [nuxt] istemcisinin tarayıcısı, doğru oturum çerezi olan PHP’e sahip olur;

[client/routing] komut dosyası, [nuxt] istemcisinde her sayfa değişikliğinde çalıştırılır. Komut dosyasının kodu, hedef sayfa ne olursa olsun geçerlidir: basitçe, çoğu zaman tarayıcıya zaten sahip olduğu PHP oturum çerezini verir; ancak iki istisna vardır:

  • uygulamanın başlatılmasından hemen sonra, [nuxt] sunucusu, [index] sayfasını çalıştırır ve PHP adlı ilk oturum çerezini alır; bu çerez, [nuxt] istemcisinin tarayıcısında bulunmaz;
  • az önce açıklandığı gibi [nuxt] sunucusu [fin-session] sayfasını çalıştırdığında;

Şimdi, gezinme menüsündeki bağlantısına tıklandığı için [fin-session] sayfasının yalnızca [nuxt] istemcisi tarafından çalıştırıldığı durumu inceleyelim. Artık [nuxt] istemcisi, [asyncData] işlevini çalıştırıyor:


try {
      // Vergi hesaplama sunucusuna yeni bir oturum (PHP) talep ediliyor
      const dao = context.app.$dao()
      const response = await dao.finSession()
      // günlük
      console.log('[fin-session asyncData response=]', response)
      // Bir hata mı oluştu?
      if (response.état !== 400) {
        // hata response.réponse adresinde bulunuyor
        throw new Error(response.réponse)
      }
      // sunucu yeni bir oturum çerezi gönderdi PHP
      // Bu çerez hem sunucu hem de Nuxt istemcisi tarafından alınır
      // Bu kod [nuxt] istemcisi tarafından çalıştırılırsa, PHP oturum çerezi nuxt oturumuna eklenmelidir
      // böylece [nuxt] sunucusundaki [plgDao] eklentisi bunu alabilir ve [dao] katmanını
      // bu kod [nuxt] sunucusu tarafından çalıştırılırsa, PHP oturum çerezi nuxt oturumuna eklenmelidir
      // oturumuna eklenmelidir; böylece [nuxt] istemcisinin yönlendirme işlemi bunu alıp tarayıcıya iletebilir
      const phpSessionCookie = dao.getPhpSessionCookie()
      // de jSON oturumunun başlatıldığı bilgisi depoya kaydedilir ve PHP oturum çerezi saklanır
      context.store.commit('replace', { jsonSessionStarted: true, phpSessionCookie, userAuthenticated: false, adminData: '' })
      // depolama alanı, [nuxt] oturumuna kaydedilir
      const session = context.app.$session()
      session.save(context)
      // sonuç döndürülür
      return { result: "[succès]. La session jSON reste initialisée mais vous n'êtes plus authentifié(e)." }
    } catch (e) {
      // günlüğe kaydedilir
      console.log('[fin-session asyncData error=]', e)
      // hata bildirilir
      return { result: '[échec]', showErrorLoading: true, errorLoadingMessage: e.message }
    } finally {
      // günlük
      console.log('[fin-session asyncData finished]')
      if (process.client) {
        // bekleme sona erdi
        context.app.$eventBus().$emit('loading', false)
      }
    }
  • 3. satır: Burada elde edilen, [nuxt] istemcisinin [dao] katmanıdır;
  • 18. satır: [nuxt] istemcisinin [dao] katmanı tarafından alınan PHP oturum çerezi depolanır, depoya yerleştirilir (20. satır) ve ardından [nuxt] oturumuna kaydedilir (22-23. satırlar);
  • bu noktadan sonra her şey yolunda gider, çünkü [nuxt] sunucusunun [dao] katmanının, [nuxt] oturumundan PHP oturum çerezini alacağı bilinmektedir;

15.19. Exécution

Bu örneği çalıştırmak için, temiz bir durumdan başlamak amacıyla, çalıştırma öncesinde [nuxt] istemcisini çalıştıran tarayıcıdan [nuxt] oturum çerezini ve PHP çerezini silmeye dikkat etmelisiniz. Aşağıda Chrome tarayıcısıyla bir örnek verilmiştir:

Image

15.20. Conclusion

Bu örnek özellikle karmaşıktı. Önceki örneklerde edinilen bilgileri bir araya getiriyordu: [nuxt] oturumunda deponun kalıcılığı, işlev enjeksiyon eklentileri, yönlendirme ara yazılımı, asenkron işlemlerde hata yönetimi. Kullanıcıların hem gezinme menüsündeki bağlantıları kullanabilmelerini hem de URL adreslerini elle girebilmelerini ve bunun uygulamayı bozmaması istenmesi, karmaşıklığı daha da artırdı. Bunun için, her sayfanın istemci tarafından mı yoksa sunucu tarafından mı çalıştırıldığına göre nasıl davrandığını incelemek zorunda kaldık.

İstemci ve [nuxt] sunucusunun bu tutarlılığı zorunlu değildir. Şu sık karşılaşılan durumu ele alabiliriz:

  • ilk sayfa [nuxt] sunucusu tarafından sunulur;
  • sonraki tüm sayfalar, o sırada [SPA] modunda çalışan [nuxt] istemcisi tarafından sunulur;

Bununla birlikte, bu durumda bile tüm sayfaların [nuxt] sunucusu tarafından işlendiğinde ne sonuç vereceğini kontrol etmek gerekir; çünkü sayfaları talep eden arama motorları bu sonucu alacaktır.