본문으로 건너뛰기

Go SDK [community]

커뮤니티 SDK

이 SDK는 완전히 커뮤니티에서 관리합니다.

Remnawave Go SDK는 RestAPI와의 편리한 상호작용을 위한 라이브러리입니다.

✨ 주요 기능

  • ogen v1.19.0으로 생성: 고처리량을 위한 제로 리플렉션 JSON 디코더
  • 타입 안전: OpenAPI 3.0 스펙에 대한 컴파일 타임 검증
  • 컨트롤러 기반 설계: 깔끔한 API 접근을 위한 정리된 서브 클라이언트
  • 단순화된 시그니처: 간단한 작업을 위한 장황한 Params 구조체 없음
  • 컨텍스트 지원: 일급 context.Context 지원
  • OpenTelemetry: 내장 추적 계측
  • 요청 옵션: ...RequestOption을 통한 요청별 커스터마이징
  • 에디터: 요청/응답 미들웨어 지원

설치

go get github.com/Jolymmiles/remnawave-api-go/v2@latest
경고

항상 Remnawave 백엔드 버전에 맞는 올바른 버전의 SDK를 선택하고 고정하세요.

SDK 버전Remnawave 패널 버전
v2.6.12.6.1
v2.5.32.5.3
v2.3.0-62.3.0
v2.2.6-32.2.6

사용법

기본 예제
package main

import (
"context"
"fmt"
"log"

remapi "github.com/Jolymmiles/remnawave-api-go/v2/api"
)

func main() {
ctx := context.Background()

// Create base client
baseClient, err := remapi.NewClient(
"https://your-panel.example.com",
remapi.StaticToken{Token: "YOUR_API_TOKEN"},
)
if err != nil {
log.Fatal(err)
}

// Wrap with organized sub-clients
client := remapi.NewClientExt(baseClient)

// Get user by UUID - simplified signature
resp, err := client.Users().GetUserByUuid(ctx, "user-uuid-here")
if err != nil {
log.Fatal(err)
}

switch r := resp.(type) {
case *remapi.UserResponse:
fmt.Printf("User: %s\n", r.Response.Username)
case *remapi.NotFoundError:
fmt.Println("User not found")
case *remapi.BadRequestError:
fmt.Printf("Validation error: %v\n", r.Errors)
}
}
사용자 생성 및 관리
package main

import (
"context"
"fmt"
"log"

remapi "github.com/Jolymmiles/remnawave-api-go/v2/api"
)

func main() {
ctx := context.Background()

baseClient, _ := remapi.NewClient(
"https://your-panel.example.com",
remapi.StaticToken{Token: "YOUR_API_TOKEN"},
)
client := remapi.NewClientExt(baseClient)

// Create user
createResp, err := client.Users().CreateUser(ctx, &remapi.CreateUserRequest{
Username: "john_doe",
})
if err != nil {
log.Fatal(err)
}

user := createResp.(*remapi.UserResponse).Response
fmt.Printf("Created user: %s (UUID: %s)\n", user.Username, user.UUID)

// Disable user
_, err = client.Users().DisableUser(ctx, user.UUID.String())
if err != nil {
log.Fatal(err)
}
fmt.Println("User disabled")

// Enable user
_, err = client.Users().EnableUser(ctx, user.UUID.String())
if err != nil {
log.Fatal(err)
}
fmt.Println("User enabled")

// Delete user
_, err = client.Users().DeleteUser(ctx, user.UUID.String())
if err != nil {
log.Fatal(err)
}
fmt.Println("User deleted")
}
노드 관리
package main

import (
"context"
"fmt"
"log"

remapi "github.com/Jolymmiles/remnawave-api-go/v2/api"
)

func main() {
ctx := context.Background()

baseClient, _ := remapi.NewClient(
"https://your-panel.example.com",
remapi.StaticToken{Token: "YOUR_API_TOKEN"},
)
client := remapi.NewClientExt(baseClient)

// Get all nodes
nodesResp, err := client.Nodes().GetAllNodes(ctx)
if err != nil {
log.Fatal(err)
}

nodes := nodesResp.(*remapi.NodesResponse).Response
fmt.Printf("Total nodes: %d\n", len(nodes))

for _, node := range nodes {
fmt.Printf(" - %s (%s): connected=%v\n",
node.Name, node.Address, node.IsConnected)
}

// Get single node
if len(nodes) > 0 {
nodeResp, _ := client.Nodes().GetOneNode(ctx, nodes[0].UUID.String())
node := nodeResp.(*remapi.NodeResponse).Response
fmt.Printf("\nNode details: %s\n", node.Name)
}
}
페이지네이션
package main

import (
"context"
"fmt"
"log"

remapi "github.com/Jolymmiles/remnawave-api-go/v2/api"
)

func main() {
ctx := context.Background()

baseClient, _ := remapi.NewClient(
"https://your-panel.example.com",
remapi.StaticToken{Token: "YOUR_API_TOKEN"},
)
client := remapi.NewClientExt(baseClient)

// Use PaginationHelper for iterating through pages
pager := remapi.NewPaginationHelper(50) // 50 items per page

for pager.HasMore {
resp, err := client.Users().GetAllUsers(ctx,
pager.Limit, // size
pager.Offset, // start
)
if err != nil {
log.Fatal(err)
}

users := resp.(*remapi.GetAllUsersResponse)
for _, user := range users.Response.Users {
fmt.Printf("User: %s (UUID: %s)\n", user.Username, user.UUID)
}

// Advance to next page
pager.SetTotal(int(users.Response.Total))
pager.NextPage()
}

fmt.Printf("Total users: %d\n", *pager.Total)
}
오류 처리
package main

import (
"context"
"fmt"
"log"

remapi "github.com/Jolymmiles/remnawave-api-go/v2/api"
)

func main() {
ctx := context.Background()

baseClient, _ := remapi.NewClient(
"https://your-panel.example.com",
remapi.StaticToken{Token: "YOUR_API_TOKEN"},
)
client := remapi.NewClientExt(baseClient)

resp, err := client.Users().GetUserByUuid(ctx, "invalid-uuid")
if err != nil {
log.Fatal("Network error:", err)
}

// Available error types depend on the endpoint — check the generated
// Res interface (e.g. UsersGetUserByUuidRes) for the full list.
switch e := resp.(type) {
case *remapi.UserResponse:
fmt.Printf("User found: %s\n", e.Response.Username)
case *remapi.BadRequestError:
fmt.Println("Validation errors:")
for _, ve := range e.Errors {
fmt.Printf(" - %s: %s (path: %v)\n",
ve.Code, ve.Message, ve.Path)
}
case *remapi.NotFoundError:
fmt.Println("Resource not found")
case *remapi.InternalServerError:
fmt.Printf("Server error: %s\n", e.Message.Value)
}
}

사용 가능한 컨트롤러

컨트롤러설명
client.ApiTokens()API 토큰 관리
client.Auth()인증
client.BandwidthStatsNodes()노드 대역폭 통계
client.BandwidthStatsUsers()사용자 대역폭 통계
client.ConfigProfile()설정 프로파일
client.ExternalSquad()외부 스쿼드
client.Hosts()호스트 관리
client.HostsBulkActions()호스트 일괄 작업
client.HwidUserDevices()HWID 장치
client.InfraBilling()인프라 청구
client.InternalSquad()내부 스쿼드
client.Keygen()키 생성
client.Nodes()노드 관리
client.NodesUsageHistory()노드 사용 기록
client.Passkey()패스키 인증
client.RemnawaveSettings()패널 설정
client.Snippets()코드 스니펫
client.Subscription()구독 관리
client.SubscriptionPageConfig()구독 페이지 설정
client.SubscriptionSettings()구독 설정
client.SubscriptionTemplate()구독 템플릿
client.Subscriptions()다중 구독
client.System()시스템 정보
client.UserSubscriptionRequestHistory()요청 기록
client.Users()사용자 관리
client.UsersBulkActions()사용자 일괄 작업

오류 타입

타입HTTP 상태설명
BadRequestError400세부 정보가 있는 유효성 검사 오류
UnauthorizedError401인증 필요
ForbiddenError403접근 거부
NotFoundError404리소스를 찾을 수 없음
InternalServerError500서버 오류

🛠️ 프로젝트 링크