fmgcli

package module
v0.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 14, 2026 License: MIT Imports: 12 Imported by: 0

README

fmgcli

Go client for FortiManager JSON-RPC APIs.

Features

  • User/password login flow and API key flow
  • Session-based request support
  • FortiManager object management helpers for:
    • Addresses
    • Services
    • Policies
    • Workspace lock/unlock and commit
  • Test suite based on httptest

Installation

go get github.com/rrpereira/fmgcli

Quick Start

User Login
package main

import (
    "log"

    "github.com/rrpereira/fmgcli"
)

func main() {
    client := fmgcli.NewUserClient("https://fortimanager.example.com", "my-user", "my-password")

    if err := client.Login(); err != nil {
        log.Fatal(err)
    }
    defer client.Logout()

    if err := client.CreateSubnetAddress("root", "host-10-0-0-1", "10.0.0.1", "255.255.255.255", "managed by fmgcli"); err != nil {
        log.Fatal(err)
    }
}
API Key
package main

import (
    "log"

    "github.com/rrpereira/fmgcli"
)

func main() {
    client := fmgcli.NewAPIClient("https://fortimanager.example.com", "my-api-key")

    if _, err := client.GetServiceByName("root", "HTTPS"); err != nil {
        log.Fatal(err)
    }
}

Compatibility

  • Requires Go 1.23+
  • Designed for FortiManager JSON-RPC endpoints (/jsonrpc)

Development

go test ./...
End-to-End Tests

The repository includes a full template at .env.example with every variable referenced by e2e tests.

cp .env.example .env
# Edit .env with values from your FortiManager environment
go test -tags=e2e ./...

Environment variables used by e2e tests:

  • FMG_E2E_HOST
  • FMG_E2E_USER
  • FMG_E2E_PASSWORD
  • FMG_E2E_TOKEN
  • FMG_E2E_ADOM
  • FMG_E2E_ADDRESS_NAME
  • FMG_E2E_ADDRESS_NAMES
  • FMG_E2E_ADDRESS_METAFIELD_KEY
  • FMG_E2E_ADDRESS_METAFIELD_VALUE
  • FMG_E2E_ADDRESS_METAFIELD_VALUES
  • FMG_E2E_ADDRESS_NAME_IP_NETMASK_NAME
  • FMG_E2E_ADDRESS_NAME_IP_NETMASK_IP
  • FMG_E2E_ADDRESS_NAME_IP_NETMASK_NETMASK
  • FMG_E2E_PKG
  • FMG_E2E_POLICY_ID
  • FMG_E2E_POLICY_METAFIELD_KEY
  • FMG_E2E_POLICY_METAFIELD_VALUE
  • FMG_E2E_POLICY_METAFIELD_VALUES
  • FMG_E2E_SERVICE_NAME
  • FMG_E2E_SERVICE_PROTOCOL
  • FMG_E2E_SERVICE_MIN_PORT
  • FMG_E2E_SERVICE_MAX_PORT
  • FMG_E2E_SERVICE_NAMES
  • FMG_E2E_SERVICE_METAFIELD_KEY
  • FMG_E2E_SERVICE_METAFIELD_VALUE
  • FMG_E2E_SERVICE_METAFIELD_VALUES
  • FMG_E2E_GROUP_METAFIELD_KEY

Versioning

This project follows semantic versioning.

License

This project is licensed under the MIT License. See LICENSE.

Disclaimer

Fortinet and FortiManager are trademarks of Fortinet, Inc. This project is an independent client and is not officially affiliated with Fortinet.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AddPolicyResp

type AddPolicyResp struct {
	Result []CreatePolicyResult `json:"result"`
}

type AddressGroupOptions added in v0.2.1

type AddressGroupOptions func(*AddressGroupReqData)

func WithAddressGroupMetafields added in v0.2.1

func WithAddressGroupMetafields(metafields map[string]interface{}) AddressGroupOptions

type AddressGroupReq added in v0.2.1

type AddressGroupReq struct {
	Method  string                  `json:"method"`
	Params  []AddressGroupReqParams `json:"params"`
	Session string                  `json:"session,omitempty" redact:"true"`
}

type AddressGroupReqData added in v0.2.1

type AddressGroupReqData struct {
	Name       string                 `json:"name"`
	Member     []string               `json:"member,omitempty"`
	Comment    string                 `json:"comment,omitempty"`
	Metafields map[string]interface{} `json:"meta fields,omitempty"`
}

type AddressGroupReqParams added in v0.2.1

type AddressGroupReqParams struct {
	Data []AddressGroupReqData `json:"data"`
	Url  string                `json:"url"`
}

type AddressGroupResp added in v0.2.1

type AddressGroupResp struct {
	Result []AddressGroupRespResult `json:"result"`
}

type AddressGroupRespData added in v0.2.1

type AddressGroupRespData struct {
	Name string `json:"name"`
}

type AddressGroupRespResult added in v0.2.1

type AddressGroupRespResult struct {
	Data   AddressGroupRespData `json:"data"`
	Status Status               `json:"status"`
	Url    string               `json:"url"`
}

type AddressOptions

type AddressOptions func(*SubnetAddressReqData)

func WithAddressMetafields

func WithAddressMetafields(metafields map[string]interface{}) AddressOptions

type Client

type Client struct {
	Host     string
	Key      string
	User     string
	Password string
	Session  string
	// contains filtered or unexported fields
}

func NewAPIClient

func NewAPIClient(host, key string, opts ...ClientOptions) *Client

func NewUserClient

func NewUserClient(host, user, password string, opts ...ClientOptions) *Client

func (*Client) Commit

func (fm *Client) Commit(adom string) error

func (*Client) CreateAddressGroup added in v0.2.1

func (fm *Client) CreateAddressGroup(adom, name string, members []string, comment string, opts ...AddressGroupOptions) error

func (*Client) CreatePolicy

func (fm *Client) CreatePolicy(pkg, adom, comment string, srcs, dsts, services []string, opts ...PolicyOptions) (int, error)

func (*Client) CreateService

func (fm *Client) CreateService(adom, name, protocol string, minPort, maxPort int, comment string, opts ...ServiceOptions) error

func (*Client) CreateSubnetAddress

func (fm *Client) CreateSubnetAddress(adom, name, subnet, netmask, comment string, opts ...AddressOptions) error

func (*Client) DeleteAddress added in v0.2.0

func (fm *Client) DeleteAddress(adom, addressName string) error

func (*Client) DeleteAddressGroup added in v0.2.1

func (fm *Client) DeleteAddressGroup(adom, groupName string) error

func (*Client) DeleteFromPolicy

func (fm *Client) DeleteFromPolicy(id int, objects []string, role, vdom, device, adom string) error

func (*Client) DeletePolicy added in v0.2.0

func (fm *Client) DeletePolicy(adom, pkg string, id int) error

func (*Client) DeleteService added in v0.2.0

func (fm *Client) DeleteService(adom, serviceName string) error

func (*Client) DisablePolicies

func (fm *Client) DisablePolicies(ids []int, vdom, device, adom string) error

func (*Client) DisablePolicy

func (fm *Client) DisablePolicy(adom, pkg string, id int) error

func (*Client) GetAddressByMetafield

func (fm *Client) GetAddressByMetafield(adom, key string, value interface{}) (*GetAddressData, error)

func (*Client) GetAddressByName

func (fm *Client) GetAddressByName(adom, objectName string) (*GetAddressData, error)

func (*Client) GetAddressByNameIPAndNetmask

func (fm *Client) GetAddressByNameIPAndNetmask(adom, objectName, ip, netmask string) (*GetAddressData, error)

func (*Client) GetAddressGroupByMetafield added in v0.2.1

func (fm *Client) GetAddressGroupByMetafield(adom, key string, value interface{}) (*GetAddressGroupData, error)

func (*Client) GetAddressGroupByName added in v0.2.1

func (fm *Client) GetAddressGroupByName(adom, groupName string) (*GetAddressGroupData, error)

func (*Client) GetAddressGroupsByMetafield added in v0.2.1

func (fm *Client) GetAddressGroupsByMetafield(adom, key string, values []interface{}) ([]GetAddressGroupData, error)

func (*Client) GetAddressGroupsByName added in v0.2.1

func (fm *Client) GetAddressGroupsByName(groupNames []string, adom string) ([]GetAddressGroupData, error)

func (*Client) GetAddressesByMetafield

func (fm *Client) GetAddressesByMetafield(adom, key string, values []interface{}) ([]GetAddressData, error)

func (*Client) GetAddressesByName

func (fm *Client) GetAddressesByName(objectNames []string, adom string) ([]GetAddressData, error)

func (*Client) GetObjectsByMetafield added in v0.2.2

func (fm *Client) GetObjectsByMetafield(adom, metafieldName string, metafieldValues []interface{}) (*ObjectsByMetafieldResult, error)

func (*Client) GetPoliciesByID

func (fm *Client) GetPoliciesByID(pkg, adom string, ids []int) ([]GetPolicyData, error)

func (*Client) GetPoliciesByMetafield

func (fm *Client) GetPoliciesByMetafield(adom, pkg, key string, values []interface{}) ([]GetPolicyData, error)

func (*Client) GetPolicyByMetafield

func (fm *Client) GetPolicyByMetafield(adom, pkg, key string, value interface{}) (*GetPolicyData, error)

func (*Client) GetServiceByMetafield

func (fm *Client) GetServiceByMetafield(adom, key string, value interface{}) (*GetServiceData, error)

func (*Client) GetServiceByNamePortAndProtocol

func (fm *Client) GetServiceByNamePortAndProtocol(adom, name, protocol string, minPort, maxPort int) (*GetServiceData, error)

func (*Client) GetServicesByMetafield

func (fm *Client) GetServicesByMetafield(adom, key string, values []interface{}) ([]GetServiceData, error)

func (*Client) GetServicesByName

func (fm *Client) GetServicesByName(serviceNames []string, adom string) ([]GetServiceData, error)

func (*Client) Lock

func (fm *Client) Lock(adom string) error

func (*Client) Login

func (fm *Client) Login() error

func (*Client) Logout

func (fm *Client) Logout() error

func (*Client) Unlock

func (fm *Client) Unlock(adom string) error

func (*Client) UpdateAddressGroupWithMetafields added in v0.2.1

func (fm *Client) UpdateAddressGroupWithMetafields(adom, name string, metafields map[string]interface{}) error

func (*Client) UpdateServiceWithMetafields

func (fm *Client) UpdateServiceWithMetafields(adom, name string, metafields map[string]interface{}) error

func (*Client) UpdateSubnetAddressWithMetafields

func (fm *Client) UpdateSubnetAddressWithMetafields(adom, name string, metafields map[string]interface{}) error

type ClientOptions

type ClientOptions func(*Client)

func WithLog

func WithLog(l *slog.Logger) ClientOptions

type CommitParams

type CommitParams struct {
	Url string `json:"url"`
}

type CommitReq

type CommitReq struct {
	Method  string         `json:"method"`
	Params  []CommitParams `json:"params"`
	Session string         `json:"session,omitempty" redact:"true"`
}

type CommitResp

type CommitResp struct {
	Result []Result `json:"result"`
}

type CreatePolicyParams

type CreatePolicyParams struct {
	Data CreatePolicyReqData `json:"data"`
	Url  string              `json:"url"`
}

type CreatePolicyReq

type CreatePolicyReq struct {
	Method  string               `json:"method"`
	Params  []CreatePolicyParams `json:"params"`
	Session string               `json:"session,omitempty" redact:"true"`
}

type CreatePolicyReqData

type CreatePolicyReqData struct {
	Action     string                 `json:"action"`
	Srcintf    []string               `json:"srcintf"`
	Dstinft    []string               `json:"dstintf"`
	Srcaddr    []string               `json:"srcaddr"`
	Dstaddr    []string               `json:"dstaddr"`
	Service    []string               `json:"service"`
	Status     string                 `json:"status"`
	Schedule   string                 `json:"schedule"`
	Logtraffic string                 `json:"logtraffic"`
	Metafields map[string]interface{} `json:"meta fields,omitempty"`
	Comments   string                 `json:"comments"`
}

type CreatePolicyRespData

type CreatePolicyRespData struct {
	PolicyID int `json:"policyid"`
}

type CreatePolicyResult

type CreatePolicyResult struct {
	Data   CreatePolicyRespData `json:"data"`
	Status Status               `json:"status"`
	Url    string               `json:"url"`
}

type DeleteFromParams added in v0.2.1

type DeleteFromParams struct {
	Data []string `json:"data"`
	Url  string   `json:"url"`
}

type DeleteFromReq added in v0.2.1

type DeleteFromReq struct {
	Method  string           `json:"method"`
	Params  DeleteFromParams `json:"params"`
	Session string           `json:"session,omitempty" redact:"true"`
}

type DeleteResourceReq added in v0.2.1

type DeleteResourceReq struct {
	Method  string     `json:"method"`
	Params  []UrlParam `json:"params"`
	Session string     `json:"session,omitempty" redact:"true"`
}

type DeleteResp

type DeleteResp struct {
	Result []Result `json:"result"`
}

type DisableParams

type DisableParams struct {
	Data DisableReqData `json:"data"`
	Url  string         `json:"url"`
}

type DisableReq

type DisableReq struct {
	Method  string          `json:"method"`
	Params  []DisableParams `json:"params"`
	Session string          `json:"session,omitempty" redact:"true"`
}

type DisableReqData

type DisableReqData struct {
	Status string `json:"status"`
}

type DisableResp

type DisableResp struct {
	Result []DisableResult `json:"result"`
}

type DisableRespData

type DisableRespData struct {
	PolicyID int `json:"policyid"`
}

type DisableResult

type DisableResult struct {
	Data   DisableRespData `json:"data"`
	Status Status          `json:"status"`
	Url    string          `json:"url"`
}

type GetAddressData

type GetAddressData struct {
	DynamicMapping interface{}            `json:"dynamic_mapping"`
	List           interface{}            `json:"list"`
	Metafields     map[string]interface{} `json:"meta fields"`
	Name           string                 `json:"name"`
	Oid            int                    `json:"oid"`
	Subnet         []string               `json:"subnet"`
	Tagging        interface{}            `json:"tagging"`
}

type GetAddressGroupData added in v0.2.1

type GetAddressGroupData struct {
	Name       string                 `json:"name"`
	Member     []string               `json:"member"`
	Metafields map[string]interface{} `json:"meta fields,omitempty"`
}

type GetAddressGroupResp added in v0.2.1

type GetAddressGroupResp struct {
	Result []GetAddressGroupResult `json:"result,omitempty"`
}

type GetAddressGroupResult added in v0.2.1

type GetAddressGroupResult struct {
	Data   GetAddressGroupData `json:"data,omitempty"`
	Status Status              `json:"status,omitempty"`
	Url    string              `json:"url,omitempty"`
}

type GetAddressGroupsParams added in v0.2.1

type GetAddressGroupsParams struct {
	Fields []string `json:"fields"`
	Option []string `json:"option,omitempty"`
	Url    string   `json:"url"`
}

type GetAddressGroupsReq added in v0.2.1

type GetAddressGroupsReq struct {
	Method  string                   `json:"method"`
	Params  []GetAddressGroupsParams `json:"params"`
	Session string                   `json:"session,omitempty" redact:"true"`
	Verbose int                      `json:"verbose,omitempty"`
}

type GetAddressGroupsResp added in v0.2.1

type GetAddressGroupsResp struct {
	Result []GetAddressGroupsResult `json:"result,omitempty"`
}

type GetAddressGroupsResult added in v0.2.1

type GetAddressGroupsResult struct {
	Data   []GetAddressGroupData `json:"data,omitempty"`
	Status Status                `json:"status,omitempty"`
	Url    string                `json:"url,omitempty"`
}

type GetAddressResp

type GetAddressResp struct {
	Result []GetAddressResult `json:"result,omitempty"`
}

type GetAddressResult

type GetAddressResult struct {
	Data   GetAddressData `json:"data,omitempty"`
	Status Status         `json:"status,omitempty"`
	Url    string         `json:"url,omitempty"`
}

type GetAddressesReq

type GetAddressesReq struct {
	Method  string             `json:"method"`
	Params  []GetObjectsParams `json:"params"`
	Session string             `json:"session,omitempty" redact:"true"`
	Verbose int                `json:"verbose,omitempty"`
}

type GetAddressesResp

type GetAddressesResp struct {
	Result []GetAddressesResult `json:"result,omitempty"`
}

type GetAddressesResult

type GetAddressesResult struct {
	Data   []GetAddressData `json:"data,omitempty"`
	Status Status           `json:"status,omitempty"`
	Url    string           `json:"url,omitempty"`
}

type GetObjectsParams added in v0.2.2

type GetObjectsParams struct {
	Fields []string `json:"fields"`
	Option []string `json:"option,omitempty"`
	Url    string   `json:"url"`
}

type GetObjectsReq added in v0.2.2

type GetObjectsReq struct {
	Method  string             `json:"method"`
	Params  []GetObjectsParams `json:"params"`
	Session string             `json:"session,omitempty" redact:"true"`
	Verbose int                `json:"verbose,omitempty"`
}

type GetObjectsResp added in v0.2.2

type GetObjectsResp struct {
	Result []GetObjectsResult `json:"result,omitempty"`
}

type GetObjectsResult added in v0.2.2

type GetObjectsResult struct {
	Data   json.RawMessage `json:"data,omitempty"`
	Status Status          `json:"status,omitempty"`
	Url    string          `json:"url,omitempty"`
}

type GetPoliciesParams

type GetPoliciesParams struct {
	Fields []string `json:"fields"`
	Option []string `json:"option"`
	Url    string   `json:"url"`
}

type GetPoliciesReq

type GetPoliciesReq struct {
	Method  string              `json:"method"`
	Params  []GetPoliciesParams `json:"params"`
	Session string              `json:"session,omitempty" redact:"true"`
	Verbose int                 `json:"verbose,omitempty"`
}

type GetPoliciesResp

type GetPoliciesResp struct {
	Result []GetPoliciesResult `json:"result"`
}

type GetPoliciesResult

type GetPoliciesResult struct {
	Data   []GetPolicyData `json:"data"`
	Status Status          `json:"status"`
	Url    string          `json:"url"`
}

type GetPolicyData

type GetPolicyData struct {
	Action  string   `json:"action"`
	Srcaddr []string `json:"srcaddr"`
	Dstaddr []string `json:"dstaddr"`
	Objseq  int      `json:"obj seq"`
	//Oid    int      `json:"oid"`
	PolicyID   int                    `json:"policyid"`
	Service    []string               `json:"service"`
	Status     string                 `json:"status"`
	Metafields map[string]interface{} `json:"meta fields"`
}

type GetPolicyResp

type GetPolicyResp struct {
	Result []GetPolicyResult `json:"result"`
}

type GetPolicyResult

type GetPolicyResult struct {
	Data   GetPolicyData `json:"data"`
	Status Status        `json:"status"`
	Url    string        `json:"url"`
}

type GetServiceData

type GetServiceData struct {
	Name         string                 `json:"name"`
	ObjSeq       int                    `json:"obj seq"`
	Oid          int                    `json:"oid"`
	Protocol     string                 `json:"protocol,omitempty"`
	TCPPortRange []string               `json:"tcp-portrange"`
	UDPPortRange []string               `json:"udp-portrange"`
	Metafields   map[string]interface{} `json:"meta fields,omitempty"`
}

type GetServiceResp

type GetServiceResp struct {
	Result []GetServiceResult `json:"result"`
}

type GetServiceResult

type GetServiceResult struct {
	Data   GetServiceData `json:"data"`
	Status Status         `json:"status"`
	Url    string         `json:"url"`
}

type GetServicesParams

type GetServicesParams struct {
	Fields []string `json:"fields"`
	Option []string `json:"option,omitempty"`
	Url    string   `json:"url"`
}

type GetServicesReq

type GetServicesReq struct {
	Method  string              `json:"method"`
	Params  []GetServicesParams `json:"params"`
	Session string              `json:"session,omitempty" redact:"true"`
	Verbose int                 `json:"verbose,omitempty"`
}

type GetServicesResp

type GetServicesResp struct {
	Result []GetServicesResult `json:"result,omitempty"`
}

type GetServicesResult

type GetServicesResult struct {
	Data   []GetServiceData `json:"data,omitempty"`
	Status Status           `json:"status,omitempty"`
	Url    string           `json:"url,omitempty"`
}

type LockReq

type LockReq struct {
	Method  string     `json:"method"`
	Params  []UrlParam `json:"params"`
	Session string     `json:"session,omitempty" redact:"true"`
}

type LockResp

type LockResp struct {
	Result []Result `json:"result"`
}

type LoginData

type LoginData struct {
	User     string `json:"user"`
	Password string `json:"password" redact:"true"`
}

type LoginParams

type LoginParams struct {
	Data LoginData `json:"data"`
	Url  string    `json:"url"`
}

type LoginRequest

type LoginRequest struct {
	Method string        `json:"method"`
	Params []LoginParams `json:"params"`
}

type LoginResp

type LoginResp struct {
	Result  []Result `json:"result"`
	Session string   `json:"session,omitempty" redact:"true"`
}

type LogoutParams

type LogoutParams struct {
	Url string `json:"url"`
}

type LogoutReq

type LogoutReq struct {
	Method  string         `json:"method"`
	Params  []LogoutParams `json:"params"`
	Session string         `json:"session,omitempty" redact:"true"`
}

type LogoutResp

type LogoutResp struct {
	Result  []Result `json:"result"`
	Session string   `json:"session,omitempty" redact:"true"`
}

type ObjectsByMetafieldResult added in v0.2.2

type ObjectsByMetafieldResult struct {
	AddrGrp []GetAddressGroupData
	Address []GetAddressData
	Service []GetServiceData
}

type PolicyOptions

type PolicyOptions func(*CreatePolicyReqData)

func WithMetafields

func WithMetafields(metafields map[string]interface{}) PolicyOptions

type Result

type Result struct {
	Status Status `json:"status"`
	Url    string `json:"url"`
}

type ServiceOptions

type ServiceOptions func(*ServiceReqData)

func WithServiceMetafields

func WithServiceMetafields(metafields map[string]interface{}) ServiceOptions

type ServiceReq

type ServiceReq struct {
	Method  string             `json:"method"`
	Params  []ServiceReqParams `json:"params"`
	Session string             `json:"session,omitempty" redact:"true"`
}

type ServiceReqData

type ServiceReqData struct {
	Name         string                 `json:"name"`
	Protocol     string                 `json:"protocol,omitempty"`
	TCPPortRange []string               `json:"tcp-portrange,omitempty"`
	UDPPortRange []string               `json:"udp-portrange,omitempty"`
	Comment      string                 `json:"comment,omitempty"`
	Metafields   map[string]interface{} `json:"meta fields,omitempty"`
}

type ServiceReqParams

type ServiceReqParams struct {
	Data []ServiceReqData `json:"data"`
	Url  string           `json:"url"`
}

type ServiceResp

type ServiceResp struct {
	Result []ServiceRespResult `json:"result"`
}

type ServiceRespData

type ServiceRespData struct {
	Name string `json:"name"`
}

type ServiceRespResult

type ServiceRespResult struct {
	Data   ServiceRespData `json:"data"`
	Status Status          `json:"status"`
	Url    string          `json:"url"`
}

type Status

type Status struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
}

type SubnetAddressReq

type SubnetAddressReq struct {
	Method  string                   `json:"method"`
	Params  []SubnetAddressReqParams `json:"params"`
	Session string                   `json:"session,omitempty" redact:"true"`
}

type SubnetAddressReqData

type SubnetAddressReqData struct {
	Name       string                 `json:"name"`
	Type       string                 `json:"type,omitempty"`
	Subnet     string                 `json:"subnet,omitempty"`
	Comment    string                 `json:"comment,omitempty"`
	Metafields map[string]interface{} `json:"meta fields,omitempty"`
}

type SubnetAddressReqParams

type SubnetAddressReqParams struct {
	Data []SubnetAddressReqData `json:"data"`
	Url  string                 `json:"url"`
}

type SubnetAddressResp

type SubnetAddressResp struct {
	Result []SubnetAddressRespResult `json:"result"`
}

type SubnetAddressRespData

type SubnetAddressRespData struct {
	Name string `json:"name"`
}

type SubnetAddressRespResult

type SubnetAddressRespResult struct {
	Status Status                `json:"status"`
	Url    string                `json:"url"`
	Data   SubnetAddressRespData `json:"data"`
}

type UnlockParams

type UnlockParams struct {
	Url string `json:"url"`
}

type UnlockReq

type UnlockReq struct {
	Method  string         `json:"method"`
	Params  []UnlockParams `json:"params"`
	Session string         `json:"session,omitempty" redact:"true"`
}

type UnlockResp

type UnlockResp struct {
	Result []Result `json:"result"`
}

type UrlParam

type UrlParam struct {
	Url string `json:"url"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL