Kiến trúc tổng quát

GraphQL plugin trong hệ thống này được thiết kế như một lớp tích hợp giữa GraphQL runtime và web application hiện có. Thay vì tự xây dựng một GraphQL server độc lập, plugin tận dụng hạ tầng web sẵn có để xử lý xác thực, quản lý request context, gọi service nghiệp vụ và trả response theo chuẩn GraphQL.
Cách tiếp cận này giúp GraphQL trở thành một phần tự nhiên của ứng dụng web, thay vì tạo ra một nhánh xử lý riêng biệt, tách rời với REST hoặc các cơ chế dùng chung khác.

Thành phần chính

Về mặt nguyên lý, plugin gồm bốn nhóm trách nhiệm chính.
Thứ nhất là lớp cấu hình. Lớp này bật khả năng xử lý GraphQL trong runtime và nạp các thiết lập cần thiết từ file cấu hình.
Thứ hai là cơ chế quét và đăng ký thành phần. Plugin không phụ thuộc vào một danh sách query cố định, mà đọc danh sách package từ cấu hình rồi quét các thành phần phù hợp để đưa vào runtime.
Thứ ba là lớp bảo mật. GraphQL request đi qua cơ chế xác thực của web layer trước, sau đó được kiểm tra thêm một lần ở tầng GraphQL để đảm bảo các query yêu cầu đăng nhập không thể chạy khi thiếu user context.
Thứ tư là lớp thực thi nghiệp vụ. Mỗi query GraphQL được ánh xạ tới một fetcher hoặc resolver chịu trách nhiệm đọc input, gọi service nghiệp vụ và trả dữ liệu hoặc lỗi theo cấu trúc GraphQL.

Luồng hoạt động

Luồng xử lý một GraphQL request có thể hình dung như sau:
sequenceDiagram
    participant Client as Client
    participant Web as Web runtime
    participant Auth as Web authentication
    participant GQL as GraphQL runtime
    participant Guard as GraphQL security check
    participant Resolver as GraphQL fetcher
    participant Service as Business service

    Client->>Web: Gửi GraphQL request
    Web->>Auth: Kiểm tra và nạp user context
    Auth-->>Web: Request context đã sẵn sàng

    Web->>GQL: Parse query
    GQL->>Guard: Kiểm tra query có yêu cầu đăng nhập không

    alt Thiếu quyền truy cập
        Guard-->>Client: Trả lỗi unauthorized
    else Hợp lệ
        GQL->>Resolver: Thực thi fetcher tương ứng
        Resolver->>Service: Gọi nghiệp vụ
        Service-->>Resolver: Trả dữ liệu
        Resolver-->>Client: GraphQL response
    end
Về bản chất, plugin không chỉ xử lý query ở thời điểm thực thi, mà còn tham gia từ rất sớm trong vòng đời request để đảm bảo context và bảo mật đã đầy đủ trước khi business logic được gọi.

Cách xử lý request và response

Khi request GraphQL đi vào hệ thống, web runtime trước tiên cố gắng nhận diện người dùng từ cơ chế xác thực chung của ứng dụng. Nếu request đã có sẵn user context thì luồng này gần như không phát sinh thêm chi phí. Nếu chưa có, hệ thống sẽ dùng cơ chế xác thực chung để bổ sung thông tin người dùng vào request context.
Sau bước đó, GraphQL runtime phân tích query, xác định tên thao tác cần thực thi và chọn fetcher tương ứng. Tại đây có thêm một lớp kiểm tra bảo mật ở đúng ngữ cảnh GraphQL. Lớp này dựa trên metadata của query để biết query nào bắt buộc phải có người dùng đã đăng nhập.
Nếu query hợp lệ, fetcher sẽ đọc input từ hai nguồn:
  • request context, dùng cho các dữ liệu hệ thống như thông tin người dùng
  • query definition, dùng cho các tham số nghiệp vụ của field đang được gọi
Fetcher sau đó gọi xuống service nghiệp vụ và trả dữ liệu về cho client. Nếu có lỗi validate hoặc lỗi nghiệp vụ theo ngữ cảnh GraphQL, plugin tạo response lỗi theo cấu trúc phù hợp để client có thể xác định đúng field, đúng nguyên nhân và đúng mã lỗi.

Bảo mật

Một trong những điểm đáng chú ý của thiết kế này là bảo mật được kiểm tra theo hai lớp.
Lớp đầu tiên nằm ở web layer. Mục tiêu của lớp này là đồng bộ GraphQL với cơ chế xác thực chung của toàn bộ ứng dụng. Nhờ đó, GraphQL không cần tự định nghĩa lại cách nhận diện người dùng.
Lớp thứ hai nằm ở GraphQL runtime. Lớp này không chỉ hỏi “request đã xác thực chưa”, mà hỏi cụ thể hơn: “query hiện tại có bắt buộc đăng nhập không”. Nếu câu trả lời là có, nhưng request không mang user context hợp lệ, hệ thống dừng thực thi ngay và trả lỗi truy cập.
Cách làm này giúp giảm rủi ro một query nhạy cảm bị gọi trong tình huống request đi qua được tầng web nhưng chưa có đủ ngữ cảnh bảo mật ở tầng GraphQL.

Vì sao thiết kế này hữu ích

Thiết kế này mang lại một số lợi ích rõ ràng.
Trước hết, GraphQL dùng lại được toàn bộ hạ tầng authentication của web application. Điều này giúp giảm trùng lặp logic và giữ cho hành vi giữa GraphQL và REST nhất quán.
Thứ hai, query được khai báo theo hướng mở rộng. Thay vì sửa code lõi mỗi khi thêm một query mới, hệ thống có thể phát hiện thêm thành phần mới qua cơ chế scan từ cấu hình.
Thứ ba, business logic không bị nhồi vào runtime GraphQL. Fetcher chỉ là lớp trung gian mỏng, còn nghiệp vụ thật sự vẫn nằm trong service layer, nhờ đó code dễ bảo trì hơn.
Thứ tư, response lỗi có cấu trúc rõ ràng hơn lỗi HTTP thuần túy trong nhiều tình huống nhập liệu sai hoặc validate thất bại, điều này đặc biệt hữu ích cho frontend.

Ranh giới với REST

Một điểm cần làm rõ là plugin này không biến GraphQL thành REST, và cũng không tự động chuyển mọi query GraphQL thành endpoint REST.
Điều mà plugin thực sự làm là:
  • tích hợp GraphQL vào web runtime
  • cung cấp fetcher để xử lý query
  • bổ sung cơ chế bảo mật và context cho GraphQL
  • hỗ trợ thêm khả năng sinh tài liệu cho REST API ở một phần khác của plugin
Nói cách khác, GraphQL và REST cùng tồn tại trong một hệ thống, dùng chung một số hạ tầng nền như authentication, configuration và tài liệu hóa, nhưng vẫn là hai mô hình giao tiếp khác nhau.

Giới hạn cần lưu ý

Từ source hiện tại có thể thấy plugin tập trung vào tích hợp runtime và thực thi query, chứ không thể hiện rằng nó tự xây schema engine riêng hay tự động sinh REST endpoint từ GraphQL operation.
Ngoài ra, endpoint GraphQL cụ thể không được khai báo thủ công trong phần plugin đang xét. Điều này cho thấy nhiều khả năng phần endpoint và runtime cốt lõi do framework đảm nhiệm, còn plugin chủ yếu bổ sung cấu hình, query handler và các lớp tích hợp đặc thù cho web application.
Đây là một ranh giới quan trọng cần giữ đúng khi mô tả kiến trúc, để tránh hiểu nhầm rằng plugin đang làm nhiều hơn những gì code thực sự thể hiện.

Kết luận

GraphQL plugin trong hệ thống này hoạt động như một lớp tích hợp kiến trúc: nó bật GraphQL trong web runtime, quét và đăng ký các thành phần mở rộng, tái sử dụng cơ chế xác thực chung của ứng dụng, áp dụng kiểm tra bảo mật ở tầng GraphQL, rồi chuyển từng query vào fetcher để gọi nghiệp vụ.
Điểm mạnh của cách thiết kế này là GraphQL không đứng riêng như một subsystem tách biệt, mà được gắn chặt vào hạ tầng web hiện có. Nhờ vậy, hệ thống vừa giữ được tính nhất quán về bảo mật và cấu hình, vừa đủ linh hoạt để mở rộng thêm query mới mà không phải can thiệp sâu vào lõi runtime.