4. Docker dan RESTful API - Algoritma-dan-Pemrograman-ITS/camin-2023 GitHub Wiki

Docker dan API

Docker

Bayangkan ketika kita ingin memelihara 2 jenis ikan, yang satu adalah ikan air tawar, dan yang satu adalah ikan air asin, sementara kita hanya punya satu akuarium. Salah satu solusi yang terpikirkan adalah dengan memasang penyekat kedap air pada akuairum sehingga yang satu dapat diisi dengan air tawar dan yang satunya lagi dapat diisi dengan air asin. Kurang lebih seperti itulah docker bekerja.

ilustrasi docker

Pada ilustrasi diatas, Docker membuat sebuah kontainer untuk masing-masing aplikasi dengan environment yang berbeda-beda, yang masing-masing kontainer memiliki environment yang mendukung aplikasi di dalamnya.

Sebelum kita mendalami penggunaan Docker pada Laravel, alangkah baiknya untuk melakukan instalasi Docker terlebih dahulu.

Pada Ubuntu

cek di sini

Pada Windows

Lakukan instalasi WSL (Windows Subsystem for Linux) terlebih dahulu di sini, barulah kemudian instal docker di sini.

Disclaimer: jika ukuran RAM kalian dibawah 8 GB (disarankan setidaknya memiliki RAM 12 GB atau lebih), disarankan untuk menginstall docker pada linux (bisa menggunakan virtual box atau dual boot)

Docker pada Laravel

Salah satu ciri-ciri adanya aplikasi yang menggunakan Docker, maka terdapat file docker-compose.yml.

docker-compose

Buatlah sebuah file dengan nama docker-compose.yml dan isikan file tersebut dengan contoh di bawah.

services:
  # Database
  db:
    platform: linux/x86_64
    image: mysql:5.7
    volumes:
      - db_data:/var/lib/mysql
    restart: always
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: yourdb
      MYSQL_PASSWORD: password
    networks:
      - mysql-phpmyadmin

  # phpmyadmin
  phpmyadmin:
    depends_on:
      - db
    image: phpmyadmin
    restart: always
    ports:
      - "8090:80"
    environment:
      PMA_HOST: db
      MYSQL_ROOT_PASSWORD: password
    networks:
      - mysql-phpmyadmin

networks:
  mysql-phpmyadmin:

volumes:
  db_data:

Pada file diatas, nantinya Docker akan membuat sebuah kontainer dengan 2 layanan, yaitu database mysql dan phpmyadmin menggunakan image yang sudah ada pada Docker Hub. Jalankan command berikut untuk membuat kontainer yang diinginkan.

docker compose up -d

docker compose up

konsep image dan kontainer di sini mirip seperti konsep class dan object. class adalah sesuatu yang ada pada source code kita, dan object adalah hasil instansiasi dari class tersebut.

Buka http://localhost:8090/ (phpmyadmin dapat diakses pada port 8090 sesuai dengan isi docker-compose.yml).

phpmyadmin

Kredensial dari phpmyadmin sudah ada pada docker-compose.yml, yaitu root:password.

phpmyadmin setelah login

Kini project kita sudah memiliki sebuah database mysql yang dapat diakses melalui phpmyadmin. Sebelum melakukan migrasi, pastikan pada file .env, kredensial database sudah cocok dengan kredensial pada phpmyadmin.

env

Kemudian lakukanlah migrasi seperti yang sudah diajarkan.

image

Jika migrasi sukses, maka project kita sudah terhubung pada database yang ada di dalam kontainer Docker. Repository selengkapnya ada di sini.

Catatan: penulis lupa melakukan screenshot saat pertama kali melakukan migrasi, sehingga menggunakan rollback untuk memperlihatkan proses migrasi.

API

API (Application Programming Interface) adalah sebuah cara agar beberapa program dapat berkomunikasi satu sama lain. Hal ini akan sangat berguna ketika proyek yang kita lakukan memiliki beberapa program yang terpisah (Contoh: Program untuk Back-end dan Front-end).

API

Source: https://www.erp-information.com/

Spesifikasi API

Terdapat berbagai spesifikasi API, yang ada untuk menyelaraskan set of rules dan syntax.

Specifications

RESTful API

Disebut juga REST API, API ini merupakan API yang mengikuti arsitektur REST (representational state transfer)

REST API Method

Kriteria

  • Arsitektur client-server dengan messaging HTTP
  • Bersifat stateless, tidak ada informasi client di tiap request dan tiap request terpisah
  • Support caching
  • Antarmuka yang seragam dalam pertukaran informasi
  • Layered system

API Endpoint

API Endpoint adalah titik spesifik dimana API suatu program dapat diakses oleh program lain. Konsepnya nyaris sama dengan konsep URL dan URI yang pernah dibahas sebelumnya.

Laravel Resources

Laravel memiliki sebuah class Resources yang berguna untuk melakukan formatting data menjadi bentuk JSON. Pada contoh kali ini, penulis menggunakan class Resources untuk formatting data sebelum data tersebut kita kirimkan. Command dibawah akan otomatis membuat sebuah file pada direktori app/Http/Resources/CaminResources.php.

php artisan make:resource CaminResource
<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class CaminResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
     */
    public function toArray($request)
    {
        return [
            'nama' => $this->nama,
            'angkatan_id' => $this->angkatan_id,
            'nrp' => $this->nrp,
            'jurusan' => $this->jurusan,
        ];
    }
}

Berikut adalah bentuk response ketika tidak menggunakan Resources:

image

Dan berikut ketika menggunakan Resources:

image

Laravel API

Spesifikasi API Endpoint ada pada routes/api.php. Sama seperti pada routes/web.php, penambahan URI pada routes/api.php akan menciptakan sebuah API Endpoint baru.

Route::get('/ping', function(){
    return response()->json('Pong', 200);
});

Route::controller(CaminAPIController::class)->group(function () {
    Route::get('/camin', 'index');
    Route::get('/camin/{camins_id}', 'show');
    Route::post('/camin', 'store');
    Route::post('/camins', 'store_multiple');
    Route::put('/camin/{camins_id}', 'update');
    Route::delete('/camin/{camins_id}', 'destroy');
});

Pada contoh diatas, salah satu API Endpoint yang terbentuk adalah dengan URI /api/ping.

Karena penggunaan URI pada routes/web.php dan routes/api.php berbeda (yang satu mengembalikan view, yang satu mengembalikan JSON), ada baiknya untuk membuat controller sendiri yang didedikasikan untuk API endpoint tersebut.

// fungsi index yang digunakan pada web.php
public function index()
{
    $camins = Camin::all();
    return view('camin.index', compact('camins'));
}
// fungsi index yang digunakan pada api.php
public function index()
{
    $camins = CaminResource::collection(Camin::all());

    return response()->json([
        'status' => true,
        'camins' => $camins
    ]);
}

Repository: https://github.com/Kadigas/camin-2023/tree/docker

Testing API

Ada banyak cara untuk melakukan pengecekan apakah API sudah bekerja sebagaimana seharusnya atau belum. Cara paling primitif adalah menggunakan command curl pada terminal.

curl

Kita juga dapat melakukan pencarian API Endpoint pada browser kita, dan browser kita akan menampilkan responsenya.

browser

Terdapat juga beberapa aplikasi seperti Postman dan Insomnia yang didedikasikan untuk pengembangan API.

Insomnia

Postman

Request Header dan Body

Setiap kali kita melakukan pemanggilan API, Client (kita) mengirimkan sebuah HTTP Request pada alamat dari API tersebut. HTTP Request Header berisi informasi tambahan yang terkadang diperlukan oleh program tempat API berada seperti authorization.

Request Header

Adapun HTTP Request Body berisi file yang diperlukan oleh API jika API tersebut membutuhkan sebuah file seperti pada method POST.

Request Body

Ketika kita memanggil suatu API, sebuah HTTP Response akan dikirimkan kepada kita dengan Header dan Body yang memiliki penggunaan serupa dengan HTTP Request.

Berikut adalah contoh HTTP Response Header setelah pemanggilan method GET:

200 OK
Access-Control-Allow-Origin: *
Connection: Keep-Alive
Content-Encoding: gzip
Content-Type: text/html; charset=utf-8
Date: Mon, 18 Jul 2016 16:06:00 GMT
Etag: "c561c68d0ba92bbeb8b0f612a9199f722e3a621a"
Keep-Alive: timeout=5, max=997
Last-Modified: Mon, 18 Jul 2016 02:36:04 GMT
Server: Apache
Set-Cookie: mykey=myvalue; expires=Mon, 17-Jul-2017 16:06:00 GMT; Max-Age=31449600; Path=/; secure
Transfer-Encoding: chunked
Vary: Cookie, Accept-Encoding
X-Backend-Server: developer2.webapp.scl3.mozilla.com
X-Cache-Info: not cacheable; meta data too large
X-kuma-revision: 1085259
x-frame-options: DENY

Pemanggilan API

Pengecekan API pada materi sebelumnya sudah termasuk pemanggilan API, namun terdapat beberapa fungsi, library, package, atau sejenisnya yang didedikasikan untuk melakukan pemanggilan API.

LARAVEL JavaScript (Node)
Guzzle HTTP client (Facades\Http) fetch, axios

CORS

CORS (Cross-Origin Resource Sharing) adalah sebuah protokol atau mekanisme untuk pengambilan data dengan sumber dan tujuan yang berbeda.

CORS

Pada umumnya, Browser menggunakan SOP (Same-Origin Policy) sehingga browser akan memblokir konten jika terdapat perbedaan sumber (domain, port, protokol).

Hal ini dapat menjadi masalah saat integrasi Front-end dengan Back-end yang dapat diatasi dengan beberapa hal.

Modul ini hanya mengenalkan CORS namun belum dapat menjelaskan dengan rinci sekaligus penyelesaiannya. Diperlukan sumber lain untuk hal tersebut

Selengkapnya: https://www.contentstack.com/docs/developers/how-to-guides/understanding-and-resolving-cors-error/

Dokumentasi

Dokumentasi API adalah hal yang penting terlebih ketika kita membuatkan sebuah API yang bersifat publik. Penulis tidak memiliki pengalaman dalam hal ini, namun sebuah dokumentasi harus (menurut penulis) setidaknya memiliki:

  • API Endpoint (termasuk query pada URI jika ada)
  • Request (Header dan Body, lengkap dengan format data pada body seperti parameter apa yang ada, baik wajib dan opsional)
  • Response (Header dan Body, lengkap dengan kemungkinan response yang ada seperti: 200, 400, 404, dsb)