Použití Axios HTTP klienta

31.10.2020
Web API je všude kolem nás, je to způsob jak propojit systémy mezi sebou. Článek popisuje jak s webovým API komunikovat pomocí javascriptové knihovny Axios. Tu můžeme využít pro techniku AJAX, kdy javascriptový kód, který běží v prohlížeči uživatele, na pozadí stránky komunikuje s backend částí aplikace. Axios budeme volat v Jest testech, které nám zároveň ověří správnou funkčnost.

Slovníček

ASP.NET Core Open-source webový framework od Microsoftu (první release 2016).
Axios Javascriptový HTTP/S client.
Jest Javascriptový testovací framework, spravovaný Facebookem.
AJAX Způsob jakým JavaScript může z prohlížeče komunikovat s webovým serverem.
Node Javascriptový runtime.
Npm Balíčkovací manažer pro node.
Babel Javascriptový kompilátor (transpilátor).

Obsah

Základní použití

Pro poslání GET požadavku
axios.get(url, config)
POST požadavku
axios.post(url, data, config)
zpracování odpovědi
.then(function (response) { console.log(response) })
error handling
.catch(function (error) {
  if (error.response) {
    // Request made and server responded
    console.log(error.response);
  } else if (error.request) {
    // The request was made but no response was received
    console.log(error.request);
  } else {
    // Something happened in setting up the request that triggered an Error
    console.log(error.message);
  }

Příprava backendu

Backend je velmi jednoduchý Controller v ASP.NET Core MVC aplikaci. Obsahuje dvě akce pro zpracování GET požadavku a dvě akce pro zpracování POST požadavku. Jedna akce je vždy bez úprav a druhá s použitím routy.
using Microsoft.AspNetCore.Mvc;

namespace WebApi.Controllers
{
    public class ApiController : Controller
    {
        [HttpGet]
        public IActionResult GetCommand(int? id)
        {
            if (id == null) return BadRequest();

            return Ok();
        }

        [HttpGet]
        [Route("api/getCommand/{id?}")]
        public IActionResult GetCommand2(int? id)
        {
            if (id == null) return BadRequest();

            return Ok();
        }

        [HttpPost]
        public IActionResult PostCommand(int? id)
        {
            if (id == null) return BadRequest();

            return Ok();
        }

        [HttpPost]
        [Route("api/postCommand/{id?}")]
        public IActionResult PostCommand2(int? id)
        {
            if (id == null) return BadRequest();

            return Ok();
        }
    }
}

Otestování pomocí frameworku Jest

Instalace

Pro instalaci použijeme baličkovací nástroj npm. V rootu našeho projektu vytvoříme konfigurační soubor package.json. Ten můžeme vytvořit buď
  • ručně
  • pomocí příkazu npm init
  • nebo přidat pomocí Visual Studia (Solution Explorer: Project Name > Add > New Item... > npm Configuration File)
V každém případě musí soubor obsahovat minimálně pole name a version. V příkazové řádce se přepneme do rootu našeho projektu a nainstalujeme framework. Příznak --save-dev říká, že nám Jest stačí ve vývojovém prostředí.
npm install --save-dev jest
Balíček a jeho závislosti se stáhli do složky node_modules, která se, pokud neexistuje, nově vytvoří. konfigurační soubor nyní může vypadat následovně
{
  "version": "1.0.0",
  "name": "asp.net",
  "private": true,
  "devDependencies": {
    "jest": "^26.6.1"
  }
}
dáme ještě konfiguračnímu souboru vědět, který framework pro testování použít
"scripts": {
  "test": "jest"
}
Protože budeme chtít v testovácím scriptu použít knihovnu axios, musíme jí také nainstalovat pomocí npm, abychom jí mohli naimportovat jako modul.
npm install --save-dev axios
Zároveň Jest používá pro transpilaci node balíčků transpilátor babel, který také nainstalujeme a nakonfigurujeme.
npm install --save-dev babel-core
npm install --save-dev babel-preset-env
babel.config.js
module.exports = {
  presets: [['babel-preset-env', { targets: { node: 'current' } }]],
};
Dále budeme také potřebovat balíčky https a qs
npm install --save-dev https
npm install --save-dev qs

Příprava GET testů

get.test.js
/**
* @jest-environment node
*/

import axios from 'axios';
import https from 'https';

const url = 'localhost:44370'
const agent = new https.Agent({ rejectUnauthorized: false });

test('GET request, ID in query parameter.', () => {

  expect.assertions(1);

  return axios.get(`https://${url}/api/getCommand?id=1`, { httpsAgent: agent })
      .then(function (response) {
          expect(response.status).toBe(200);
      })
});

test('GET request, ID in params property.', () => {

  expect.assertions(1);

  return axios.get(`https://${url}/api/getCommand`, { httpsAgent: agent, params: { id: 1 } })
      .then(function (response) {
          expect(response.status).toBe(200);
      })
});

test('GET request, ID as part of URL route.', () => {

  expect.assertions(1);

  return axios.get(`https://${url}/api/getCommand/1`, { httpsAgent: agent })
      .then(function (response) {
          expect(response.status).toBe(200);
      })
});
  • @jest-environment node dáváme Jestu vědět, že se má spouštět pod node prostředím, jinak se použije javascriptový emulátor prohlížeče Jsdom, který by nám začal vracet chybové hlášky týkající se CORS pravidel.
  • nastavením https.Agent({ rejectUnauthorized: false }) říkáme, aby axios neověřoval self-signed certifikát u certifikačních autorit.

Příprava POST testů

post.test.js
/**
* @jest-environment node
*/

import axios from 'axios';
import https from 'https';
import qs from 'qs';

const url = 'localhost:44370'

test('POST request, ID in query parameter.', () => {

  expect.assertions(1);

  https.globalAgent.options.rejectUnauthorized = false;

  return axios.post(`https://${url}/api/postCommand?id=1`)
      .then(function (response) {
          expect(response.status).toBe(200);
      })
});

test('POST request, ID is in data object.', () => {

  expect.assertions(1);

  https.globalAgent.options.rejectUnauthorized = false;

  const data = { id: 1 }

  return axios.post(`https://${url}/api/postCommand`, qs.stringify(data))
      .then(function (response) {
          expect(response.status).toBe(200);
      })
});

test('POST request, ID as part of URL route.', () => {

  expect.assertions(1);

  https.globalAgent.options.rejectUnauthorized = false;

  return axios.post(`https://${url}/api/postCommand/1`)
      .then(function (response) {
          expect(response.status).toBe(200);
      })
});'
  • https.globalAgent.options.rejectUnauthorized = false; dělá to samé co https.Agent({ rejectUnauthorized: false }) ale funguje i pro POST požadavek. Agent třída mi pro POST požadavek nefungovala.
  • qs.stringify převede parametry na JSON objekt.

Spuštění

npm test -- --verbose

Odkazy