Site icon Bệ Phóng Việt

Xây dựng Ứng Dụng Web Tương Tác với FastAPI và ReactJS

Advertisements

Giới Thiệu về FastAPI và ReactJS

FastAPI là một framework web hiệu suất cao cho Python, cho phép xây dựng nhanh chóng các dịch vụ backend mạnh mẽ với API RESTful. Nó rất phù hợp với các dự án cần hiệu suất và khả năng xử lý đồng thời cao.

ReactJS là một thư viện JavaScript mạnh mẽ và linh hoạt để xây dựng giao diện người dùng, giúp quản lý trạng thái ứng dụng hiệu quả và tạo ra các trải nghiệm tương tác mượt mà cho người dùng.

Thiết Lập Backend với FastAPI

Để bắt đầu với FastAPI, trước tiên chúng ta cần chuẩn bị môi trường Python và cài đặt các gói cần thiết. Bạn có thể tạo một môi trường ảo mới trong Python sử dụng `venv` như sau:

python -m venv env
source env/bin/activate # Đối với Linux/Mac
env\Scripts\activate   # Đối với Windows

Sau khi kích hoạt môi trường ảo, tiến hành cài đặt FastAPI và một ASGI server như `uvicorn`:

pip install fastapi uvicorn

Tiếp theo, bạn có thể định nghĩa một ứng dụng FastAPI đơn giản với một route như sau:

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def read_root():
    return {"Hello": "World"}

Chạy ứng dụng FastAPI bằng uvicorn với lệnh dưới đây:

uvicorn main:app --reload

Với lệnh trên, FastAPI sẽ chạy server ở trạng thái phát triển, với chế độ tự động cập nhật code khi có thay đổi.

Trong bài viết này, chúng ta sẽ cùng nhau tìm hiểu cách tạo một API đơn giản sử dụng FastAPI và kết nối với cơ sở dữ liệu qua SQLAlchemy. Đầu tiên, bạn cần chuẩn bị một dự án Python. Đảm bảo bạn có cài đặt sẵn FastAPI và SQLAlchemy bằng cách thêm chúng vào tệp requirements.txt hoặc thực hiện lệnh cài đặt qua pip:

pip install fastapi sqlalchemy

Sau đó, chúng ta sẽ tạo một file main.py để định nghĩa các tuyến API. Đây là ví dụ cơ bản để tạo một ứng dụng FastAPI:

from fastapi import FastAPI
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db"

engine = create_engine(
    SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()

app = FastAPI()

Trong đoạn mã trên, chúng ta khai báo URL cho cơ sở dữ liệu và tạo engine để kết nối. Biến SessionLocal sẽ được sử dụng để tương tác với cơ sở dữ liệu. Chúng ta cũng khởi tạo một ứng dụng FastAPI mới. Tiếp theo, định nghĩa một model cơ sở dữ liệu:

from sqlalchemy import Column, Integer, String

class Item(Base):
    __tablename__ = "items"

    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, index=True)
    description = Column(String, index=True)

Cuối cùng, ta sẽ tạo endpoint để phục vụ cho frontend bằng cách sử dụng decorator @app.get của FastAPI:

@app.get("/items/{item_id}")
async def read_item(item_id: int):
    return {"item_id": item_id, "name": "Item name", "description": "This is an example item"}

Bằng cách này, chúng ta đã thiết lập được một API cơ bản với FastAPI và có thể mở rộng để tích hợp với frontend ReactJS, đảm bảo rằng các endpoint của chúng ta có thể xử lý và trả về dữ liệu một cách hiệu quả.

Xây Dựng Giao Diện Người Dùng với ReactJS

ReactJS cho phép bạn tạo các component có thể tái sử dụng và quản lý trạng thái phức tạp một cách dễ dàng. Chúng ta sẽ khám phá cách thiết lập dự án React, sử dụng Redux để quản lý trạng thái toàn cục, và tích hợp với API FastAPI.

Trong phần này, chúng ta sẽ đi qua một ví dụ đơn giản để tạo giao diện đăng nhập sử dụng ReactJS và tích hợp nó với backend FastAPI. Điều này sẽ giúp hiển thị cách mà frontend và backend có thể chia sẻ dữ liệu và giữ cho thông tin người dùng được cập nhật và bảo mật.

Trước tiên, chúng ta cần tạo một component đăng nhập trong ReactJS. Component này sẽ chứa các ô nhập liệu cho tên người dùng và mật khẩu, cũng như nút gửi để kích hoạt hành động đăng nhập.

{`import React, { useState } from 'react';

function LoginForm() {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');

  const handleSubmit = (event) => {
    event.preventDefault();
    // Call the login API from FastAPI
    fetch('/api/login', {
      method: 'POST',
      headers: {'Content-Type': 'application/json'},
      body: JSON.stringify({ username, password }),
    })
    .then(response => response.json())
    .then(data => {
      // Handle success or error
      if (data.access_token) {
        localStorage.setItem('token', data.access_token);
        alert('Login successful!');
      } else {
        alert('Login failed!');
      }
    });
  }

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" value={username} onChange={(e) => setUsername(e.target.value)} />
      <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} />
      <button type="submit">Login</button>
    </form>
  );
}

export default LoginForm;
`}

Tiếp theo, chúng ta cần định nghĩa endpoint đăng nhập trong FastAPI để xử lý yêu cầu từ frontend. Endpoint này sẽ kiểm tra thông tin đăng nhập và trả về một token nếu thành công.

{`from fastapi import FastAPI, HTTPException
from pydantic import BaseModel

app = FastAPI()

class LoginRequest(BaseModel):
  username: str
  password: str

@app.post("/api/login")
async def login(request: LoginRequest):
  if request.username == 'admin' and request.password == 'secret':
    return {"access_token": "fake-jwt-token"}
  raise HTTPException(status_code=400, detail="Invalid credentials")
`}

Với ví dụ này, bạn có thể thấy cách ReactJS và FastAPI tương tác với nhau để hoàn tất một chức năng đăng nhập cơ bản. Component frontend gửi thông tin đăng nhập thông qua POST request đến API, và API trả về token hoặc thông báo lỗi.

Bảo Mật và Tích Hợp

Trong mọi ứng dụng web, bảo mật đóng vai trò then chốt để bảo vệ dữ liệu và quyền riêng tư của người dùng. Một trong những phương pháp phổ biến để thực hiện bảo mật là sử dụng JSON Web Token (JWT). JWT giúp xác thực người dùng một cách an toàn và đơn giản thông qua việc mã hóa thông tin xác thực thành các token. Những token này sẽ được gửi kèm theo mỗi yêu cầu HTTP đến server, từ đó server có thể dễ dàng xác thực và cho phép hoặc từ chối truy cập.

Khi sử dụng JWT trong FastAPI, trước hết chúng ta cần cài đặt thư viện hỗ trợ và thiết lập cơ chế mã hóa token. Server sẽ tạo một token mới với key bí mật khi người dùng đăng nhập thành công. Token này chứa thông tin người dùng và có thời hạn sử dụng nhất định. Tại frontend, mỗi khi thực hiện yêu cầu cần xác thực, ReactJS sẽ đính kèm token vào header của request.

Để bảo vệ các endpoint của API khỏi các truy cập trái phép, FastAPI cho phép thiết lập các dependency để kiểm tra token ở mỗi request. Nếu token hợp lệ, yêu cầu sẽ được thực hiện; ngược lại, sẽ trả về thông báo lỗi. Đây là cách hiệu quả để bảo vệ API của bạn tránh khỏi nguy cơ tấn công từ bên ngoài.

Việc kết hợp FastAPI và JWT không chỉ giúp tăng cường bảo mật mà còn đảm bảo trải nghiệm người dùng liền mạch, đồng thời giữ cho hệ thống của bạn an toàn trước các mối đe dọa an ninh mạng.

Trong phát triển ứng dụng web full-stack, vấn đề tích hợp giữa frontend và backend là vô cùng quan trọng để đảm bảo dữ liệu di chuyển mượt mà và trải nghiệm người dùng không bị gián đoạn. Với FastAPI và ReactJS, việc tích hợp này có thể đạt được dễ dàng thông qua các kỹ thuật tiên tiến và công cụ hỗ trợ mạnh mẽ.

Đầu tiên, việc quản lý CORS (Cross-Origin Resource Sharing) là cần thiết để đảm bảo rằng frontend (chạy trên một domain) có thể truy cập dữ liệu từ backend (chạy trên domain khác). FastAPI cung cấp các phương thức đơn giản để cấu hình CORS, giúp bạn kiểm soát và xác định rõ các nguồn tài nguyên nào sẽ có quyền truy cập API.

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

origins = [
    "http://localhost:3000",
    "https://myapp.example.com",
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

Mã trên cho thấy cách triển khai middleware cho phép các nguồn frontend có quyền truy cập.

Tiếp theo, sự đồng bộ giữa frontend ReactJS và backend FastAPI cần được quản lý một cách chính xác. ReactJS sử dụng fetch hoặc axios để gửi request và nhận response từ backend. Một approach phổ biến là sử dụng các promise để xử lý request không đồng bộ, giúp giao diện người dùng không bị ảnh hưởng do các quá trình tải dữ liệu.

import axios from 'axios';

const fetchUserData = async () => {
  try {
    const response = await axios.get('https://api.example.com/user');
    console.log(response.data);
    // Cập nhật state của React component với dữ liệu đã nhận
  } catch (error) {
    console.error("Có lỗi xảy ra khi tải dữ liệu:", error);
  }
};

// Gọi hàm fetchUserData khi component được mount
useEffect(() => {
  fetchUserData();
}, []);

Đoạn mã trên minh họa cách ReactJS gửi yêu cầu GET đến server và xử lý dữ liệu trả về với axios. Đồng thời, việc sử dụng useEffect hook giúp đảm bảo yêu cầu chỉ được thực hiện một lần sau khi component được render.

Bằng cách kết hợp các phương pháp trên, việc tích hợp giữa FastAPI và ReactJS được thực hiện mượt mà mà vẫn duy trì được tính bảo mật và hiệu suất cao.

Exit mobile version