Alkalmazások fejlesztése

12. előadás

Horváth Győző
Egyetemi adjunktus
1117 Budapest, Pázmány Péter sétány 1/c., 2.420-as szoba
Tel: (1) 372-2500/1816
horvath.gyozo@inf.elte.hu

Eddig

  • Ember.js
  • Router, Route, Controller, Component
  • Adatok lefele
  • Ember-data
  • Action-ök felfele

Tartalomjegyzék

  • REST API
  • JSON API
  • Fortune.js
  • Ember-data REST adapter

REST API

REST API

Representational State Transfer (REST) Application Programming Interface (API)

  • Adathozzáférés HTTP protokollon keresztül
  • CRUD műveletek adatforráson modelleken
  • HTTP metódusok segítségével (GET, POST, DELETE, PUT/PATCH)
  • (Általában) JSON formátumú kérések/válaszok

REST API példa

  • GET /people: Összes adat lekérdezése a people modellből
  • GET /people/john: A john azonosítójú elem lekérdezése a people modellből
  • POST /people: Új elem felvétele a people modellbe (adatok a request bodyban)
  • DELETE /people/john: A john azonosítójú elem törlése a people modellből
  • PUT /people/john: A john azonosítójú elem frissítése a people modellből

JSON API

A specification for building APIs in JSON

http://jsonapi.org/

  • JSON formátumot használó REST API specifikáció
  • Az ember-data alapértelmezetten ezt a formátumot kezeli
  • mime-type: application/vnd.api+json
  • Kötelező (MUST) és ajánlott (RECOMMENDED) szabályok
  • Részletes specifikáció: http://jsonapi.org/format/
  • Query-k, kapcsolatok kezelése
  • Szabványos válaszok, hibaüzenetek

JSON API Példa

Kérés

GET /articles?include=author

Válasz

HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
    "data": [{
        "type": "articles",
        "id": "1",
        "attributes": {
            "title": "JSON API paints my bikeshed!",
            "body": "The shortest article. Ever.",
            "created": "2015-05-22T14:56:29.000Z",
            "updated": "2015-05-22T14:56:28.000Z"
        },
        "relationships": {
            "author": { "data": {"id": "42", "type": "people"}  }
        }
    }],
    "included": [ {
        "type": "people",
        "id": "42",
        "attributes": {
            "name": "John",
            "age": 80,
            "gender": "male"
        }
    } ]
}

JSON API Példa 2.

Kérés

POST /photos HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
{
    "data": {
        "type": "photos",
        "attributes": {
            "title": "Ember Hamster",
            "src": "http://example.com/images/productivity.png"
        },
        "relationships": {
            "photographer": {
                "data": { "type": "people", "id": "9" }
            }
        }
    }
}

Feladat

Alakítsunk ki JSON API formátumot használó REST API szervert az alkalmazásunknak!

Lépések

  • Express szerver
  • REST végpontok
  • Adatmodell szerveroldalon
  • Perzisztálás
  • JSON API formátum

1. lépés

Hozzunk létre szerver oldalon egy új Express alkalmazást

npm install express --save

server.js

var express = require('express');

var server = express();

var port = process.env.PORT || 8080;
server.listen(port, function () {
    console.log('JSON Api server started on port ' + port);
});

2. lépés

Alakítsunk ki REST API végpontokat: Fortune.js

npm install fortune --save

server.js

var fortune = require('fortune');

// Új tároló (alapértelmezetten memóriában tárol)
var store = fortune();

// Express middleware
server.use(fortune.net.http(store));

// Csak akkor fusson a szerver, ha sikerült csatlakozni a tárolóhoz
// Hasonlóan a Waterline-hoz    
store.connect().then(function () {
    server.listen(port, function () {
        console.log('JSON Api server started on port ' + port);
    });
});

3. lépés

Hozzuk létre a szerveroldalon a kliensoldalinak megfelelő adatmodellt!

http://fortunejs.com/api/#fortune-definetype

server.js

store.defineType('<adatmodell neve>', {
    <mező neve>: {type: <mező típusa>},
    field1: {type: String},
    field2: {type: Number, min: 0, max: 100},
    field3: {type: Boolean},
    field4: {type: Date},
    ...
    <kapcsolat neve>: { 
        link: '<kapcsolt modell neve>',
        inverse: '<visszafele kapcsolat neve>',
        isArray: true
    },
    ...
});

4. lépés

Használjunk fájl alapú adatbázist (NeDB) az adatok perzisztálására!

npm install fortune-nedb --save

server.js

var nedbAdapter = require('fortune-nedb');

var store = fortune({
    adapter: {
        type: nedbAdapter,
        options: { dbPath: __dirname + '/.db' }
    }
}); 

Tesztelés

Teszteljük a kialakított API-t!

A végponttesztelővek egyes végpontokra küldhetünk különböző metódusokkal kéréseket.

Teszt

  • hozzunk létre POST metódussal új elemet az adatbázisban
  • kérdezzük le GET metódussal az összes elemet egy modellben
  • kérdezzünk le egy konkrét elemet GET metódussal
  • módosítsunk/töröljünk a PUT és DELETE metódusokkal

5. lépés

Használjunk JSON API formátumot a REST API-nkban!

npm install fortune-json-api --save

server.js

var jsonapi = require('fortune-json-api');

// Beállítjuk a JSON API serializer-t
var store  = fortune({
    adapter: {
        type: nedbAdapter,
        options: { dbPath: __dirname + '/.db' }
    },
    serializers: [{ type: jsonapi }]    
});
// Minden URL-ről engedélyezzük a hozzáférést az API-hoz
// Mindenképp a `server.use(fortune.net.http(store));` sor elé kerüljön
server.use(function (req, res, next) {
    res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PATCH, DELETE');
    res.setHeader('Access-Control-Allow-Origin', '*');
    next();
});

Feladat

Alakítsuk át a kliens oldali alkalmazásunkat úgy, hogy az új API-t használja adatforrásként!

Adatmodell

A szerver oldalon alakítsuk ki úgy az adatmodellt, hogy megegyezzen a kliensoldalival!

Adapter

application.js / adapter.js

FixtureAdapter => JSONAPIAdapter

export default DS.JSONAPIAdapter.extend({
    host: 'http://<JSON API URL>.c9users.io',
    namespace: ''
});

Ember.js konfiguráció

Az Ember.js számára engedélyezni kell a külső URL-ről történő adatlekérést.

config/environment.js

ENV.contentSecurityPolicy = {
    'default-src': "'none'",
    'script-src': "'self'",
    'font-src': "'self' 'unsafe-eval' https://fonts.gstatic.com",
    'connect-src': "'self' 'unsafe-eval' http://<REST API URL>.c9users.io",
    'img-src': "'self'",
    'style-src': "'self' 'unsafe-eval' https://fonts.googleapis.com",
    'media-src': "'self'"
};

Adatok felvitele kézzel JSON API-n keresztül

Küldjünk POST kérést a megfelelő végpontra:

Kérés fejléce

Content-type: application/vnd.api+json

Kérés törzse

{
    "data": {
        "type": "<modell neve>",
        "attributes": {
            "<mezőnév>": "<érték>",
            ...
        }
    }
}

Példa

POST /photos HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
{
    "data": {
        "type": "photos",
        "attributes": {
            "title": "Ember Hamster",
            "src": "http://example.com/images/productivity.png"
        },
        "relationships": {
            "photographer": {
                "data": { "type": "people", "id": "9" }
            }
        }
    }
}

Ember.js használat

Csak az adaptert kell módosítani, minden egyéb kód változatlan