Výukový program: jak napsat CRUD API s Vapor 2

Na konci tohoto tutoriálu budete mít API s Create, Read, Update and Delete (CRUD) na Uživateli mluvícím JSON!

Výsledek tohoto tutoriálu najdete na githubu: zde.

1. Vytvoření nového projektu Vapor

Poznámka: Chcete-li provést tento tutoriál, musíte mít nainstalovanou aplikaci Swift 3, vapor-toolbox a postgresql.

Klonujeme api-šablonu, kterou poskytuje pára:

parní nový zkušební příklad

Jděte do adresáře, vytvořte nový projekt Xcode a otevřete jej:

ukázka CD /
páry xcode -y

Měli byste mít strukturu projektu takto:

testovací příklad /
├── Package.swift
├── Zdroje /
│ ├── Aplikace /
├── │ ├── Config + Setup.swift
│ │ ├── Droplet + Setup.swift
Utes │ ├── Routes.swift
│ │ ├── Ovladače /
└── │ │ └── PostController.swift
│ │ └── Modely /
└── │ └── Post.swift
│ └── Run /
├── Testy /
├── Config /
├── Veřejné /
├── Závislosti /
└── Produkty /

2. Odstraňte (přesuňte do koše) soubory a kód

Rád začínám od nuly, takže přesně víme, které soubory a implementace jsou pro co potřeba

testovací příklad /
├── Package.swift
├── Zdroje /
│ ├── Aplikace /
├── │ ├── Config + Setup.swift
│ │ ├── Droplet + Setup.swift
Utes │ ├── Routes.swift
│ │ ├── Controllers / <- DELETE
└── │ │ └── PostController.swift <- DELETE
│ │ └── Modely /
│ │ └── Post.swift <- DELETE
│ └── Run /
├── Testy /
├── Config /
├── Veřejné /
├── Závislosti /
└── Produkty /

Inside Sources / App / Config + Setup.swift odstraňte následující řádek:

importovat FluentProvider
přípona Config {
  public func setup () vyvolá {
    // povolit fuzzy konverze pro tyto typy
    // (sem přidejte své vlastní typy)
    Node.fuzzy = [Row.self, JSON.self, Node.self]
    zkuste setupProviders ()
    zkuste setupPreparations ()
  }
  /// Konfigurovat poskytovatele
  private func setupProviders () vyvolá {
    zkuste addProvider (FluentProvider.Provider.self)
  }
  /// Přidejte všechny modely, které by měly mít své
  /// schémata připravená před spuštěním aplikace
  private func setupPreparations () vyvolá {
    Prepar.append (Post.self) <- DELETE
  }
}

Inside Sources / App / Routes.swift odstraní vše, takže to vypadá takto:

import Vapor
rozšíření Droplet {
  func setupRoutes () vyvolá {
  }
}

3. Přidejte závislosti

V Package.swift přidejte následující závislost (postgresql):

importovat PackageDescription
let package = Package (
  name: "test-example",
  cíle: [
    Cíl (název: „Aplikace“),
    Cíl (název: „Spustit“, závislosti: [„Aplikace“]),
  ],
  závislosti: [
    .Balíček (url: „https://github.com/vapor/vapor.git“, majorVersion: 2),
    .Balíček (url: "https://github.com/vapor/fluent-provider.git", majorVersion: 1), <- NEZAPOMÍNAJTE TENTO KOMMA;)
    .Balíček (url: "https://github.com/vapor/postgresql-provider.git", majorVersion: 2)
  ],
  vyloučit: [
    "Config",
    "Databáze",
    "Lokalizace",
    "Veřejnost",
    "Zdroje",
  ]
)

Nyní načtěte novou závislost terminálu v testovacím příkladu / adresáři, znovu vytvořte svůj projekt Xcode a znovu jej otevřete:

parní tah
páry xcode -y

V Sources / App / Config + Setup.swift přidejte PostgreSQLProvider:

importovat FluentProvider
import PostgreSQLProvider <- ADD
přípona Config {
  public func setup () vyvolá {
    // povolit fuzzy konverze pro tyto typy
    // (sem přidejte své vlastní typy)
    Node.fuzzy = [Row.self, JSON.self, Node.self]
    zkuste setupProviders ()
    zkuste setupPreparations ()
  }
  /// Konfigurovat poskytovatele
  private func setupProviders () vyvolá {
    zkuste addProvider (FluentProvider.Provider.self)
    zkuste addProvider (PostgreSQLProvider.Provider.self) <- ADD
  }
  /// Přidejte všechny modely, které by měly mít své
  /// schémata připravená před spuštěním aplikace
  private func setupPreparations () vyvolá {
  }
}
Podívejme se, jestli všechno zatím šlo dobře, ujistěte se, že jste vybrali My Mac a stiskli běh ► a uvidíme, jestli 127.0.0.1:8080 v prohlížeči vrací prázdnou stránku

4. Nakonfigurujte a vytvořte databázi

Uvnitř Config / vytvořte novou složku nazvanou tajemství a ve složce tajemství / adresář vytvořte soubor s názvem postgresql.json:

testovací příklad /
├── Package.swift
├── Zdroje /
├── Testy /
├── Config /
├── ├── app.json
│ ├── crypto.json
│ ├── droplet.json
├── ├── fluent.json
│ ├── tajemství / <- VYTVOŘIT
│ │ └── postgresql.json <- CREATE
│ └── server.json
├── Veřejné /
├── Závislosti /
└── Produkty /

Uvnitř postgresql.json napište:

{
  "hostname": "127.0.0.1",
  "port": 5432,
  "user": "martinlasek",
  "Heslo": "",
  "database": "testexample"
}
Poznámka: uživatele martinlasek budete muset nahradit svým uživatelským jménem

Inside Config / fluent.json nastavte postgresql jako váš ovladač

{
  "//": "Základní databázová technologie, která se má použít.",
  "//": "paměť: SQLite v paměti DB.",
  "//": "sqlite: Persisted SQLite DB (konfigurovat s sqlite.json)",
  "//": "Další ovladače jsou k dispozici prostřednictvím poskytovatelů Vapor",
  "//": "https://github.com/search?q=topic:vapor-provider+topic:database",
  "driver": "postgresql", <- změna z paměti na postgresql
  ...
}

Vytvořte testovací příklad databáze zadáním následujícího do terminálu:

createdb testexample;

5. Vytvořte uživatelský model

Uvnitř zdrojů / aplikací / modelů / vytvořte soubor s názvem User.swift, regenerujte a otevřete svůj projekt Xcode:

klepněte na Zdroje / Aplikace / Modely / User.swift
páry xcode -y
Protože ve vašem adresáři Modely / adresář není žádný soubor .swift, Xcode tento adresář nezobrazí. Proto nemůžete vytvořit soubor v rámci modelů / prostřednictvím Xcode

Vložte do kódu Inside Sources / App / Models / User.swift následující kód:

import Vapor
importovat FluentProvider
import HTTP
konečná třída Uživatel: Model {
  let storage = Storage ()
  var username: String
  var věk: Int
  init (uživatelské jméno: String, věk: Int) {
    self.username = uživatelské jméno
    self.age = věk
  }
  // inicializovat uživatele databázovými daty
  init (row: Row) vyvolá {
    username = try row.get ("username")
    age = try row.get ("age")
  }
  func makeRow () vyvolá -> Řádek {
    var row = Row ()
    try row.set ("username", username)
    try row.set ("věk", věk)
    návratová řada
  }
}
/ / / MARK: Plynulá příprava
přípona Uživatel: Příprava {
  // připraví tabulku v databázi
  static func prepar (_ database: Database) vyvolá {
    zkuste database.create (self) {builder in
      builder.id ()
      builder.string („uživatelské jméno“)
      builder.int ("věk")
    }
  }
  // odstraní tabulku z databáze
  static func revert (_ database: Database) vyvolá {
    zkuste database.delete (self)
  }
}
/// OZNAČENÍ: JSON
přípona Uživatel: JSONConvertible {
  // umožňuje inicializovat uživatele pomocí json
  pohodlí init (json: JSON) vyvolá {
    self.init (
      username: try json.get ("username"),
      age: try json.get ("age")
    )
  }
  // vytvořit json z instance uživatele
  func makeJSON () vyvolá -> JSON {
    var json = JSON ()
    zkuste json.set (User.idKey, id)
    zkuste json.set ("username", username)
    zkuste json.set ("věk", věk)
    návrat json
  }
}

Přidejte svou aplikaci do svého modelu tím, že ji přidáte do Sources / App / Config + Setup.swift

importovat FluentProvider
import PostgreSQLProvider
přípona Config {
  public func setup () vyvolá {
    // povolit fuzzy konverze pro tyto typy
    // (sem přidejte své vlastní typy)
    Node.fuzzy = [Row.self, JSON.self, Node.self]
    zkuste setupProviders ()
    zkuste setupPreparations ()
  }
  /// Konfigurovat poskytovatele
  private func setupProviders () vyvolá {
    zkuste addProvider (FluentProvider.Provider.self)
    zkuste addProvider (PostgreSQLProvider.Provider.self)
  }
  /// Přidejte všechny modely, které by měly mít své
  /// schémata připravená před spuštěním aplikace
  private func setupPreparations () vyvolá {
    Prepar.append (User.self) <- PŘIDAT
  }
}

Nyní znovu spusťte projekt ►, připraví vaši databázi a vytvoří uživatelskou tabulku. Vaše konzole Xcode vám ukáže něco jako:

Aktuální hashovací klíč „0000000000000000“ není bezpečný.
Před použitím ve výrobě aktualizujte hash.key v Config / crypto.json.
K vygenerování náhodného řetězce použijte `openssl rand -base64 `.
Aktuální šifrový klíč „AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAčeUČITČEČÍ 90 105 41
Před použitím ve výrobě aktualizujte soubor cipher.key v Config / crypto.json.
K vygenerování náhodného řetězce použijte `openssl rand -base64 32`.
Databáze připravena <- to je to, co hledáme
Žádný příkaz není dodáván, výchozí nastavení je…
Spouštěcí server dne 0.0.0.0:8080
Pokud vám Xcode nedovolí spustit váš projekt, spusťte v terminálu páry xcode -y a zkuste znovu spustit

6. Implementujte: Vytvořit

Ve vašem Sources / App / Routes.swift implementujte novou cestu, která bude očekávat požadavek JSON, inicializovat uživatele z něj a přetrvat ho do databáze:

import Vapor
rozšíření Droplet {
  func setupRoutes () vyvolá {
    /// Vytvořit uživatele
    /// http: post
    příspěvek ("uživatel") {req in
      // check request zachovává json
      stráž nechal json = req.json else {
        throw Abort (.badRequest, důvod: "není poskytován json")
      }
      let user: User
      // zkuste inicializovat uživatele pomocí json
      dělat {
        user = try User (json: json)
      }
      úlovek {
        throw Abort (.badRequest, důvod: "nesprávný json")
      }
      // uložit uživatele
      try user.save ()
      // návratový uživatel
      návrat try user.makeJSON ()
    }
  }
}

Pokud nyní spustíte ► vaši aplikaci a POST na 127.0.0.1:8080/user s platným JSON:

{
  "username": "Tom Cruise",
  "věk": 23
}

vytvoří uživatele, uloží jej do databáze a vrátí vám vytvořeného uživatele ve formátu JSON. Můžete použít Postman, nebo pokud mluvíte nerdy , stačí zadat terminál:

curl -H "Content-Type: application / json" -X POST -d '{"username": "Tom Cruise", "age": 23}' http://127.0.0.1:8080/user

V každém případě dostanete odpověď vypadající takto:

{"id": 1, "age": 23, "username": "Tom Cruise"}

7. Implementujte: Přečtěte si

Ve svých zdrojích / aplikacích / Routes.swift implementujte novou trasu, která očekává ID a vrátí vám uživatele s tímto ID ve formátu JSON:

import Vapor
rozšíření Droplet {
  func setupRoutes () vyvolá {
    /// Vytvořit uživatele
    /// http: post
    příspěvek ("uživatel") {req in
      ...
    }
    /// PŘEČTĚTE uživatele podle daného id
    /// http: get
    get ("user", Int.parameter) {req in
      // get id from url
      let userId = try req.parameters.next (Int.self)
      // najít uživatele s daným id
      guard let user = try User.find (userId) else {
        throw Abort (.badRequest, důvod: "uživatel s id \ (userId) neexistuje")
      }
      // vrátit uživatele jako json
      návrat try user.makeJSON ()
    }
  }
}

Pokud nyní spouštíte ► vaši aplikaci, protože se jedná o trasu GET, můžete spustit prohlížeč 127.0.0.1:8080/user/1 buď v prohlížeči, nebo pokud mluvíte nerdy stačí zadat terminál:

stočit http://127.0.0.1:8080/user/1

mělo by vám vrátit JSON uživatele s ID použitým v adrese URL vypadající takto:

{
  "id": 1,
  "věk": 23,
  "username": "Tom Cruise"
}

8. Implementace: Aktualizace

Ve svých zdrojích / aplikacích / Routes.swift implementujte novou trasu, která bude očekávat požadavek JSON s ID, které bude uživatel aktualizovat a vrátit vám aktualizovaného uživatele ve formátu JSON:

import Vapor
rozšíření Droplet {
  func setupRoutes () vyvolá {
    /// Vytvořit uživatele
    /// http: post
    příspěvek ("uživatel") {req in
      ...
    }
    /// PŘEČTĚTE uživatele podle daného id
    /// http: get
    get ("user", Int.parameter) {req in
      ...
    }
    
    /// UPDATE uživatel plně
    /// http: put
    put ("user", Int.parameter) {req in
      // get userId from url
      let userId = try req.parameters.next (Int.self)
      // najít uživatele podle daného id
      guard let user = try User.find (userId) else {
        throw Abort (.badRequest, reason: "uživatel s daným id: \ (userId) nebyl nalezen")
      }
      // check username poskytuje json
      guard let username = req.data ["username"] ?. string else {
        throw Abort (.badRequest, důvod: „není zadáno žádné uživatelské jméno“)
      }
      // věk kontroly poskytuje společnost json
      guard let age = req.data ["age"] ?. int else {
        throw Abort (.badRequest, důvod: „není poskytován věk“)
      }
      // nastaví nové hodnoty na nalezeného uživatele
      user.username = uživatelské jméno
      user.age = věk
      // uložit uživatele s novými hodnotami
      try user.save ()
      // vrátit uživatele jako json
      návrat try user.makeJSON ()
    }
  }
}

Pokud nyní spustíte ► vaši aplikaci a PUT na 127.0.0.1:8080/user/1 s platným JSON:

{
  "username": "Link",
  "věk": 41
}

vyhledá uživatele s daným id v URL, aktualizuje jeho vlastnosti, uloží ho zpět do databáze a vrátí jej zpět ve formátu JSON. Můžete použít Postman, nebo pokud mluvíte nerdy , stačí zadat terminál:

curl -H "Content-Type: application / json" -X PUT -d '{"username": "Yamato", "age": 41}' http://127.0.0.1:8080/user/1

mělo by vám vrátit JSON aktualizovaného uživatele, který vypadá takto:

{
  "id": 1,
  "username": "Yamato"
  "věk": 41,
}

9. Implementace: Odstranit

Ve své Sources / App / Routes.swift implementujte novou trasu, která očekává ID a vrátí vám JSON s úspěšnou zprávou

import Vapor
rozšíření Droplet {
  func setupRoutes () vyvolá {
    /// Vytvořit uživatele
    /// http: post
    příspěvek ("uživatel") {req in
      ...
    }
    /// PŘEČTĚTE uživatele podle daného id
    /// http: get
    get ("user", Int.parameter) {req in
      ...
    }
    
    /// UPDATE uživatel plně
    /// http: put
    put ("user", Int.parameter) {req in
      ...
    }
    /// VYMAZAT uživatele pomocí id
    /// http metoda: odstranit
    delete ("user", Int.parameter) {req in
      // získejte uživatelské jméno z adresy URL
      let userId = try req.parameters.next (Int.self)
      // najít uživatele s daným id
      guard let user = try User.find (userId) else {
        throw Abort (.badRequest, důvod: "uživatel s id \ (userId) neexistuje")
      }
      // smazat uživatele
      zkuste user.delete ()
      návrat try JSON (uzel: ["type": "success", "message": "uživatel s id \ (userId) byl úspěšně smazán"])
    }
  }
}

Pokud nyní spustíte ► vaši aplikaci a ODSTRANIT na 127.0.0.1:8080/user/1, vyhledá uživatele s daným id v adrese URL, smaže jej a vrátí JSON s úspěšnou zprávou včetně ID uživatele. Můžete použít Postman, nebo pokud mluvíte nerdy , stačí zadat terminál:

curl -X DELETE http://127.0.0.1:8080/user/1

Mělo by vám vrátit JSON vypadající takto:

{
  "type": "success",
  "message": "uživatel s ID 1 byl úspěšně smazán"
}

Gratuluji! Úspěšně jste implementovali API s CRUD na uživatele !!

Kam dál? Naučte se, jak testovat trasy zde!

Děkuji za přečtení! Pokud máte nějaké návrhy nebo vylepšení, dejte mi vědět! Rád bych od vás slyšel!

Twitter / Github / Instagram