Thiết lập OpenAPI Linter tốt nhất cho thiết kế API nhất quán năm 2026

So sánh các tùy chọn trình kiểm tra OpenAPI (Spectral, Redocly, Vacuum) và thiết lập một quy trình tích hợp giữa trình chỉnh sửa, pre-commit và CI để đảm bảo thiết kế API nhất quán, được kiểm tra hợp đồng.

INEZA Felin-Michel

INEZA Felin-Michel

16 tháng 6 2026

Thiết lập OpenAPI Linter tốt nhất cho thiết kế API nhất quán năm 2026

Apidog cho doanh nghiệp

Triển khai tại chỗ

SSO & RBAC

Tuân thủ SOC 2

Khám phá Apidog Enterprise

Hai kỹ sư cùng một nhóm phát hành hai endpoint trong cùng một tuần. Một endpoint trả về created_at, endpoint kia trả về createdAt. Một endpoint phân trang với ?page=2, endpoint kia với ?offset=20. Một endpoint đặt lỗi trong đối tượng error cấp cao nhất, endpoint kia lại nhúng một chuỗi message. Cả hai đều vượt qua đánh giá mã, vì người đánh giá đọc logic chứ không đọc cách đặt tên. Sáu tháng sau, giao diện API của bạn trông như thể được viết bởi năm công ty khác nhau, và mỗi lần tích hợp client đều cần một trường hợp đặc biệt.

Một OpenAPI linter tồn tại để phát hiện sự sai lệch đó trước khi nó được triển khai. Nó đọc tài liệu OpenAPI của bạn, chạy nó đối chiếu với một tập hợp các quy tắc (các hoạt động cần mô tả, các lược đồ cần ví dụ, tên thuộc tính tuân theo quy ước viết hoa/thường, mỗi phản hồi khai báo một loại phương tiện), và làm hỏng bản dựng khi một quy tắc bị vi phạm. Đây là ý tưởng tương tự như ESLint cho JavaScript hoặc RuboCop cho Ruby, nhưng hướng đến hợp đồng API của bạn thay vì mã ứng dụng của bạn. Nếu bạn từng ước rằng việc đánh giá thiết kế API có thể được tự động hóa như cách định dạng mã, thì đó chính xác là những gì một linter thực hiện.

💡
Nếu bạn thiết kế và kiểm thử API của mình trong Apidog, bạn cũng sẽ nhận được các kiểm tra tính nhất quán ngay từ giai đoạn thiết kế cùng với một CLI kiểm soát phần còn lại của quy trình, vì vậy linter không phải là thứ duy nhất ngăn cách một đặc tả cẩu thả với việc đưa vào sản xuất. (Tải Apidog nếu bạn muốn thực hành theo các ví dụ về thiết kế.)
button

Một OpenAPI linter thực sự kiểm tra những gì

Một linter hoạt động trên tệp đặc tả, không phải trên một máy chủ đang chạy. Hãy hướng nó đến openapi.yaml và nó sẽ duyệt qua mọi đường dẫn, hoạt động, tham số, lược đồ và phản hồi, áp dụng các quy tắc từng cái một. Các quy tắc thuộc một vài nhóm.

Tính hợp lệ. Đây có phải là một tài liệu OpenAPI hợp lệ không? Mọi $ref có được giải quyết không? Các từ khóa bắt buộc có mặt không? Điều này trùng lặp với việc xác thực lược đồ đơn thuần, và hầu hết các linter thực hiện điều này như một cơ sở trước bất cứ điều gì khác.

Tính đầy đủ. Mọi hoạt động có operationId, tóm tắt và mô tả không? Mọi tham số có tự giải thích không? Mọi lược đồ có mang một example không? Đây là những quy tắc giúp tài liệu và SDK được tạo ra thực sự có thể sử dụng được, và chúng là những thứ mà con người thường quên nhất.

Tính nhất quán. Đây là phần thưởng thực sự. Tên thuộc tính sử dụng một quy ước viết hoa/thường. Các phân đoạn đường dẫn là danh từ số nhiều. Các phản hồi lỗi có chung một cấu trúc. Mọi phản hồi 2xx đều khai báo application/json. Mã trạng thái được sử dụng theo đúng ý định của đặc tả HTTP. Không có lỗi nào trong số này là lỗi khi đứng một mình; cùng với nhau, chúng tạo nên sự khác biệt giữa một API có cảm giác được thiết kế và một API có cảm giác được lắp ghép.

Phong cách riêng. Các quy ước riêng của bạn. Có thể mọi endpoint phải được gắn thẻ. Có thể DELETE phải trả về 204. Có thể các trường chỉ dùng nội bộ phải có tiền tố. Đây là những quy tắc mà không ai khác có, và khả năng viết chúng là điều phân biệt một linter mà bạn có thể sống chung với một linter mà bạn phải đấu tranh.

Một quy tắc có mức độ nghiêm trọng: lỗi (error), cảnh báo (warning), thông tin (info) hoặc gợi ý (hint). Lỗi sẽ làm hỏng bản dựng; cảnh báo sẽ hiển thị nhưng vẫn cho phép bản dựng qua. Thanh điều chỉnh mức độ nghiêm trọng đó là thứ cho phép bạn áp dụng linting trên một API hiện có mà không bị chìm trong 4.000 vi phạm ngay từ ngày đầu tiên. Bắt đầu mọi thứ với mức cảnh báo, sửa những lỗi tồi tệ nhất, sau đó nâng cấp các quy tắc lên mức lỗi khi bạn tiến hành. Về mặt khái niệm tại sao các quy tắc này lại quan trọng và cách các nhóm thực thi chúng ở quy mô lớn, thông tin chi tiết hơn nằm trong cách các công ty hàng đầu đảm bảo tính nhất quán trong thiết kế API.

Các tùy chọn linter OpenAPI chính

Dưới đây là các công cụ đáng biết, với đánh giá trung thực về vị trí phù hợp của từng công cụ.

Spectral

Spectral, từ Stoplight, là tiêu chuẩn thực tế. Đây là một CLI và thư viện mã nguồn mở thực hiện linting cho OpenAPI 2.0 và 3.x (cũng như AsyncAPI, và bất kỳ JSON hoặc YAML nào thông qua JSONPath). Nó đi kèm với một bộ quy tắc spectral:oas tích hợp sẵn bao gồm các quy tắc thông thường, và điểm mạnh thực sự của nó là các quy tắc tùy chỉnh: bạn mô tả những gì cần kiểm tra bằng cách sử dụng các bộ chọn given kiểu JSONPath cùng với một hàm then, tất cả trong một tệp YAML. Có một danh mục lớn các hàm tích hợp sẵn (truthy, pattern, casing, length, enumeration) và bạn có thể chuyển sang JavaScript khi cần logic mà định dạng khai báo không thể diễn tả.

Điểm mạnh: nó có mặt ở khắp mọi nơi, nó có hệ sinh thái quy tắc lớn nhất, các tiện ích mở rộng trình chỉnh sửa tồn tại cho VS Code và các trình khác, và nó chạy ở bất cứ đâu Node chạy. Nếu bạn muốn một công cụ được toàn ngành công nhận, thì đây chính là nó. Đánh đổi là việc viết các quy tắc không tầm thường có nghĩa là phải học JSONPath và, cuối cùng, API hàm của Spectral. Chúng tôi có một hướng dẫn đầy đủ về điều đó trong xây dựng các quy tắc Spectral tùy chỉnh với TypeScript nếu bạn muốn tìm hiểu sâu về việc tạo quy tắc.

extends: ["spectral:oas"]
rules:
  operation-operationId: error
  operation-description: warn
  property-casing:
    description: Properties must be camelCase
    given: $.components.schemas..properties[*]~
    severity: error
    then:
      function: casing
      functionOptions:
        type: camel
npx @stoplight/spectral-cli lint openapi.yaml

Redocly CLI

Redocly CLI kết hợp linting với đóng gói (bundling) và xem trước tài liệu. Linter của nó đọc cấu hình redocly.yaml, cung cấp một bộ quy tắc tích hợp sẵn và hỗ trợ các bộ quy tắc có thể cấu hình cùng với các plugin tùy chỉnh được viết bằng JavaScript. Các nhóm đã sử dụng Redocly để tạo tài liệu sẽ có linting trong cùng một chuỗi công cụ mà không cần thêm phụ thuộc, và các quy tắc tích hợp sẵn hướng tới những gì giúp tài liệu hiển thị tốt.

Điểm mạnh: tích hợp chặt chẽ với quy trình làm việc tài liệu và đóng gói, các giá trị mặc định tốt, và định dạng cấu hình cảm thấy quen thuộc nếu bạn đang sống trong hệ sinh thái Redocly. Nếu bạn chưa sử dụng, thư viện quy tắc nhỏ hơn của Spectral và câu chuyện về quy tắc tùy chỉnh ít được tài liệu hóa rộng rãi hơn.

npx @redocly/cli lint openapi.yaml

Vacuum

Vacuum là một linter mới hơn được viết bằng Go, được xây dựng để đạt tốc độ cao. Nó tương thích với các bộ quy tắc của Spectral, vì vậy bạn có thể trỏ nó vào một tệp .spectral.yaml hiện có và nhận được các kiểm tra tương tự chạy nhanh hơn đáng kể trên các đặc tả lớn. Đối với một monorepo với hàng chục tài liệu API lớn, sự khác biệt về thời gian chạy là có thật.

Điểm mạnh: nhanh, tương thích với bộ quy tắc Spectral, một tệp nhị phân duy nhất không cần môi trường chạy Node. Nếu đặc tả của bạn nhỏ, lợi ích về tốc độ là không đáng kể, và hệ sinh thái cũng như công cụ chỉnh sửa còn non trẻ hơn của Spectral, vì vậy nó hấp dẫn nhất như một công cụ tăng tốc CI hơn là một lựa chọn từ đầu.

Swagger và openapi-spec-validator

Cần nhắc tên để bạn không nhầm lẫn chúng với các linter. Swagger Editor và swagger-cli/openapi-spec-validator kiểm tra xem một tài liệu có phải là OpenAPI hợp lệ hay không. Đó chỉ là tính hợp lệ, không phải tính nhất quán hay phong cách riêng. Chúng sẽ vui vẻ chấp nhận một đặc tả mà mọi thuộc tính được đặt tên khác nhau, bởi vì không có gì trong đặc tả OpenAPI cấm điều đó. Xác thực là cần thiết, nhưng nó là mức sàn, không phải mức trần. Nếu bạn đang lựa chọn giữa các công cụ họ Swagger và một nền tảng thiết kế đầy đủ, những đánh đổi được trình bày trong các lựa chọn thay thế Swagger cũng kiểm thử API của bạn.

Kiểm tra trong thời gian thiết kế với Apidog

Các công cụ trên chạy sau khi bạn có một tệp. Nơi khác để phát hiện sự không nhất quán là trước khi tệp tồn tại, trong khi bạn đang thiết kế endpoint. Apidog là một nền tảng thiết kế ưu tiên: bạn xây dựng các endpoint và lược đồ dữ liệu trong một trình chỉnh sửa trực quan, và nó giữ cho dự án của bạn nhất quán nội bộ trong suốt quá trình. Các lược đồ dữ liệu có thể tái sử dụng có nghĩa là cùng một mô hình được tham chiếu ở khắp mọi nơi thay vì định nghĩa lại cho mỗi endpoint, điều này loại bỏ toàn bộ một loại sai lệch trong việc đặt tên ngay từ nguồn. Các thành phần phản hồi được chia sẻ cũng làm điều tương tự cho các cấu trúc lỗi.

Apidog không phải là một sự thay thế trực tiếp cho bộ quy tắc của Spectral; nếu bạn đã cam kết các quy tắc .spectral.yaml, hãy tiếp tục chạy chúng. Điều Apidog thay đổi là lượng lỗi mà linter của bạn tìm thấy ngay từ đầu. Khi giao diện thiết kế buộc phải tái sử dụng, linter sẽ chuyển từ việc tìm thấy hàng loạt vi phạm sang chỉ thỉnh thoảng phát hiện. Và bởi vì Apidog nhập và xuất OpenAPI 3.x tiêu chuẩn, tệp bạn đưa cho Spectral hoặc Vacuum trong CI là cùng một hiện vật, vì vậy hai lớp này bổ trợ cho nhau thay vì cạnh tranh.

Thiết lập linter bạn có thể chạy ngay hôm nay

Một thiết lập tốt sẽ chạy kiểm tra ở ba nơi, mỗi nơi có một nhiệm vụ khác nhau. Trình chỉnh sửa cung cấp phản hồi tức thì. Hook pre-commit ngăn chặn các lỗi rõ ràng tại chỗ. CI là cổng mà không ai có thể bỏ qua. Dưới đây là từng lớp.

Lớp 1: trình chỉnh sửa

Cài đặt tiện ích mở rộng Spectral VS Code và thêm tệp .spectral.yaml vào thư mục gốc của kho lưu trữ. Tiện ích mở rộng sẽ tự động nhận diện và gạch chân các vi phạm khi bạn chỉnh sửa đặc tả, giống như cách một lỗi chính tả bị gạch chân màu đỏ. Đây là vòng lặp phản hồi rẻ nhất có thể, bởi vì nhà phát triển sửa lỗi trước khi nó trở thành một commit. Không có gì khác để cấu hình; tệp trong kho lưu trữ là nguồn duy nhất của sự thật về các quy tắc.

Lớp 2: pre-commit

Thêm một hook để một đặc tả bị lỗi không bao giờ đến được remote. Sử dụng một script package.json cộng với một Git hook là đủ:

{
  "scripts": {
    "lint:api": "spectral lint openapi.yaml --fail-severity=error"
  }
}
# .git/hooks/pre-commit  (or via husky)
#!/bin/sh
npm run lint:api || {
  echo "OpenAPI lint failed. Fix the spec before committing."
  exit 1
}

Cờ --fail-severity=error là phần quan trọng. Nó cho linter thoát với mã khác không chỉ khi có lỗi, vì vậy các cảnh báo vẫn được in ra mà không chặn commit. Điều đó giữ cho hook có thể sử dụng được trong khi bạn vẫn đang nâng cấp các quy tắc.

Lớp 3: CI

Đây là cổng quan trọng, bởi vì đó là cổng mà đồng đội không thể bỏ qua bằng --no-verify. Một bước của GitHub Actions:

name: API lint
on: [pull_request]
jobs:
  spectral:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npx @stoplight/spectral-cli lint openapi.yaml --fail-severity=error

Công việc thất bại khi đặc tả vi phạm một quy tắc cấp lỗi, yêu cầu pull request hiển thị dấu kiểm màu đỏ, và việc hợp nhất bị chặn cho đến khi ai đó sửa nó. Đó là toàn bộ cơ chế thực thi. Không bảng điều khiển, không cằn nhằn; quy tắc hoặc là xanh hoặc là không.

Lớp 4: kiểm thử API theo đặc tả mô tả

Một linter chứng minh đặc tả được định dạng tốt và nhất quán. Nó không nói lên liệu API đang chạy có khớp với đặc tả hay không. Khoảng cách đó là nơi sự sai lệch hợp đồng ẩn nấp: một tài liệu được linting đẹp mắt mô tả hành vi mà máy chủ đã ngừng tuân thủ ba bản phát hành trước đó. Để thu hẹp khoảng cách này, bạn chạy các kiểm thử đối với API trực tiếp trong cùng một quy trình.

Đây là nơi Apidog CLI phù hợp bên cạnh linter của bạn. Nó là một gói npm, apidog-cli, và nó chạy các kịch bản kiểm thử Apidog của bạn từ dòng lệnh để chúng được đưa vào CI ngay sau bước lint:

npm install -g apidog-cli
apidog run --access-token $APIDOG_ACCESS_TOKEN -t 605067 -e 1629989 -r cli,junit

Lệnh apidog run thoát với mã khác không khi một kiểm thử thất bại, cùng một giao ước mà mọi bước CI đều dựa vào, vì vậy một kiểm thử thất bại sẽ chặn việc hợp nhất đúng như cách một lỗi lint thất bại. Bộ báo cáo -r junit xuất ra XML mà bảng điều khiển CI của bạn phân tích thành cây pass/fail, và -e chỉ các kịch bản tương tự đến môi trường staging hoặc production mà không cần sao chép chúng. CLI cũng có thể import một tài liệu OpenAPI 3.x, vì vậy tệp mà linter của bạn kiểm tra là cùng tệp mà Apidog kiểm thử. Để biết toàn bộ mẫu pipeline, bao gồm các bộ báo cáo và xử lý mã thoát, hãy xem hướng dẫn về chạy Apidog CLI trong pipeline CI/CD của bạn. Nếu bạn đang sử dụng GitHub cụ thể, Apidog CLI trong GitHub Actions có một quy trình làm việc có thể sao chép-dán.

Lint trước, kiểm thử sau. Bước lint nhanh và bắt các vấn đề thiết kế; bước kiểm thử chậm hơn và bắt các vấn đề hành vi. Chạy chúng như hai giai đoạn và một pull request phải vượt qua cả hai.

Chọn và áp dụng bộ quy tắc mà không gặp khó khăn

Chọn công cụ là phần dễ. Áp dụng nó trên một API đã tồn tại là nơi các nhóm bị đình trệ, bởi vì lần chạy đầu tiên trên một đặc tả trưởng thành sẽ trả về hàng trăm vi phạm và phản ứng rõ ràng là tắt toàn bộ hệ thống.

Đừng bắt đầu từ không có quy tắc nào và đừng bắt đầu với mọi quy tắc ở mức lỗi. Hãy bắt đầu từ bộ quy tắc tích hợp sẵn (spectral:oas) với mọi thứ bạn thêm vào được đặt thành warn. Chạy nó, đọc số lượng, và sửa các lỗi hợp lệ trước tiên vì đó là những lỗi thực sự. Sau đó chọn hai hoặc ba quy tắc nhất quán quan trọng nhất đối với khách hàng của bạn (thường là quy tắc viết hoa/thường của thuộc tính và một cấu trúc lỗi duy nhất) và chỉ nâng cấp những quy tắc đó lên mức error. Mọi thứ khác vẫn là cảnh báo. Mỗi sprint, hãy nâng cấp thêm một hoặc hai cảnh báo lên lỗi khi cơ sở mã được cập nhật. Trong vòng một quý, toàn bộ bộ quy tắc sẽ được thực thi và không ai phải ngừng triển khai để đạt được điều đó.

Viết các quy tắc phong cách riêng một cách tiết kiệm. Mỗi quy tắc tùy chỉnh là mã mà ai đó phải bảo trì và giải thích cho người mới. Một quy tắc chỉ đáng được áp dụng khi một vi phạm thực sự gây ra vấn đề cho bạn, chứ không phải vì nó có thể. Đối với các quy tắc bạn viết, hãy dựa vào lớp thiết kế để làm cho chúng hiếm khi bị kích hoạt: nếu các lược đồ của bạn được tái sử dụng từ một định nghĩa trung tâm, một quy tắc viết hoa/thường của thuộc tính gần như không bao giờ được kích hoạt vì chỉ có một nơi tên được định nghĩa. Khung khái niệm về những quy tắc nào đáng được thực thi, và những quy tắc nào là tranh cãi vô ích, được đề cập trong các thực hành tốt nhất về thiết kế API.

Nếu bạn thiết kế bằng một ngôn ngữ khác với YAML thô, linter vẫn áp dụng. TypeSpec biên dịch thành OpenAPI, và bạn thực hiện linting tài liệu được xuất ra theo cùng một cách; linter không quan tâm tệp được tạo ra như thế nào, chỉ quan tâm đến nội dung của nó.

Linter phù hợp ở đâu trong vòng lặp thiết kế lớn hơn

Linter là một kiểm soát trong quy trình làm việc thiết kế ưu tiên, chứ không phải toàn bộ. Vòng lặp đầy đủ là: thiết kế hợp đồng, lint nó, mock nó để client có thể xây dựng dựa trên nó, kiểm thử việc triển khai đối với nó, và xuất bản tài liệu từ nó. Bỏ qua bất kỳ bước nào thì các bước khác sẽ mất giá trị. Một đặc tả đã được lint nhưng không ai mock vẫn chặn công việc frontend. Một đặc tả đã được mock nhưng không ai kiểm thử vẫn lệch khỏi thực tế.

Lý do đặt thiết kế lên hàng đầu trong vòng lặp đó cũng là lý do linting hoạt động hiệu quả: bắt các vấn đề ở nơi chúng dễ sửa chữa nhất. Thay đổi tên thuộc tính trong công cụ thiết kế là một lần chỉnh sửa. Thay đổi nó sau khi ba nhóm đã triển khai dựa trên tên cũ là một quá trình di chuyển. Linter thực thi tính nhất quán trên tệp; một quy trình thiết kế ưu tiên thực thi tính nhất quán trên quyết định trước khi tệp tồn tại. Nếu bạn muốn lập luận rộng hơn về thứ tự, API-first so với API design-first so với code-first trình bày các đánh đổi, và các công cụ thiết kế API theo hợp đồng ưu tiên bao gồm các công cụ hỗ trợ điều đó.

button

Apidog bao quát toàn bộ vòng lặp đó tại một nơi: thiết kế với các lược đồ có thể tái sử dụng, mock tức thì, kiểm thử với CLI trong CI và xuất OpenAPI sạch sẽ cho bất kỳ linter nào bạn tiêu chuẩn hóa. Linter vẫn có nhiệm vụ của nó; chỉ là nó ít phải phát hiện hơn.

button

Thực hành thiết kế API trong Apidog

Khám phá cách dễ dàng hơn để xây dựng và sử dụng API