15. Voorbeeld [nuxt-12]: verzoeken aan HTTP met axios
15.1. Présentation
In dit nieuwe voorbeeld gaan we ontdekken hoe we in de functies [asyncData] verzoeken HTTP kunnen uitvoeren met de bibliotheek [axios]. Daarnaast gaan we gebruikmaken van reeds opgedane kennis:
- het gebruik van plug-ins uit het voorbeeld [nuxt-06]:
- het opslaan van de store in een sessiecookie uit het voorbeeld [nuxt-06];
- het beheren van de navigatie met middleware uit het voorbeeld [nuxt-09];
- het beheer van fouten uit het voorbeeld [nuxt-11];
De architectuur van het voorbeeld ziet er als volgt uit:

- de applicatie [nuxt] wordt opgeslagen op de server [node.js] [3], gedownload door de browser [1], die deze vervolgens uitvoert;
- zowel de client [nuxt] [1] als de server [nuxt] [3] zullen verzoeken HTTP richten aan de gegevensserver [2]. Deze server is de server voor belastingberekening die in deel PHP 7 is ontwikkeld. We gebruiken de nieuwste versie, versie 14, waarbij de verzoeken CORS zijn toegestaan;
De architectuur van het voorbeeld kan als volgt worden vereenvoudigd:

- in [1] levert de server [node.js] de pagina’s [nuxt] aan de browser [2]. Het is de laag [web] [8] van de server die deze pagina’s levert. Om de pagina te leveren, heeft de server mogelijk externe gegevens opgevraagd bij de gegevensserver [3]. Het is de laag [DAO] [9] die de nodige verzoeken HTTP uitvoert;
- bij elke pagina-aanroep naar de server [node.js][1], ontvangt de browser [2] de volledige applicatie [nuxt], die vervolgens in de modus SPA wordt uitgevoerd. Het blok [UI] (gebruikersinterface) [4] toont de pagina’s [vue.js] aan de gebruiker. De acties van dit blok of de natuurlijke levenscyclus van de pagina’s kunnen leiden tot het opvragen van externe gegevens bij de gegevensserver [3]. De laag [DAO] [5] voert vervolgens de benodigde verzoeken HTTP uit;
15.2. Projectboomstructuur

15.3. Het configuratiebestand [nuxt.config.js]
Het project wordt gecontroleerd aan de hand van het volgende bestand: [nuxt.config.js]:
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: [
// Doc: https://github.com/nuxt-community/eslint-module
'@nuxtjs/eslint-module'
],
/*
** Nuxt.js modules
*/
modules: [
// Doc: https://bootstrap-vue.js.org
'bootstrap-vue/nuxt',
// Doc: 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) { }
},
// broncodemap
srcDir: 'nuxt-12',
// router
router: {
// hoofdmap van de applicatie URL
base: '/nuxt-12/',
// routeringsmiddleware
middleware: ['routing']
},
// server
server: {
// servicepoort, standaard 3000
port: 81,
// netwerkadressen waarop wordt geluisterd, standaard localhost: 127.0.0.1
// 0.0.0.0 = alle netwerkadressen van de machine
host: 'localhost'
},
// omgeving
env: {
// axios-configuratie
timeout: 2000,
withCredentials: true,
baseURL: 'http://'localhost/php7/scripts-web/impots/version-14',
// configuratie van de sessiecookie [nuxt]
maxAge: 60 * 5
}
}
- regel 22: we beheren zelf de melding dat er gewacht wordt op het einde van een asynchrone actie;
- regel 31: we gaan verschillende plug-ins gebruiken die ofwel voor de client, ofwel voor de server zijn bedoeld, maar niet voor beide tegelijk;
- regel 52: de module [axios] is geïntegreerd in [nuxt]. Dit heeft tot gevolg dat het object [axios], dat de verzoeken HTTP van deapplicatie [nuxt] naar de belastingberekeningsserver PHP, beschikbaar zal zijn in [context.$axios];
- regel 54: met de module [cookie-universal-nuxt] kunnen we de sessie [nuxt] in een cookie opslaan;
- regel 60: met de eigenschap [axios] kunnen we de module [@nuxtjs/axios] uit regel 52 configureren. We zullen deze mogelijkheid niet gebruiken, maar geven de voorkeur aan de eigenschap [env] uit regel 88;
- regel 90: maximale wachttijd voor het antwoord van de server voor de belastingberekening;
- regel 91: vereist voor de client [nuxt] – staat het gebruik van cookies toe bij de communicatie met de belastingberekeningsserver;
- regel 92: de basis-URL van de belastingberekeningsserver;
- regel 94: levensduur van de Nuxt-sessie (5 min);
- regel 77: het verkeer tussen de client en de server [nuxt] wordt geregeld door routing-middleware;
15.4. De [UI]-laag van de applicatie

We gaan de applicatie [nuxt] toegang verlenen tot de API van de belastingberekeningsserver via de volgende weergave:

- in [2], het menu dat toegang geeft tot de API van de belastingberekeningsserver:
- [Authentification]: komt overeen met de pagina [authentification]. Deze pagina doet een authenticatieverzoek aan de belastingberekeningsserver met de inloggegevens [admin, admin], die momenteel de enige zijn die zijn toegestaan. Het weergegeven resultaat is vergelijkbaar met dat van [3];
- [Requête AdminData]: komt overeen met de pagina [get-admindata]. Deze pagina vraagt de belastingberekeningsserver om de gegevens, hier [adminData] genoemd, die nodig zijn voor de berekening van de belasting. Het weergegeven resultaat is vergelijkbaar met [3];
- [Fin session impôt]: komt overeen met de pagina [fin-session]. Deze pagina verstuurt een verzoek tot beëindiging van de sessie PHP naar de server voor belastingberekening. De server beëindigt vervolgens de huidige sessie PHP en initialiseert een nieuwe, lege sessie;
15.5. De lagen [dao] van de applicatie [nuxt]
Zoals hierboven aangegeven, zal de architectuur van de applicatie [nuxt] als volgt zijn:

- in [1] levert de server [node.js] de pagina’s [nuxt] aan de browser [2]. Het is de laag [web] [8] van de server die deze pagina’s levert. Om de pagina te leveren, heeft de server mogelijk externe gegevens opgevraagd bij de gegevensserver [3]. Het is de laag [DAO] [9] die de nodige verzoeken HTTP uitvoert;
- bij elke pagina-aanroep naar de server [node.js][1], ontvangt de browser [2] de volledige applicatie [nuxt], die vervolgens in de modus SPA wordt uitgevoerd. Het blok [UI] (gebruikersinterface) [4] toont de pagina’s [vue.js] aan de gebruiker. De acties van dit blok of de levenscyclus van de pagina’s kunnen leiden tot het opvragen van externe gegevens bij de gegevensserver [3]. Het is de laag [DAO] [5] die vervolgens de benodigde verzoeken HTTP uitvoert;
We zullen versie 14 van de belastingberekeningsserver gebruiken die is ontwikkeld in het document |Inleiding tot de taal PHP7 aan de hand van een voorbeeld|. We zullen slechts een deel van de API (Application Programming Interface) jSON ervan gebruiken:
Verzoek | Antwoord |
| |
| |
| |
| |
15.5.1. De laag [dao] van de server [nuxt]

De server [node.js] [1] zal gebruikmaken van de laag [dao] die wordt beschreven in het document |Inleiding tot het VUE.JS-framework aan de hand van een voorbeeld|. Hier volgt nogmaals de code ervan:
'use strict';
// imports
import qs from 'qs'
class Dao {
// constructor
constructor(axios) {
this.axios = axios;
// sessiecookie
this.sessionCookieName = "PHPSESSID";
this.sessionCookie = '';
}
// sessie initialiseren
async initSession() {
// verzoekopties HHTP [get /main.php?action=init-session&type=json]
const options = {
method: "GET",
// parameters van de URL
params: {
action: 'init-session',
type: 'json'
}
};
// uitvoering van de query HTTP
return await this.getRemoteData(options);
}
async authentifierUtilisateur(user, password) {
// opties van de aanvraag HHTP [post /main.php?action=authentifier-utilisateur]
const options = {
method: "POST",
headers: {
'Content-type': 'application/x-www-form-urlencoded',
},
// hoofdtekst van het POST
data: qs.stringify({
user: user,
password: password
}),
// parameters van de URL
params: {
action: 'authentifier-utilisateur'
}
};
// uitvoering van de query HTTP
return await this.getRemoteData(options);
}
async getAdminData() {
// opties van de aanvraag HHTP [get /main.php?action=get-admindata]
const options = {
method: "GET",
// parameters van de URL
params: {
action: 'get-admindata'
}
};
// uitvoering van de query HTTP
const data = await this.getRemoteData(options);
// resultaat
return data;
}
async getRemoteData(options) {
// voor de sessiecookie
if (!options.headers) {
options.headers = {};
}
options.headers.Cookie = this.sessionCookie;
// uitvoering van de aanvraag HTTP
let response;
try {
// asynchrone aanvraag
response = await this.axios.request('main.php', options);
} catch (error) {
// de parameter [error] is een uitzondering – deze kan verschillende vormen aannemen
if (error.response) {
// het antwoord van de server staat in [error.response]
response = error.response;
} else {
// de fout wordt opnieuw gegenereerd
throw error;
}
}
// response is het volledige antwoord HTTP van de server (headers HTTP + het antwoord zelf)
// de sessiecookie wordt opgehaald, indien deze bestaat
const setCookie = response.headers['set-cookie'];
if (setCookie) {
// setCookie is een array
// we zoeken de sessiecookie in deze array
let trouvé = false;
let i = 0;
while (!trouvé && i < setCookie.length) {
// we zoeken naar de sessiecookie
const results = RegExp('^(' + this.sessionCookieName + '.+?);').exec(setCookie[i]);
if (results) {
// de sessiecookie wordt opgeslagen
// eslint-disable-next-line require-atomic-updates
this.sessionCookie = results[1];
// gevonden
trouvé = true;
} else {
// volgend element
i++;
}
}
}
// het antwoord van de server staat in [response.data]
return response.data;
}
}
// export van de klasse
export default Dao;
- alle methoden van de laag [dao] geven het object terug dat door de gegevensserver [{action : ‘xx’, état : nn, réponse : {...}] is verzonden, met:
- [action]: de naam van de actie die door de gegevensserver wordt uitgevoerd;
- [état]: numerieke indicator:
- [initSession]: status=700 voor een foutloos antwoord;
- [authentifierUtilisateur]: status=200 voor een foutloos antwoord;
- [getAdminData]: status=1000 voor een foutloos antwoord;
- [fin-session]: status=400 voor een foutloos antwoord;
- [réponse]: antwoord gekoppeld aan de numerieke indicator [état]. Kan variëren afhankelijk van deze numerieke indicator;
Laten we de constructor van de klasse [Dao] eens bekijken:
// constructor
constructor(axios) {
this.axios = axios;
// sessiecookie
this.sessionCookieName = "PHPSESSID";
this.sessionCookie = '';
}
- regel 2: het object [axios] dat als argument aan de constructor wordt doorgegeven, wordt geleverd door de aanroepende code. Dit object zal de verzoeken HTTP uitvoeren;
- regel 5: de naam van de sessiecookie die door de gegevensserver wordt verzonden, geschreven als PHP;
- regel 6: de sessiecookie die wordt uitgewisseld tussen de laag [dao] en de gegevensserver. Deze wordt geïnitialiseerd door de functie [getRemoteData] in de regels 67-113;
Voor de sessiecookie moeten we twee afzonderlijke lagen [dao] in aanmerking nemen:
- die van de browser;
- die van de server;
We zullen drie sessiecookies moeten beheren:
- het cookie dat wordt uitgewisseld tussen de client [nuxt] en de server PHP 7;
- het cookie dat wordt uitgewisseld tussen de server [nuxt] en de server PHP 7;
- het cookie dat wordt uitgewisseld tussen de client [nuxt] en de server [nuxt];
We zorgen ervoor dat de sessiecookie met de server PHP hetzelfde is voor de client en de server [nuxt]. We noemen dit de sessiecookie PHP. Dit is de sessiecookie uit de gevallen 1 en 2. We noemen de sessiecookie [nuxt] de sessiecookie uit geval 3. We hebben dus twee sessies:
- een sessie PHP met de sessiecookie PHP;
- een sessie [nuxt] met de sessiecookie [nuxt];
Waarom gebruiken we hetzelfde cookie voor de sessies PHP van de client en de browser [nuxt]? We willen dat de applicatie met de server PHP kan communiceren, ongeacht of het om de client of de server [nuxt] gaat:
- als een actie A van de server [nuxt] de server PHP in een toestand E brengt, wordt deze toestand weerspiegeld in de sessie PHP die door de server PHP wordt onderhouden;
- door gebruik te maken van hetzelfde sessiecookie PHP als de server, zou een actie B van de client [nuxt], die volgt op actie A van de server [nuxt], de server PHP aantreffen in detoestand E die door de server [nuxt] is achtergelaten en zou dus kunnen voortbouwen op het werk dat al door de server [nuxt] is verricht;
- als na actie B van de client [nuxt] een actie C van de server [nuxt] volgt, zal deze actie om dezelfde reden als hierboven het werk kunnen gebruiken dat is verricht door actie B van de client [nuxt];
Om ervoor te zorgen dat de browser van de klant [nuxt] kan communiceren met de belastingberekeningsserver PHP, gebruiken we versie 14 van deze server, die domeinoverschrijdende oproepen toestaat, d.w.z. verzoeken van een browser naar de server PHP. Verzoeken van de server [nuxt] naar de server PHP zijn daarentegen geen inter-domeinverzoeken. Dit begrip geldt alleen voor verzoeken die vanuit een browser worden gedaan.
Laten we teruggaan naar de code van de constructor van de vorige klasse [Dao]:
// constructor
constructor(axios) {
this.axios = axios;
// sessiecookie
this.sessionCookieName = "PHPSESSID";
this.sessionCookie = '';
}
- regels 5 en 6 hebben betrekking op de sessiecookie PHP met de server voor de belastingberekening;
Het beheer van de bovengenoemde sessiecookie PHP is niet geschikt voor de server [nuxt]: de laag [dao] wordt bij elk nieuw verzoek aan de server [nuxt] geïnstantieerd. We herinneren ons immers dat het opvragen van een pagina bij de server [nuxt] neerkomt op het opnieuw opstarten van de applicatie [nuxt]. Wanneer dus na afloop van het eerste verzoek dat door de server [nuxt] aan de gegevensserver wordt gedaan, het sessiecookie PHP van de laag [dao] wordt geïnitialiseerd, gaat deze waarde verloren bij het volgende verzoek HTTP van dezelfde server [nuxt], omdat ondertussen de laag [dao] opnieuw is aangemaakt, de constructor opnieuw is uitgevoerd en de sessiecookie PHP is gereset met de lege tekenreeks (regel 6);
Een oplossing is om een andere constructor te gebruiken voor de laag [dao] van de server:
// constructor
constructor(axios, phpSessionCookie) {
// axios-bibliotheek
this.axios = axios
// waarde van het sessiecookie
this.phpSessionCookie = phpSessionCookie
// naam van de sessiecookie van de server PHP
this.phpSessionCookieName = 'PHPSESSID'
}
- regel 2: deze keer wordt het sessiecookie PHP doorgegeven aan de constructor van de laag [dao] van de gegevensserver;
Hoe kan de server [nuxt] dit sessiecookie PHP aan de constructor van zijn laag [dao] verstrekken? We zullen de sessiecookie PHP opslaan in de sessiecookie [nuxt] die wordt uitgewisseld tussen de browser en de server [nuxt]. Het proces verloopt als volgt:
- de applicatie [nuxt] wordt gestart;
- wanneer de server [nuxt] zijn eerste verzoek HTTP doet aan de server PHP, slaat hij de sessiecookie PHP die hij heeft ontvangen op in de sessiecookie [nuxt] die hij uitwisselt met de client [nuxt];
- de browser waarop de client [nuxt] draait, ontvangt dit sessiecookie [nuxt] en stuurt het dus systematisch terug bij elk nieuw verzoek aan de server [nuxt];
- wanneer de server [nuxt] een nieuw verzoek moet doen aan de server PHP, zal hij de sessiecookie PHP terugvinden in de sessiecookie [nuxt] die de browser naar hem heeft verzonden. Vervolgens stuurt hij deze door naar de server PHP;
Er zijn inderdaad twee sessiecookies en deze mogen niet met elkaar worden verward:
- het sessiecookie [nuxt] dat wordt uitgewisseld tussen de server [nuxt] en de browser van de klant [nuxt];
- de sessiecookie PHP die wordt uitgewisseld tussen de server [nuxt] en de server PHP of tussen de client [nuxt] en de server PHP;
Laten we nu terugkeren naar de code van de methode van de klasse [Dao]. Deze bevat geen functie om de sessie PHP met de belastingberekeningsserver af te sluiten. We voegen deze toe:
// einde van de sessie voor de belastingberekening
async finSession() {
// verzoekopties HHTP [get /main.php?action=fin-session]
const options = {
method: 'GET',
// parameters van de URL
params: {
action: 'fin-session'
}
}
// uitvoering van de query HTTP
const data = await this.getRemoteData(options)
// resultaat
return data
}
Bij het testen blijkt dat de functie [getRemoteData], die in regel 12 wordt aangeroepen, niet geschikt is voor de methode [finSession]:
async getRemoteData(options) {
// voor de sessiecookie
if (!options.headers) {
options.headers = {};
}
options.headers.Cookie = this.sessionCookie;
// uitvoering van de aanvraag HTTP
let response;
try {
// asynchrone aanvraag
response = await this.axios.request('main.php', options);
} catch (error) {
// de parameter [error] is een uitzondering – deze kan verschillende vormen aannemen
if (error.response) {
// het antwoord van de server staat in [error.response]
response = error.response;
} else {
// de fout wordt opnieuw gegenereerd
throw error;
}
}
// response is het volledige antwoord HTTP van de server (headers HTTP + het antwoord zelf)
// de sessiecookie wordt opgehaald, indien deze bestaat
const setCookie = response.headers['set-cookie'];
if (setCookie) {
// setCookie is een array
// we zoeken de sessiecookie in deze array
let trouvé = false;
let i = 0;
while (!trouvé && i < setCookie.length) {
// we zoeken naar de sessiecookie
const results = RegExp('^(' + this.sessionCookieName + '.+?);').exec(setCookie[i]);
if (results) {
// de sessiecookie wordt opgeslagen
// eslint-disable-next-line require-atomic-updates
this.sessionCookie = results[1];
// gevonden
trouvé = true;
} else {
// volgend element
i++;
}
}
}
// het antwoord van de server staat in [response.data]
return response.data;
}
- regels 30-43: er wordt gezocht naar de cookie [PHPSESSID=xxx]. Als deze wordt gevonden, wordt hij opgeslagen in de klasse (regel 36);
Deze code is niet geschikt voor de nieuwe methode [finSession], omdat bij de actie [fin-session] de server PHP twee cookies verstuurt met de naam [PHPSESSID]. Hier volgt een voorbeeld dat is verkregen met een client [Postman]:

- in [1], het verzoek van de client [Postman];
- in [3], het antwoord van de server PHP;
- in [4], de headers HTTP van het antwoord van de server PHP;

- in [5] geeft de server PHP eerst aan dat hij de huidige sessie PHP heeft verwijderd;
- in [6] stuurt de server PHP de cookie van de nieuwe sessie PHP;
Met de huidige code haalt de functie [getRemoteData] het cookie [5] op, terwijl het cookie [6] moet worden opgeslagen.
De code van de functie [getRemoteData] moet dus worden aangepast:
async getRemoteData(options) {
// is er een sessiecookie PHP?
if (this.phpSessionCookie) {
// zijn er headers?
if (!options.headers) {
// er wordt een leeg object aangemaakt
options.headers = {}
}
// header van de sessiecookie PHP
options.headers.Cookie = this.phpSessionCookie
}
// het verzoek wordt uitgevoerd HTTP
let response
try {
// asynchroon verzoek
response = await this.axios.request('main.php', options)
} catch (error) {
// de parameter [error] is een uitzondering – deze kan verschillende vormen aannemen
if (error.response) {
// het antwoord van de server staat in [error.response]
response = error.response
} else {
// de fout wordt opnieuw gegenereerd
throw error
}
}
// response is het volledige antwoord HTTP van de server (headers HTTP + het antwoord zelf)
// we zoeken naar de sessiecookie PHP in de ontvangen cookies
// alle ontvangen cookies
const cookies = response.headers['set-cookie']
if (cookies) {
// cookies is een array
// er wordt gezocht naar de sessiecookie PHP in deze array
let trouvé = false
let i = 0
while (!trouvé && i < cookies.length) {
// we zoeken naar de sessiecookie PHP
const results = RegExp('^(' + this.phpSessionCookieName + '.+?)$').exec(cookies[i])
if (results) {
// de sessiecookie PHP wordt opgeslagen
const phpSessionCookie = results[1]
// zit het woord [deleted] erin?
const results2 = RegExp(this.phpSessionCookieName + '=deleted').exec(phpSessionCookie)
if (!results2) {
// we hebben de juiste sessiecookie PHP
this.phpSessionCookie = phpSessionCookie
// gevonden
trouvé = true
} else {
// volgend element
i++
}
} else {
// volgend element
i++
}
}
}
// het antwoord van de server staat in [response.data]
return response.data
}
- regel 41: er is een cookie gevonden met de naam [PHPSESSID]. Deze wordt lokaal opgeslagen;
- regel 43: we controleren of de opgeslagen cookie de tekenreeks [PHPSESSID=deleted] bevat;
- regel 46: als het antwoord nee is, dan hebben we de juiste cookie [PHPSESSID] gevonden. We slaan deze op in de klasse;
Na de functie [getRemoteData] wordt de sessiecookie PHP in de klasse opgeslagen, in [this.phpSessionCookie]. We hebben gezegd dat de klasse bij elk nieuw verzoek HTTP van de server [nuxt] wordt geïnstantieerd. De sessiecookie PHP moet dus uit de klasse worden geëxfiltreerd. Hiervoor voegen we een nieuwe methode toe aan de klasse:
// toegang tot de sessiecookie PHP
getPhpSessionCookie() {
return this.phpSessionCookie
}
- de server [nuxt] vraagt een actie aan bij zijn laag [dao] door het sessiecookie PHP aan de constructor ervan door te geven, indien deze er een heeft;
- zodra de actie is uitgevoerd, haalt de server [nuxt] de sessiecookie PHP op die door de laag [dao] is opgeslagen met behulp van de voorgaande methode [getPhpSessionCookie]. Dit cookie kan hetzelfde zijn als het vorige of een ander. Dit laatste geval doet zich in twee situaties voor:
- tijdens de uitvoering van de methode [initSession] (er was voorheen geen sessiecookie PHP);
- bij het uitvoeren van de methode [finSession] (de server PHP wijzigt de sessiecookie PHP);
Er is een bijzonderheid met betrekking tot de sessiecookie PHP. De server [nuxt] ontvangt deze cookie niet altijd van de server PHP. Deze laatste verstuurt de cookie namelijk slechts één keer. Daarna verstuurt hij het niet meer. Als we de code van [getRemoteData] en die van [getPhpSessionCookie] bekijken, zien we dat wanneer de server PHP geen sessiecookie verstuurt, de functie [getPhpSessionCookie] het sessiecookie PHP terugstuurt dat aan de constructor is doorgegeven. Op deze manier stuurt de server altijd het laatste sessiecookie PHP, dat de server PHP hem heeft gestuurd, terug naar die server.
15.5.2. De laag [dao] van de client [nuxt]

Voor de client [nuxt] die in een browser draait, gebruiken we de code van de klasse [Dao] uit het document |Inleiding tot het VUE.JS-framework aan de hand van een voorbeeld|:
"use strict";
// imports
import qs from "qs";
class Dao {
// constructor
constructor(axios) {
this.axios = axios;
}
// sessie initialiseren
async initSession() {
// verzoekopties HHTP [get /main.php?action=init-session&type=json]
const options = {
method: "GET",
// parameters van de URL
params: {
action: "init-session",
type: "json"
}
};
// uitvoering van de query HTTP
return await this.getRemoteData(options);
}
async authentifierUtilisateur(user, password) {
// opties van de query HHTP [post /main.php?action=authentifier-utilisateur]
const options = {
method: "POST",
headers: {
"Content-type": "application/x-www-form-urlencoded"
},
// hoofdtekst van de POST
data: qs.stringify({
user: user,
password: password
}),
// parameters van de URL
params: {
action: "authentifier-utilisateur"
}
};
// uitvoering van de query HTTP
return await this.getRemoteData(options);
}
async getAdminData() {
// opties van de aanvraag HHTP [get /main.php?action=get-admindata]
const options = {
method: "GET",
// parameters van de URL
params: {
action: "get-admindata"
}
};
// uitvoering van de query HTTP
const data = await this.getRemoteData(options);
// resultaat
return data;
}
async getRemoteData(options) {
// uitvoering van de query HTTP
let response;
try {
// asynchrone aanvraag
response = await this.axios.request("main.php", options);
} catch (error) {
// de parameter [error] is een uitzondering – deze kan verschillende vormen aannemen
if (error.response) {
// het antwoord van de server staat in [error.response]
response = error.response;
} else {
// de fout wordt opnieuw gegenereerd
throw error;
}
}
// response is het volledige antwoord HTTP van de server (HTTP-headers + het antwoord zelf)
// het antwoord van de server staat in [response.data]
return response.data;
}
}
// export van de klasse
export default Dao;
Deze code onderscheidt zich van de laag [dao] van de server [nuxt] doordat deze de sessiecookie PHP niet met de belastingberekeningsserver afhandelt: dat doet de browser.
Net zoals we hebben gedaan voor de laag [dao] van de server [nuxt], gaan we een methode [finSession] toevoegen:
// einde van de belastingberekeningssessie
async finSession() {
// opties van de aanvraag HHTP [get /main.php?action=fin-session]
const options = {
method: 'GET',
// parameters van de URL
params: {
action: 'fin-session'
}
}
// uitvoering van de query HTTP
const data = await this.getRemoteData(options)
// resultaat
return data
}
Wanneer de client [nuxt] deze methode uitvoert, ontvangt hij, net als de server [nuxt], twee sessiecookies PHP. Het is in feite de browser die deze ontvangt en deze situatie correct afhandelt: hij bewaart alleen het cookie van de nieuwe sessie PHP die door de server voor belastingberekening is gestart. Dus bij de volgende actie van de client [nuxt] naar de server PHP zal de sessiecookie PHP correct zijn, omdat de browser deze verstuurt. Er is echter een probleem: de server [nuxt] weet niet dat de sessiecookie PHP is gewijzigd. Bij de communicatie met de server PHP zal de client dan een sessiecookie PHP versturen die niet meer bestaat, en dat leidt tot problemen. De client [nuxt] zou de server [nuxt] moeten melden dat het sessiecookie PHP is gewijzigd en dit aan de server moeten doorgeven. We weten hoe hij dit kan doen: via de sessiecookie [nuxt], de cookie die tussen de client en de server [nuxt] wordt uitgewisseld. De client [nuxt] heeft ten minste twee manieren om het nieuwe sessiecookie PHP op te halen:
- door het op te vragen bij de browser;
- door gebruik te maken van de methode [getRemoteData] van de server, die weet hoe het nieuwe sessiecookie PHP kan worden opgehaald;
We gaan de tweede oplossing gebruiken, omdat die al kant-en-klaar is. De methode [getRemoteData] van de client [nuxt] ziet er dan als volgt uit:
async getRemoteData(options) {
// uitvoering van de query HTTP
let response
try {
// asynchrone aanvraag
response = await this.axios.request('main.php', options)
} catch (error) {
// de parameter [error] is een uitzondering – deze kan verschillende vormen aannemen
if (error.response) {
// het antwoord van de server staat in [error.response]
response = error.response
} else {
// de fout wordt opnieuw gegenereerd
throw error
}
}
// response is het volledige antwoord HTTP van de server (headers HTTP + het antwoord zelf)
// we zoeken naar de sessiecookie PHP in de ontvangen cookies
// alle ontvangen cookies
const cookies = response.headers['set-cookie']
if (cookies) {
// cookies is een array
// er wordt gezocht naar de sessiecookie PHP in deze array
let trouvé = false
let i = 0
while (!trouvé && i < cookies.length) {
// we zoeken naar de sessiecookie PHP
const results = RegExp('^(' + this.phpSessionCookieName + '.+?)$').exec(cookies[i])
if (results) {
// de sessiecookie PHP wordt opgeslagen
const phpSessionCookie = results[1]
// zit het woord [deleted] erin?
const results2 = RegExp(this.phpSessionCookieName + '=deleted').exec(phpSessionCookie)
if (!results2) {
// we hebben de juiste sessiecookie PHP
this.phpSessionCookie = phpSessionCookie
// gevonden
trouvé = true
} else {
// volgend element
i++
}
} else {
// volgend element
i++
}
}
}
// het antwoord van de server staat in [response.data]
return response.data
}
We hebben in [getRemoteData] alleen de code behouden die het antwoord van de server PHP verwerkt om het sessiecookie PHP te vinden. De code die de sessiecookie PHP in het verzoek aan de server PHP opnam, is niet behouden, omdat de browser waarin de client [nuxt] draait, dit zelf regelt.
Zodra de sessiecookie PHP door de client [nuxt] is verkregen, moet deze in de sessie [nuxt] worden geplaatst, zodat de server [nuxt] hiervan gebruik kan maken. De laag [dao] zorgt hier niet voor, maar biedt via een methode toegang tot de sessiecookie PHP die zij heeft opgeslagen:
// toegang tot de sessiecookie PHP
getPhpSessionCookie() {
return this.phpSessionCookie
}
De functie [getPhpSessionCookie] levert niet altijd een geldige sessiecookie op:
- hierbij moet worden bedacht dat de laag [dao] van de client [nuxt] persistent is. Deze wordt eenmaal geïnstantieerd en blijft vervolgens in het geheugen;
- zolang de server PHP geen sessiecookie PHP naar de client [nuxt] verstuurt, geeft de functie [getPhpSessionCookie] van de client [nuxt] de waarde [undefined] terug;
- wanneer de server PHP een sessiecookie PHP naar de client [nuxt] verstuurt, wordt dit opgeslagen in [this.phpSessionCookie] en blijft daar staan totdat het wordt vervangen door een nieuw sessiecookie PHP dat door de server PHP wordt verzonden. De functie [getPhpSessionCookie] van de client [nuxt] retourneert vervolgens de laatst ontvangen sessiecookie PHP;
De laag [dao] van de client [nuxt] verschilt slechts op één punt van die van de server [nuxt]: ze verstuurt de sessiecookie PHP niet zelf, omdat de browser dit doet. Toch hebben we ervoor gekozen om twee afzonderlijke lagen [dao] te behouden, omdat de redeneringen die tot hun respectievelijke schrijfwijzen leiden, verschillend zijn.
15.6. De sessie [nuxt]
![]()
De sessie [nuxt] (tussen de client en de Nuxt-server) wordt ingekapseld in het volgende object [session]:
/* eslint-disable no-console */
// sessie-instelling
const session = {
// inhoud van de sessie
value: {
// store niet geïnitialiseerd
initStoreDone: false,
// waarde van de Vuex-store
store: ''
},
// sessie opslaan in een cookie
save(context) {
// opslag van de store in de sessie
this.value.store = context.store.state
console.log('nuxt-session save=', this.value)
// de waarde van de sessie opslaan
context.app.$cookies.set('nuxt-session', this.value, { path: context.base, maxAge: context.env.maxAge })
},
// sessie resetten
reset(context) {
console.log('nuxt-session reset')
// de store resetten
context.store.commit('reset')
// de nieuwe store opslaan in de sessie en de sessie opslaan
this.save(context)
}
}
// sessie exporteren
export default session
- regels 5-10: de sessie heeft slechts één eigenschap, [value], met twee sub-eigenschappen:
- [initStoreDone], die aangeeft of de store al dan niet is geïnitialiseerd;
- [store]: de waarde [store.state] van de Vuex-store van de applicatie;
- regels 12-18: de methode [save] wordt gebruikt om de sessie [nuxt] in een cookie op te slaan. Hier wordt de bibliotheek [cookie-universal-nuxt] gebruikt om de cookie te beheren. Let op de naam van de sessiecookie [nuxt]: [nuxt-session] (regel 17);
- regels 20-26: de methode [reset] reset de sessie [nuxt];
- regel 23: de Vuex-store wordt gereset en vervolgens opgeslagen in de sessie, regel 25;
15.7. De plug-ins voor sessiebeheer [nuxt]

15.7.1. De sessiebeheer-plugin [nuxt] van serveur [nuxt]
Bij het opstarten van de applicatie is de server [nuxt] de eerste die actief wordt. Deze zal dus de sessie [nuxt] initialiseren. Het script [server/plgSession] is als volgt:
/* eslint-disable no-console */
// sessie importeren
import session from '@/entities/session'
export default (context, inject) => {
// beheer van de serversessie
console.log('[plugin server plgSession]')
// is er al een sessie?
const value = context.app.$cookies.get('nuxt-session')
if (!value) {
// nieuwe sessie
console.log("[plugin server plgSession], démarrage d'une nouvelle session")
} else {
// bestaande sessie
console.log("[plugin server plgSession], reprise d'une session existante")
session.value = value
}
// er wordt een functie geïnjecteerd in [context, Vue] die de huidige sessie zal activeren
inject('session', () => session)
}
- regel 4: de code van de sessie [nuxt] wordt geïmporteerd;
- regel 11: de waarde van de sessiecookie van de sessie [nuxt] wordt opgehaald;
- regels 12-15: als de sessiecookie [nuxt] niet bestond, dan is de in regel 4 geïmporteerde sessie [nuxt] voldoende. Er hoeft verder niets te gebeuren;
- regels 15-19: als de sessiecookie [nuxt] wel bestond, dan wordt in regel 18 de waarde ervan opgeslagen in de in regel 4 geïmporteerde sessie;
- regel 22: de sessie is ofwel geïnitialiseerd ofwel hersteld. We maken deze beschikbaar via de functie [$session];
15.7.2. De sessiebeheerplugin [nuxt] van de client [nuxt]
Het script [client/plgSession] is als volgt:
/* eslint-disable no-console */
// de sessie importeren
import session from '@/entities/session'
export default (context, inject) => {
// beheer van de clientsessie
console.log('[plugin client plgSession], reprise de la session [nuxt] du serveur')
// de bestaande sessie wordt opgehaald van de Nuxt-server
session.value = context.app.$cookies.get('nuxt-session')
// we injecteren een functie in [context, Vue] die de huidige sessie instelt
inject('session', () => session)
}
- regel 4: de sessie [nuxt] wordt geïmporteerd;
- regel 10: de huidige sessie [nuxt] wordt opgehaald uit de cookie [nuxt-session];
- regel 13: de in regel 4 geïmporteerde sessie [nuxt] wordt via de geïnjecteerde functie [$session] teruggegeven;
15.8. De plug-ins van de lagen [dao]

15.8.1. De plug-in van de laag [dao] van de client [nuxt]
Het script [client/plgDao] is als volgt:
/* eslint-disable no-console */
// we maken een toegangspunt naar de laag [Dao]
import Dao from '@/api/client/Dao'
export default (context, inject) => {
// configuratie van Axios
context.$axios.defaults.timeout = context.env.timeout
context.$axios.defaults.baseURL = context.env.baseURL
context.$axios.defaults.withCredentials = context.env.withCredentials
// instantiëren van de laag [dao]
const dao = new Dao(context.$axios)
// injectie van een functie [$dao] in de context
inject('dao', () => dao)
// log
console.log('[fonction client $dao créée]')
}
- regel 3: de laag [dao] van de client [nuxt] wordt geïmporteerd;
- regels 6-8: hetobject [context.$axios] dat de verzoeken HTTP van de laag [dao] van de client [nuxt] zal uitvoeren met de informatie uit het bestand [nuxt.config]:
// omgeving
env: {
// axios-configuratie
timeout: 2000,
withCredentials: true,
baseURL: 'http://localhost/php7/scripts-web/impots/version-14',
// configuratie van de sessiecookie [nuxt]
maxAge: 60 * 5
}
- regel 10: de laag [dao] van de client [nuxt] wordt geïnstantieerd;
- regel 12: de functie [$dao] wordt in de context en de pagina’s van de klant geïnjecteerd. Deze functie geeft toegang tot de laag [dao] van regel 10;
We onthouden dus dat om toegang te krijgen tot de laag [dao] van de client [nuxt] wanneer deze wordt uitgevoerd, we het volgende schrijven:
- [context.app.$dao()] wanneer de context bekend is;
- [this.$dao()] in een pagina [Vue.js];
15.8.2. De plug-in van de laag [dao] van de serveur [nuxt]
Het script [server/plgDao] is als volgt:
/* eslint-disable no-console */
// we maken een toegangspunt aan naar de laag [Dao]
import Dao from '@/api/server/Dao'
export default (context, inject) => {
// configuratie van Axios
context.$axios.defaults.timeout = context.env.timeout
context.$axios.defaults.baseURL = context.env.baseURL
// we halen de sessiecookie op
const store = context.app.$session().value.store
const phpSessionCookie = store ? store.phpSessionCookie : ''
console.log('session=', context.app.$session().value, 'phpSessionCookie=', phpSessionCookie)
// instantiëren van de laag [dao]
const dao = new Dao(context.$axios, phpSessionCookie)
// injectie van een functie [$dao] in de context
inject('dao', () => dao)
// log
console.log('[fonction server $dao créée]')
}
- regel 3: de laag [dao] van de server [nuxt] wordt geïmporteerd;
- regels 6-7: hetobject [context.$axios] dat de verzoeken HTTP van de laag [dao] van de server [nuxt] zal uitvoeren met de informatie uit het bestand [nuxt.config]:
// omgeving
env: {
// axios-configuratie
timeout: 2000,
withCredentials: true,
baseURL: 'http://localhost/php7/scripts-web/impots/version-14',
// configuratie van de sessiecookie [nuxt]
maxAge: 60 * 5
}
- regel 9: we halen de store van de applicatie [nuxt] op;
- regel 10: als de store bestaat, wordt de sessiecookie van PHP opgehaald, omdat deze nodig is om de laag [dao] van de server [nuxt] te instantiëren;
- regel 13: de laag [dao] van de server [nuxt] wordt geïnstantieerd;
- regel 15: de functie [$dao] wordt geïnjecteerd in de context en de pagina’s van de server [nuxt]. Deze functie geeft toegang tot de laag [dao] uit regel 13;
We onthouden dus dat om toegang te krijgen tot de laag [dao] van de server [nuxt] wanneer deze wordt uitgevoerd, we het volgende schrijven:
- [context.app.$dao()] wanneer de context bekend is;
- [this.$dao()] in een pagina [Vue.js];
15.9. De Vuex-store
![]()
De store [Vuex] slaat alle gegevens op die door de verschillende componenten van de applicatie [pages, client, serveur] moeten worden gedeeld, zonder dat deze gegevens reactief zijn.
/* eslint-disable no-console */
// status van de store
export const state = () => ({
// sessie jSON gestart
jsonSessionStarted: false,
// gebruiker geauthenticeerd
userAuthenticated: false,
// sessiecookie PHP
phpSessionCookie: '',
// adminData
adminData: ''
})
// wijzigingen in de store
export const mutations = {
// vervanging van de status
replace(state, newState) {
for (const attr in newState) {
state[attr] = newState[attr]
}
},
// reset van de store
reset() {
this.commit('replace', { jsonSessionStarted: false, userAuthenticated: false, phpSessionCookie: '', adminData: '' })
}
}
// acties van de store
export const actions = {
nuxtServerInit(store, context) {
// wie voert deze code uit?
console.log('nuxtServerInit, client=', process.client, 'serveur=', process.server, 'env=', context.env)
// sessie initialiseren
initStore(store, context)
}
}
function initStore(store, context) {
// store is de store die moet worden geïnitialiseerd
// de sessie wordt opgehaald
const session = context.app.$session()
// is de sessie al geïnitialiseerd?
if (!session.value.initStoreDone) {
// er wordt een nieuwe store gestart
console.log("nuxtServerInit, initialisation d'une nouvelle session")
// de store wordt aan de sessie toegevoegd
session.value.store = store.state
// de store is nu geïnitialiseerd
session.value.initStoreDone = true
} else {
console.log("nuxtServerInit, reprise d'un store existant")
// de store wordt bijgewerkt met de store van de sessie
store.commit('replace', session.value.store)
}
// de sessie wordt opgeslagen
session.save(context)
// log
console.log('initStore terminé, store=', store.state)
}
De volgende gegevens worden in de store opgeslagen:
- regel 6: [jsonSessionStarted] wordt op ‘waar’ gezet zodra de initialisatie van een sessie jSON met de server PHP is geslaagd, ongeacht of deze is uitgevoerd door de client of de server [nuxt]. Na afloop van deze initialisatie is het sessiecookie met de server PHP opgehaald en geplaatst in de eigenschap [phpSessionCookie], regel 10;
- regel 8: [userAuthenticated] wordt op ‘waar’ gezet zodra de authenticatie bij de server PHP is geslaagd, ongeacht of deze is uitgevoerd door de client of de server [nuxt];
- regel 12: [adminData] is de waarde [adminData] die is verkregen van de server PHP zodra de authenticatie is geslaagd;
- regels 18-22: de mutatie [replace] maakt het mogelijk de voorgaande eigenschappen te initialiseren met die van een als parameter doorgegeven object;
- regels 24-26: de mutatie [reset] zet de eigenschappen van de store terug naar hun oorspronkelijke waarden;
- regels 31-37: de functie [nuxtServerInit] delegeert haar taak aan de functie [initStore];
- regels 39-60: de functie [initStore] heeft twee taken:
- als de store nog niet is geïnitialiseerd, wordt deze geïnitialiseerd en in de sessie opgenomen;
- als de store al is geïnitialiseerd, wordt de waarde ervan opgehaald uit de sessie [nuxt];
- regel 42: de Nuxt-sessie wordt opgehaald;
- regel 44: er wordt gecontroleerd of de store is geïnitialiseerd:
- als dat niet het geval is, wordt de initiële store in de sessie geplaatst (regel 48);
- vervolgens wordt in regel 50 aangegeven dat de store is geïnitialiseerd;
- regels 51-55: als de store al was geïnitialiseerd, wordt deze gebruikt, regel 54, om de store te initialiseren met de waarde die in de sessie staat;
- regel 57: in alle gevallen wordt de sessie opgeslagen in de cookie [nuxt-session], samen met de store die deze bevat;
15.10. De plug-in [plgEventBus]

Deze plug-in is bedoeld om een gebeurtenissenbus toegankelijk te maken voor de client [nuxt] via een functie [$eventBus] die in de context van de client [nuxt] wordt geïnjecteerd. Het heeft geen zin om deze in de context van de [nuxt]-server te injecteren, aangezien deze geen gebeurtenissen kan verwerken. We hebben echter al gezien dat het injecteren aan de serverzijde en het vervolgens gebruiken ervan geen fout veroorzaakt.
/* eslint-disable no-console */
// er wordt een gebeurtenissenbus tussen de weergaven aangemaakt
import Vue from 'vue'
export default (context, inject) => {
// de gebeurtenissenbus
const eventBus = new Vue()
// injectie van een functie [$eventBus] in de context
inject('eventBus', () => eventBus)
// log
console.log('[fonction $eventBus créée]')
}
We zijn deze plug-in al tegengekomen in de paragraaf over links. De functie [$eventBus] is beschikbaar voor de client via de notaties:
- [context.app.$eventBus()] wanneer de context beschikbaar is;
- [this.$eventBus()] op de [Vue.js]-pagina’s van de client;
15.11. De componenten van de applicatie [nuxt]

De component [layout] is die uit de voorgaande voorbeelden:
<!-- indeling van de weergaven -->
<template>
<!-- regel -->
<div>
<b-row>
<!-- veld met drie kolommen -->
<b-col v-if="left" cols="3">
<slot name="left" />
</b-col>
<!-- gebied met negen kolommen -->
<b-col v-if="right" cols="9">
<slot name="right" />
</b-col>
</b-row>
</div>
</template>
<script>
export default {
// instellingen
props: {
left: {
type: Boolean
},
right: {
type: Boolean
}
}
}
</script>
De component [navigation] is de volgende:
<template>
<!-- Bootstrap-menu met drie opties -->
<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. De lay-outs van de applicatie [nuxt]

15.12.1. [default]
De lay-out [default] is de lay-out die wordt gebruikt voor het voorbeeld [nuxt-11] in de paragraaf 'link':
<template>
<div class="container">
<b-card>
<!-- een bericht -->
<b-alert show variant="success" align="center">
<h4>[nuxt-12] : requêtes HTTP avec axios</h4>
</b-alert>
<!-- het huidige routeringsscherm -->
<nuxt />
<!-- wachtmelding -->
<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>
<!-- fout bij een asynchrone bewerking -->
<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
}
},
// levenscyclus
beforeCreate() {
console.log('[default beforeCreate]')
},
created() {
console.log('[default created]')
if (process.client) {
// we luisteren naar de gebeurtenis [loading]
this.$eventBus().$on('loading', this.mShowLoading)
// evenals de gebeurtenis [errorLoadingMessage]
this.$eventBus().$on('errorLoading', this.mShowErrorLoading)
}
},
beforeMount() {
console.log('[default beforeMount]')
},
mounted() {
console.log('[default mounted]')
},
methods: {
// beheer van het wachtbericht
mShowLoading(value) {
console.log('[default mShowLoading], showLoading=', value)
this.showLoading = value
},
// fout bij een asynchrone bewerking
mShowErrorLoading(value, errorLoadingMessage) {
console.log('[default mShowErrorLoading], showErrorLoading=', value, 'errorLoadingMessage=', errorLoadingMessage)
this.showErrorLoading = value
this.errorLoadingMessage = errorLoadingMessage
}
}
}
</script>
- regels 10-14: geven het bericht weer dat er wordt gewacht op het einde van een asynchrone bewerking van de client [nuxt];
- regels 15-18: geven het eventuele foutbericht van een asynchrone bewerking weer;
- regel 37: de functie [created] van de pagina [default] wordt uitgevoerd vóór de functie [mounted] van de pagina’s;
- regel 39: als de uitvoerder de client [nuxt] is, dan luistert de pagina [default] naar de gebeurtenissen:
- [loading] die het begin of einde van een wachttijd aangeeft. Vervolgens wordt de functie [mShowLoading] uitgevoerd;
- [errorLoading], die aangeeft dat er een foutmelding moet worden weergegeven. De functie [mShowErrorLoading] wordt dan uitgevoerd;
- de pagina's [nuxt]:
- geven de wachtmelding weer door de gebeurtenis [‘loading’, true] op de gebeurtenissenbus te verzenden;
- verbergen het wachtbericht door de gebeurtenis [‘loading’, false] op de gebeurtenissenbus te verzenden;
- geven een foutmelding weer door de gebeurtenis [‘errorLoading’, true] op de gebeurtenissenbus te verzenden;
- verbergen het foutbericht door de gebeurtenis [‘errorLoading’, false] op de gebeurtenissenbus te verzenden;
15.12.2. [error]
De lay-out [error] geeft een systeemfoutmelding weer (niet beheerd door de ontwikkelaar):
<!-- definitie van de weergave HTML -->
<template>
<!-- pagina-indeling -->
<Layout :left="true" :right="true">
<!-- waarschuwing in de rechterkolom -->
<template slot="right">
<!-- bericht op roze achtergrond -->
<b-alert show variant="danger" align="center">
<h4>L'erreur suivante s'est produite : {{ JSON.stringify(error) }}</h4>
</b-alert>
</template>
<!-- navigatiemenu in de linkerkolom -->
<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',
// gebruikte componenten
components: {
Layout,
Navigation
},
// eigenschap [props]
props: { error: { type: Object, default: () => 'waiting ...' } },
// levenscyclus
beforeCreate() {
// client en server
console.log('[error beforeCreate]')
},
created() {
// client en server
console.log('[error created, error=]', this.error)
},
beforeMount() {
// alleen client
console.log('[error beforeMount]')
},
mounted() {
// alleen client
console.log('[error mounted]')
}
}
</script>
15.13. De pagina [index] wordt uitgevoerd door de server [nuxt]

De pagina [index.vue] heeft als bijzonderheid dat deze uitsluitend toegankelijk is via de server [nuxt]. Er wordt geen link aan de gebruiker getoond om er toegang toe te krijgen via de client [nuxt]. De code ervan is als volgt:
<!-- hoofdpagina -->
<template>
<Layout :left="true" :right="true">
<!-- navigatie -->
<Navigation slot="left" />
<!-- bericht-->
<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',
// gebruikte componenten
components: {
Layout,
Navigation
},
// asynchrone gegevens
async asyncData(context) {
// log
console.log('[index asyncData started]')
try {
// een sessie wordt gestart jSON
const dao = context.app.$dao()
const response = await dao.initSession()
// log
console.log('[index asyncData response=]', response)
// de sessiecookie PHP wordt opgehaald voor de volgende verzoeken
const phpSessionCookie = dao.getPhpSessionCookie()
// de sessiecookie PHP wordt opgeslagen in de sessie [nuxt]
context.store.commit('replace', { phpSessionCookie })
// is er een fout opgetreden?
if (response.état !== 700) {
// de fout bevindt zich in response.réponse
throw new Error(response.réponse)
}
// we merken op dat de sessie jSON is gestart
context.store.commit('replace', { jsonSessionStarted: true })
// het resultaat wordt weergegeven
return { result: '[succès]' }
} catch (e) {
// log
console.log('[index asyncData error=]', e)
// er wordt gemeld dat de sessie jSON niet is gestart
context.store.commit('replace', { jsonSessionStarted: false })
// de fout wordt gemeld
return { result: '[échec]', showErrorLoading: true, errorLoadingMessage: e.message }
} finally {
// de store wordt opgeslagen
const session = context.app.$session()
session.save(context)
// log
console.log('[index asyncData finished]')
}
},
// levenscyclus
beforeCreate() {
console.log('[index beforeCreate]')
},
created() {
console.log('[index created]')
},
beforeMount() {
console.log('[index beforeMount]')
},
mounted() {
console.log('[index mounted]')
// alleen client
if (this.showErrorLoading) {
console.log('[index mounted, showErrorLoading=true]')
this.$eventBus().$emit('errorLoading', true, this.errorLoadingMessage)
}
}
}
</script>
- regel 7: de pagina toont het resultaat [result] van een asynchrone aanvraag (regels 46 en 51);
- regel 31: de asynchrone bewerking is het openen van een sessie jSON met de server voor de belastingberekening;
- regel 25: we weten dat wanneer de pagina rechtstreeks bij de server [nuxt] wordt opgevraagd, de functie [asyncData] alleen door de server wordt uitgevoerd en niet door de client [nuxt], die wordt uitgevoerd wanneer de browser het antwoord van de server [nuxt] heeft ontvangen;
- regel 30: de laag [dao] wordt opgehaald in de context van de server [nuxt];
- regel 35: als de server nog geen verzoek had verzonden naar de server voor de belastingberekening, ontvangt hij zijn eerste sessiecookie PHP; anders ontvangt hij de laatste sessiecookie PHP die hij heeft ontvangen (zie de code van de laag [dao] van de server [nuxt] in de paragraaf met de link);
- regel 37: dit sessiecookie PHP wordt opgeslagen in de store;
- regels 39-42: er wordt gecontroleerd of de bewerking is geslaagd. Als dat niet het geval is, wordt er een uitzondering gegenereerd die wordt opgevangen door de [catch] in regel 47;
- regel 44: er wordt in de store genoteerd dat de sessie jSON met de server PHP is gestart;
- regel 46: het resultaat [result] wordt geretourneerd en weergegeven op regel 7;
- regels 47-54: een eventuele uitzondering wordt afgehandeld. Deze kan van twee soorten zijn:
- de bewerking HTTP op regel 31 is mislukt vanwege een communicatiefout tussen server [nuxt] en server PHP;
- de bewerking HTTP op regel 31 is geslaagd, maar het ontvangen resultaat meldde een fout (regels 39-42);
- regel 51: we zien dat de sessie jSON met de server PHP niet is gestart;
- regel 53: het resultaat [result] wordt geretourneerd en weergegeven op regel 7. Daarnaast worden de eigenschappen [showErrorLoading] en [errorLoadingMessage] ingesteld, die de client [nuxt] zal gebruiken om een foutmelding weer te geven wanneer hij de door de server [nuxt] verzonden pagina ontvangt (regels 72-79);
- regels 54-60: code die in alle gevallen wordt uitgevoerd (succes of mislukking);
- regel 56: de sessie [nuxt] wordt opgehaald in de context van de server [nuxt];
- regel 57: deze wordt opgeslagen;
- regels 63-68: zodra de functie [asyncData] is voltooid, voert de server [nuxt] de functies [beforeCreate] en [create] uit;
Opmerking: de uitvoering van de pagina [index] door de server [nuxt] kan bijvoorbeeld mislukken als de server voor de belastingberekening niet is gestart wanneer de applicatie [nuxt] wel wordt gestart:

In dat geval is de enige oplossing om eerst de belastingberekeningsserver te starten en vervolgens de applicatie [nuxt] zelf, aangezien het navigatiemenu geen optie biedt om een jSON-sessie met de belastingberekeningsserver te starten;
15.14. De pagina [index], uitgevoerd door de client [nuxt]
De pagina [index] wordt pas door de client [nuxt] uitgevoerd nadat de server [nuxt] deze naar hem heeft verzonden. Deze heeft de informatie [result] en eventueel [showErrorLoading] en [errorLoadingMessage] naar de client verzonden.
We weten dat de functie [asyncData] niet zal worden uitgevoerd. Dan blijven de functies van de levenscyclus over, en met name de functie [mounted]:
mounted() {
console.log('[index mounted]')
// alleen client
if (this.showErrorLoading) {
console.log('[index mounted, showErrorLoading=true]')
this.$eventBus().$emit('errorLoading', true, this.errorLoadingMessage)
}
}
- de client [nuxt] neemt automatisch de elementen [result] en eventueel [showErrorLoading, errorLoadingMessage], die de server [nuxt] hem heeft gestuurd, op in de eigenschappen van de pagina:
- de eigenschap [result] wordt weergegeven in regel 7;
- de eigenschappen [showErrorLoading, errorLoadingMessage] worden gebruikt door de methode [mounted]: in regel 4 wordt de eigenschap [showErrorLoading] getest. Als deze waar is, wordt in regel 6 de gebeurtenissenbus van de client [nuxt] gebruikt om aan te geven dat er een foutmelding moet worden weergegeven;
- de gebeurtenis [errorLoading], die in regel 6 wordt geactiveerd, wordt opgevangen door de pagina [layouts/default], zoals beschreven in de paragraaf ‘link’;
15.15. De pagina [authentification] wordt uitgevoerd door de server [nuxt]
De pagina [authentification] is verantwoordelijk voor het identificeren van een gebruiker bij de server voor belastingberekening. De code ervan is als volgt:
<!-- authenticatiepagina -->
<template>
<Layout :left="true" :right="true">
<!-- navigatie -->
<Navigation slot="left" />
<!-- bericht-->
<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',
// gebruikte componenten
components: {
Layout,
Navigation
},
// asynchrone gegevens
async asyncData(context) {
// log
console.log('[authentification asyncData started]')
if (process.client) {
// begin wachten op de client [nuxt]
context.app.$eventBus().$emit('loading', true)
// geen fout
context.app.$eventBus().$emit('errorLoading', false)
}
try {
// authenticatie bij de server
const dao = context.app.$dao()
const response = await dao.authentifierUtilisateur('admin', 'admin')
// log
console.log('[authentification asyncData response=]', response)
// resultaat
const userAuthenticated = response.état === 200
// er wordt genoteerd of de gebruiker is geauthenticeerd of niet
context.store.commit('replace', { userAuthenticated })
// de store wordt opgeslagen in de sessie [nuxt]
const session = context.app.$session()
session.save(context)
// authenticatiefout?
if (!userAuthenticated) {
// de fout zit in response.réponse
throw new Error(response.réponse)
}
// het resultaat wordt weergegeven
return { result: '[succès]' }
} catch (e) {
// de fout wordt gemeld
return { result: '[échec]', showErrorLoading: true, errorLoadingMessage: e.message }
} finally {
// logboek
console.log('[authentification asyncData finished]')
if (process.client) {
// einde wachten op de klant [nuxt]
context.app.$eventBus().$emit('loading', false)
}
}
},
// levenscyclus
beforeCreate() {
console.log('[authentification beforeCreate]')
},
created() {
console.log('[authentification created]')
},
beforeMount() {
console.log('[authentification beforeMount]')
},
mounted() {
console.log('[authentification mounted]')
// alleen klant
if (this.showErrorLoading) {
console.log('[authentification mounted, showErrorLoading=true]')
this.$eventBus().$emit('errorLoading', true, this.errorLoadingMessage)
}
}
}
</script>
- regel 7: de pagina geeft het resultaat [result] weer van de asynchrone aanvraag [asyncData] uit de regels 25-65;
- regels 28-33: de server voert deze regels, die bestemd zijn voor de client [nuxt], niet uit;
- regel 36: de laag [dao] wordt opgehaald van de server [nuxt];
- regel 37: er wordt geauthenticeerd bij de belastingberekeningsserver met de testgegevens [admin, admin], die als enige door de belastingberekeningsserver worden geaccepteerd;
- regel 41: de authenticatie is geslaagd als het antwoord de status 200 heeft;
- regel 43: de eigenschap [userAuthenticated] wordt in de store opgeslagen;
- regels 44-46: de store wordt opgeslagen in de sessie [nuxt];
- regels 48-51: als de authenticatie is mislukt, wordt er een uitzondering gegenereerd met de foutmelding die de belastingberekeningsserver heeft verzonden;
- anders, regel 53, wordt een succesresultaat geretourneerd dat op regel 7 wordt weergegeven;
- regels 54-57: in geval van een fout worden drie eigenschappen van de pagina [result, showErrorLoading, errorLoadingMessage] ingesteld. De eigenschap [result] wordt weergegeven in regel 7. De drie eigenschappen worden naar de client [nuxt] verzonden;
- regels 60-63: worden niet uitgevoerd door de server [nuxt];
- zodra [asyncData] het resultaat heeft gerenderd, wordt dit weergegeven op regel 7. Vervolgens worden de methoden [beforeCreate] (regels 67-69) en [created] (regels 70-72) uitgevoerd;
- dat is alles;
Opmerking: de uitvoering van de pagina [authentification] door de server [nuxt] kan bijvoorbeeld mislukken als de sessie jSON met de belastingberekeningsserver niet is geïnitialiseerd. Dit kunt u als volgt oplossen:
- verwijder de sessiecookie PHP uit uw browser (om helemaal opnieuw te beginnen):

- start de applicatie [nuxt] terwijl de berekeningsserver niet is gestart: u krijgt een foutmelding;
- start de belastingberekeningsserver;
- vraag de URL [/authentification] rechtstreeks op in de adresbalk van de browser:

In dit geval is de enige oplossing opnieuw de pagina [index] te verversen.
15.16. De pagina [authentification], uitgevoerd door de client [nuxt]
Laten we de code van de pagina nog eens bekijken:
<!-- authenticatiepagina -->
<template>
<Layout :left="true" :right="true">
<!-- navigatie -->
<Navigation slot="left" />
<!-- bericht-->
<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',
// gebruikte componenten
components: {
Layout,
Navigation
},
// asynchrone gegevens
async asyncData(context) {
// log
console.log('[authentification asyncData started]')
if (process.client) {
// begin wachten op de client [nuxt]
context.app.$eventBus().$emit('loading', true)
// geen fout
context.app.$eventBus().$emit('errorLoading', false)
}
try {
// authenticatie bij de server
const dao = context.app.$dao()
const response = await dao.authentifierUtilisateur('admin', 'admin')
// log
console.log('[authentification asyncData response=]', response)
// resultaat
const userAuthenticated = response.état === 200
// er wordt genoteerd of de gebruiker is geauthenticeerd of niet
context.store.commit('replace', { userAuthenticated })
// de store wordt opgeslagen in de sessie [nuxt]
const session = context.app.$session()
session.save(context)
// authenticatiefout?
if (!userAuthenticated) {
// de fout bevindt zich in response.réponse
throw new Error(response.réponse)
}
// het resultaat wordt weergegeven
return { result: '[succès]' }
} catch (e) {
// de fout wordt gemeld
return { result: '[échec]', showErrorLoading: true, errorLoadingMessage: e.message }
} finally {
// log
console.log('[authentification asyncData finished]')
if (process.client) {
// einde wachten op de klant [nuxt]
context.app.$eventBus().$emit('loading', false)
}
}
},
// levenscyclus
beforeCreate() {
console.log('[authentification beforeCreate]')
},
created() {
console.log('[authentification created]')
},
beforeMount() {
console.log('[authentification beforeMount]')
},
mounted() {
console.log('[authentification mounted]')
// alleen klant
if (this.showErrorLoading) {
console.log('[authentification mounted, showErrorLoading=true]')
this.$eventBus().$emit('errorLoading', true, this.errorLoadingMessage)
}
}
}
</script>
Er zijn twee gevallen waarin de pagina [authentification] door de client [nuxt] wordt uitgevoerd:
- de client [nuxt] wordt uitgevoerd nadat de server [nuxt] de pagina [authentification] naar de browser van de client [nuxt] heeft verzonden;
- de client [nuxt] omdat de gebruiker op de link [Authentification] in het navigatiemenu heeft geklikt:

Laten we eerst het eerste geval bekijken. In dit geval voert de client [nuxt] de functie [asyncData] niet uit. Hij neemt in de eigenschappen van de pagina de elementen [result] en eventueel [showErrorLoading, errorLoadingMessage] op die de server [nuxt] hem heeft gestuurd:
- de eigenschap [result] wordt weergegeven in regel 7;
- de eigenschappen [showErrorLoading, errorLoadingMessage] worden gebruikt door de methode [mounted]: in regel 79 wordt de eigenschap [showErrorLoading] getest. Als deze waar is, wordt in regel 81 de gebeurtenissenbus van de client [nuxt] gebruikt om aan te geven dat er een foutmelding moet worden weergegeven;
Het mechanisme voor het weergeven van de foutmelding is voor de pagina [index] uitgelegd in de paragraaf ‘link’.
Geval 2 betreft de client [nuxt] die wordt uitgevoerd wanneer de gebruiker op de link [Authentification] klikt. In dit geval wordt de client [nuxt] zelfstandig uitgevoerd en niet na de server [nuxt]. De functie [asyncData] wordt dan uitgevoerd. We geven alleen de details weer die afwijken van de uitleg die is gegeven voor de pagina die wordt uitgevoerd door de server [nuxt]:
- regels 28-33: de client [nuxt] vraagt om het weergeven van het wachtbericht en het verwijderen van een eventueel foutbericht dat eerder zou zijn weergegeven;
- regel 36: hier wordt nu de laag [dao] van de client [nuxt] verkregen;
- regels 60-63: de client [nuxt] vraagt om het wachtenbericht niet langer weer te geven;
- zodra [asyncData] is voltooid, zal de levenscyclus van de pagina plaatsvinden. De functie [mounted] in de regels 76-83 zal worden uitgevoerd. Als er een fout is opgetreden, wordt het foutbericht weergegeven;
Opmerking: om een fout te veroorzaken, volgt u de procedure die aan het einde van de paragraaf ‘link’ wordt uitgelegd voor de server [nuxt], maar in plaats van de pagina [authentification] op te roepen door URL in de adresbalk in te voeren, gebruikt u de link [Authentification] in het navigatiemenu. Dan wordt de client [nuxt] gestart.
15.17. De pagina [get-admindata]
De code van de pagina [get-admindata] is als volgt:
<!-- weergave get-admindata -->
<template>
<Layout :left="true" :right="true">
<!-- navigatie -->
<Navigation slot="left" />
<!-- bericht -->
<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',
// gebruikte componenten
components: {
Layout,
Navigation
},
// asynchrone gegevens
async asyncData(context) {
// log
console.log('[get-admindata asyncData started]')
if (process.client) {
// begin wachttijd
context.app.$eventBus().$emit('loading', true)
// geen fout
context.app.$eventBus().$emit('errorLoading', false)
}
try {
// gegevens worden opgevraagd [admindata]
const response = await context.app.$dao().getAdminData()
// log
console.log('[get-admindata asyncData response=]', response)
// resultaat
const adminData = response.état === 1000 ? response.réponse : ''
// de gegevens worden in de store geplaatst
context.store.commit('replace', { adminData })
// de store wordt opgeslagen in de sessie [nuxt]
const session = context.app.$session()
session.save(context)
// is er een fout opgetreden?
if (!adminData) {
// de fout bevindt zich in response.réponse
throw new Error(response.réponse)
}
// de ontvangen waarde wordt teruggegeven
return { result: adminData }
} catch (e) {
// de fout wordt gemeld
return { result: '[échec]', showErrorLoading: true, errorLoadingMessage: e.message }
} finally {
// log
console.log('[get-admindata asyncData finished]')
if (process.client) {
// einde wachttijd
context.app.$eventBus().$emit('loading', false)
}
}
},
// levenscyclus
beforeCreate() {
console.log('[get-admindata beforeCreate]')
},
created() {
console.log('[get-admindata created]')
},
beforeMount() {
console.log('[get-admindata beforeMount]')
},
mounted() {
console.log('[get-admindata mounted]')
// klant
if (this.showErrorLoading) {
console.log('[get-admindata mounted, showErrorLoading=true]')
this.$eventBus().$emit('errorLoading', true, this.errorLoadingMessage)
}
}
}
</script>
Deze pagina lijkt sterk op de pagina [authentification]. De uitleg is vergelijkbaar, zowel voor de uitvoering door de server [nuxt] als voor de uitvoering door de client [nuxt]. Merk echter op dat regel 7 niet, zoals eerder, ‘succes’ of ‘mislukt’ weergeeft, maar de waarde van de gegevens die zijn ontvangen van de belastingberekeningsserver (regel 52):

Het bovenstaande resultaat wordt zowel met de server als met de client [nuxt] verkregen. Om een fout te veroorzaken, roept u de pagina [get-admindata] op via de server of de client [nuxt], zonder te zijn geauthenticeerd:

15.18. De pagina [fin-session]
De code van de pagina is als volgt:
<!-- hoofdpagina -->
<template>
<Layout :left="true" :right="true">
<!-- navigatie -->
<Navigation slot="left" />
<!-- bericht-->
<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',
// gebruikte componenten
components: {
Layout,
Navigation
},
// asynchrone gegevens
async asyncData(context) {
// log
console.log('[fin-session asyncData started]')
// klantgeval [nuxt]
if (process.client) {
// begin wachtrij
context.app.$eventBus().$emit('loading', true)
// geen fout
context.app.$eventBus().$emit('errorLoading', false)
}
try {
// er wordt een nieuwe sessie PHP aangevraagd bij de belastingberekeningsserver
const dao = context.app.$dao()
const response = await dao.finSession()
// log
console.log('[fin-session asyncData response=]', response)
// is er een fout opgetreden?
if (response.état !== 400) {
// de fout zit in response.réponse
throw new Error(response.réponse)
}
// de server heeft een nieuwe sessiecookie verzonden: PHP
// dit wordt zowel door de server als door de Nuxt-client opgehaald
// als deze code wordt uitgevoerd door de client [nuxt], moet de sessiecookie PHP in de Nuxt-sessie worden geplaatst
// zodat de plug-in [plgDao] van de server [nuxt] deze kan ophalen en de laag [dao] kan initialiseren met
//. Als deze code wordt uitgevoerd door de server [nuxt], moet de sessiecookie PHP in de Nuxt-sessie worden geplaatst
// zodat de routing van de client [nuxt] deze ophaalt en doorgeeft aan de browser
const phpSessionCookie = dao.getPhpSessionCookie()
// wordt in de store genoteerd dat de sessie jSON is gestart en wordt het sessiecookie PHP opgeslagen
context.store.commit('replace', { jsonSessionStarted: true, phpSessionCookie, userAuthenticated: false, adminData: '' })
// de store wordt opgeslagen in de sessie [nuxt]
const session = context.app.$session()
session.save(context)
// het resultaat wordt weergegeven
return { result: "[succès]. La session jSON reste initialisée mais vous n'êtes plus authentifié(e)." }
} catch (e) {
// log
console.log('[fin-session asyncData error=]', e)
// de fout wordt gemeld
return { result: '[échec]', showErrorLoading: true, errorLoadingMessage: e.message }
} finally {
// log
console.log('[fin-session asyncData finished]')
if (process.client) {
// einde wachttijd
context.app.$eventBus().$emit('loading', false)
}
}
},
// levenscyclus
beforeCreate() {
console.log('[fin-session beforeCreate]')
},
created() {
console.log('[fin-session created]')
},
beforeMount() {
console.log('[fin-session beforeMount]')
},
mounted() {
console.log('[fin-session mounted]')
// alleen klant
if (this.showErrorLoading) {
console.log('[fin-session mounted, showErrorLoading=true]')
this.$eventBus().$emit('errorLoading', true, this.errorLoadingMessage)
}
}
}
</script>
De code lijkt sterk op die van de voorgaande pagina’s en de uitleg is hetzelfde. Er is echter één punt dat extra aandacht verdient: door de asynchrone bewerking in regel 38 zal de server voor belastingberekening een nieuwe sessiecookie PHP verzenden. De uitleg over het beheer van deze cookie verschilt naargelang de code wordt uitgevoerd door de server of door de client [nuxt].
Laten we beginnen met de server [nuxt]:
- regel 37: hier wordt de laag [dao] van de server [nuxt] geïnstantieerd. Laten we de code van de constructor nog eens bekijken:
// constructor
constructor(axios, phpSessionCookie) {
// axios-bibliotheek
this.axios = axios
// waarde van de sessiecookie
this.phpSessionCookie = phpSessionCookie
// naam van de sessiecookie van de server PHP
this.phpSessionCookieName = 'PHPSESSID'
}
Op regel 1 zien we dat de constructor de huidige sessiecookie PHP nodig heeft, de laatst ontvangen cookie, of deze nu afkomstig is van de server of van de client [nuxt];
- regel 52: de server [nuxt] haalt het cookie van de nieuwe sessie PHP op, of het oude cookie als het beëindigen van de sessie is mislukt;
- regel 54: de sessiecookie PHP wordt in de store geplaatst en vervolgens opgeslagen in de sessie [nuxt] op de regels 56-57;
- na de server is het de client [nuxt] die de pagina [fin-session] uitvoert met de door de server verzonden gegevens. We weten dat hij de functie [asyncData] niet zal uitvoeren;
- uiteindelijk, nadat de server en de client [nuxt] hun werk hebben voltooid, weten we dat het cookie PHP, dat nodig is voor de communicatie met de server voor de belastingberekening, zich in de sessie [nuxt] bevindt;
Het feit dat het cookie PHP zich in de sessie [nuxt] bevindt, is voldoende voor de server, omdat de laag [dao] het daar vandaan zal halen. In de plug-in [server/plgDao], die de laag [dao] van de server initialiseert, staat het volgende geschreven:
/* eslint-disable no-console */
// er wordt een toegangspunt tot de laag aangemaakt [Dao]
import Dao from '@/api/server/Dao'
export default (context, inject) => {
// axios-configuratie
context.$axios.defaults.timeout = context.env.timeout
context.$axios.defaults.baseURL = context.env.baseURL
// we halen de sessiecookie op
const store = context.app.$session().value.store
const phpSessionCookie = store ? store.phpSessionCookie : ''
console.log('session=', context.app.$session().value, 'phpSessionCookie=', phpSessionCookie)
// instantiëren van de laag [dao]
const dao = new Dao(context.$axios, phpSessionCookie)
// injectie van een functie [$dao] in de context
inject('dao', () => dao)
// log
console.log('[fonction server $dao créée]')
}
- regel 13 wordt de laag [dao] van de server [nuxt] geïnstantieerd met de sessiecookie PHP, afkomstig uit de sessie [nuxt], regels 9-10;
Voor de client [nuxt] ligt het anders. Het is namelijk niet de client zelf die het cookie verstuurt, maar de browser die het uitvoert. Deze browser kent echter het cookie van de nieuwe sessie PHP niet, dat door de server [nuxt] is ontvangen. Als we de links van het navigatiemenu [3] gebruiken:

Dan ontvangt de server voor de belastingberekening van de browser een verouderde sessiecookie PHP en zal hij antwoorden dat er aan deze cookie geen sessie jSON is gekoppeld. We moeten een manier vinden om de nieuwe sessiecookie PHP aan de browser door te geven.
Hiervoor kunnen we routing-middleware gebruiken:

Het script [client/routing] is de routerings-middleware die is gedefinieerd in het bestand [nuxt.config]:
// router
router: {
// hoofdmap van de applicatie URL
base: '/nuxt-12/',
// routeringsmiddleware
middleware: ['routing']
},
Het script [middleware/routing] is als volgt:
/* eslint-disable no-console */
// we importeren de client-middleware
import clientRouting from './client/routing'
export default function(context) {
// wie voert deze code uit?
console.log('[middleware], process.server', process.server, ', process.client=', process.client)
if (process.client) {
// client-routing
clientRouting(context)
}
}
- regels 9-12: er wordt alleen de client gerouteerd met een geïmporteerde functie in regel 4;
Het script [middleware/client/routing] is als volgt:
/* eslint-disable no-console */
export default function(context) {
// wie voert deze code uit?
console.log('[middleware client], process.server', process.server, ', process.client=', process.client)
// beheer van de sessiecookie PHP in de browser
// de sessiecookie PHP van de browser moet identiek zijn aan die in de Nuxt-sessie
// de actie [fin-session] ontvangt een nieuwe cookie PHP (zowel de server als de Nuxt-client)
// als de server het ontvangt, moet de client het doorgeven aan de browser
// voor zijn eigen communicatie met de server PHP
// hier gaat het om client-routing
// we halen de sessiecookie op PHP
const phpSessionCookie = context.store.state.phpSessionCookie
if (phpSessionCookie) {
// indien aanwezig, wordt de sessiecookie PHP aan de browser toegewezen
document.cookie = phpSessionCookie
}
}
Laten we terugkeren naar de situatie direct na de uitvoering van de pagina [fin-session] door de server [nuxt]:

Als we op een van de links in het menu [3] klikken, neemt de client [nuxt] het over. Aangezien er een paginawisseling plaatsvindt, wordt het routingscript van de client uitgevoerd:
- regel 13: de sessiecookie PHP wordt gevonden in de opslag van de applicatie [nuxt];
- regel 14: als deze niet leeg is, wordt deze naar de browser verzonden (regel 16). Vanaf dat moment beschikt de browser van de client [nuxt] over de juiste sessiecookie PHP;
Het script [client/routing] wordt uitgevoerd bij elke paginawisseling van de client [nuxt]. De scriptcode is geldig ongeacht de doelpagina: meestal geeft het de browser gewoon een sessiecookie PHP die deze al heeft, behalve in twee gevallen:
- direct na het opstarten van de applicatie, voert de server [nuxt] de pagina [index] uit en ontvangt een eerste sessiecookie PHP die de browser van de client [nuxt] niet heeft;
- wanneer de server [nuxt] de pagina [fin-session] uitvoert zoals zojuist uitgelegd;
Laten we nu eens kijken naar het geval waarin de pagina [fin-session] uitsluitend door de client [nuxt] wordt uitgevoerd, omdat er op de link in het navigatiemenu is geklikt. Het is nu de client [nuxt] die de functie [asyncData] uitvoert:
try {
// we vragen een nieuwe sessie PHP aan bij de server voor belastingberekening
const dao = context.app.$dao()
const response = await dao.finSession()
// log
console.log('[fin-session asyncData response=]', response)
// is er een fout opgetreden?
if (response.état !== 400) {
// de fout zit in response.réponse
throw new Error(response.réponse)
}
// de server heeft een nieuwe sessiecookie verzonden: PHP
// dit wordt zowel door de server als door de Nuxt-client opgehaald
// als deze code wordt uitgevoerd door de client [nuxt], moet de sessiecookie PHP in de Nuxt-sessie worden geplaatst
// zodat de plug-in [plgDao] van de server [nuxt] deze kan ophalen en de laag [dao] kan initialiseren met
//. Als deze code wordt uitgevoerd door de server [nuxt], moet de sessiecookie PHP in de Nuxt-sessie worden geplaatst
// zodat de routing van de client [nuxt] deze ophaalt en doorgeeft aan de browser
const phpSessionCookie = dao.getPhpSessionCookie()
// wordt in de store genoteerd dat de sessie jSON is gestart en wordt het sessiecookie PHP opgeslagen
context.store.commit('replace', { jsonSessionStarted: true, phpSessionCookie, userAuthenticated: false, adminData: '' })
// de store wordt opgeslagen in de sessie [nuxt]
const session = context.app.$session()
session.save(context)
// het resultaat wordt weergegeven
return { result: "[succès]. La session jSON reste initialisée mais vous n'êtes plus authentifié(e)." }
} catch (e) {
// log
console.log('[fin-session asyncData error=]', e)
// er wordt een foutmelding gegeven
return { result: '[échec]', showErrorLoading: true, errorLoadingMessage: e.message }
} finally {
// log
console.log('[fin-session asyncData finished]')
if (process.client) {
// einde wachttijd
context.app.$eventBus().$emit('loading', false)
}
}
- regel 3: hier wordt de laag [dao] van de client [nuxt] verkregen;
- regel 18: de sessiecookie PHP, opgehaald door de laag [dao] van de client [nuxt], wordt opgeslagen in de store (regel 20) en vervolgens opgeslagen in de sessie [nuxt] (regels 22-23);
- vanaf dat moment verloopt alles goed, omdat we weten dat de laag [dao] van de server [nuxt] het sessiecookie PHP uit de sessie [nuxt] ophaalt;
15.19. Exécution
Om dit voorbeeld uit te voeren, moet je ervoor zorgen dat je vóór de uitvoering de sessiecookie [nuxt] en de cookie PHP verwijdert uit de browser waarin de client [nuxt] wordt uitgevoerd, zodat je vanuit een schone situatie begint. Hieronder volgt een voorbeeld met de Chrome-browser:

15.20. Conclusion
Dit voorbeeld was bijzonder complex. Het bracht kennis samen die in de voorgaande voorbeelden was opgedaan: het behoud van de store in een sessie [nuxt], plug-ins voor het injecteren van functies, routing-middleware en foutbeheer bij asynchrone bewerkingen. De complexiteit werd nog vergroot doordat we wilden dat de gebruiker zowel de links in het navigatiemenu kon gebruiken als URL handmatig kon invoeren, zonder dat de applicatie daardoor zou crashen. Daarvoor moesten we onderzoeken hoe elke pagina zich gedroeg, afhankelijk van of deze door de client of door de server [nuxt] werd uitgevoerd.
Deze eenheid in het gedrag van de client en de server [nuxt] is niet onmisbaar. We kunnen ons het veelvoorkomende geval voorstellen waarin:
- de eerste pagina wordt geleverd door de server [nuxt];
- alle volgende pagina’s worden geleverd door de client [nuxt], die dan in de modus [SPA] werkt;
Maar zelfs in dit geval moet worden gecontroleerd wat het resultaat is wanneer alle pagina’s door de server [nuxt] worden uitgevoerd, want dat is wat de zoekmachines zullen krijgen wanneer ze deze opvragen.