sftp

package
v0.21.0 Latest Latest
Warning

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

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

README ΒΆ

Contributions Welcome Release

SFTP Package

The SFTP package provides a SFTP client with connection pooling, flexible authentication, and advanced file transfer capabilities. Built for reliability and ease of use, it simplifies secure file operations in distributed systems.

Features

  • Unified SFTP Client Interface
    • Complete file operations: Upload, Download, List, Mkdir, Remove, Rename, Stat
    • Context-aware operations with cancellation support
  • Connection Pooling
    • Efficient connection reuse with automatic management
    • Configurable pool size and idle timeout
    • Health checks and automatic cleanup
    • Thread-safe concurrent access
  • Flexible Authentication
    • Password authentication
    • Private key authentication (file or in-memory)
    • Passphrase-protected private keys
    • Extensible authentication handlers
  • Advanced File Transfer
    • Configurable buffer size for optimal performance
    • Real-time progress callbacks
    • Smart overwrite policies (always, never, if newer, if different size)
    • Automatic directory creation
    • Permission preservation
  • Reliability & Retry
    • Built-in retry mechanism with exponential backoff
    • Configurable retry policies
    • Connection health monitoring
    • Graceful error handling

Installation

go get github.com/kittipat1413/go-common/framework/sftp

Documentation

Go Reference

For detailed API documentation, examples, and usage patterns, visit the Go Package Documentation.

Usage

Client Interface

The core of the package is the Client interface:

type Client interface {
    Connect(ctx context.Context) error
    Close() error
    
    Upload(ctx context.Context, localPath, remotePath string, opts ...UploadOption) error
    Download(ctx context.Context, remotePath, localPath string, opts ...DownloadOption) error
    List(ctx context.Context, remotePath string) ([]os.FileInfo, error)
    Mkdir(ctx context.Context, remotePath string) error
    Remove(ctx context.Context, remotePath string) error
    Rename(ctx context.Context, oldPath, newPath string) error
    Stat(ctx context.Context, remotePath string) (os.FileInfo, error)
}
πŸš€ Quick Start
Creating an SFTP Client

Password Authentication:

import (
    "context"
    "github.com/kittipat1413/go-common/framework/sftp"
)

func main() {
    config := sftp.Config{
        Authentication: sftp.AuthConfig{
            Host:     "sftp.example.com",
            Port:     22,
            Username: "myuser",
            Method:   sftp.AuthPassword,
            Password: "mypassword",
        },
    }

    client, err := sftp.NewClient(config)
    if err != nil {
        log.Fatalf("Failed to create SFTP client: %v", err)
    }
    defer client.Close()

    // Test connection
    if err := client.Connect(context.Background()); err != nil {
        log.Fatalf("Failed to connect: %v", err)
    }
}

Private Key Authentication:

config := sftp.Config{
    Authentication: sftp.AuthConfig{
        Host:           "sftp.example.com",
        Port:           22,
        Username:       "myuser",
        Method:         sftp.AuthPrivateKey,
        PrivateKeyPath: "/path/to/private/key",
        // Or use in-memory key data:
        // PrivateKeyData: []byte("-----BEGIN RSA PRIVATE KEY-----\n..."),
    },
}

client, err := sftp.NewClient(config)
πŸ“€ Uploading Files

Basic Upload:

ctx := context.Background()
err := client.Upload(ctx, "local/file.txt", "/remote/file.txt")
if err != nil {
    log.Fatalf("Upload failed: %v", err)
}

Upload with Options:

err := client.Upload(ctx, "local/report.pdf", "/reports/2024/report.pdf",
    sftp.WithUploadCreateDirs(true),           // Create parent directories
    sftp.WithUploadPreservePermissions(true),  // Preserve file permissions
    sftp.WithUploadOverwriteIfNewer(),         // Only overwrite if newer
    sftp.WithUploadProgress(func(info sftp.ProgressInfo) {
        progress := float64(info.BytesTransferred) / float64(info.TotalBytes) * 100
        fmt.Printf("Upload progress: %.2f%%\n", progress)
    }),
)
πŸ“₯ Downloading Files

Basic Download:

err := client.Download(ctx, "/remote/file.txt", "local/file.txt")
if err != nil {
    log.Fatalf("Download failed: %v", err)
}

Download with Options:

err := client.Download(ctx, "/remote/large-file.zip", "local/large-file.zip",
    sftp.WithDownloadCreateDirs(true),
    sftp.WithDownloadPreservePermissions(true),
    sftp.WithDownloadOverwriteIfNewerOrDifferentSize(),
    sftp.WithDownloadProgress(func(info sftp.ProgressInfo) {
        fmt.Printf("Downloaded %d/%d bytes\n", info.BytesTransferred, info.TotalBytes)
    }),
)
πŸ“ Directory Operations
// Create directory (with parents)
err := client.Mkdir(ctx, "/remote/path/to/new/dir")

// List directory contents
files, err := client.List(ctx, "/remote/path")
for _, file := range files {
    fmt.Printf("%s - %d bytes\n", file.Name(), file.Size())
}

// Remove file or directory (recursive)
err := client.Remove(ctx, "/remote/path/to/file")

// Rename or move file
err := client.Rename(ctx, "/old/path", "/new/path")

// Get file info
info, err := client.Stat(ctx, "/remote/file.txt")
fmt.Printf("Size: %d, Modified: %v\n", info.Size(), info.ModTime())

Configuration

SFTP client behavior can be customized via the Config struct:

config := sftp.Config{
    Authentication: sftp.AuthConfig{
        Host:            "sftp.example.com",
        Port:            22,
        Username:        "myuser",
        Method:          sftp.AuthPrivateKey,
        PrivateKeyPath:  "/path/to/key",
        HostKeyCallback: ssh.InsecureIgnoreHostKey(),
    },
    Connection: sftp.ConnectionConfig{
        Timeout:        30 * time.Second,
        MaxConnections: 10,
        IdleTimeout:    5 * time.Minute,
        RetryPolicy: retry.Config{
            MaxAttempts: 3,
            Backoff: &retry.ExponentialBackoff{
                BaseDelay: 1 * time.Second,
                Factor:    2.0,
                MaxDelay:  30 * time.Second,
            },
        },
    },
    Transfer: sftp.TransferConfig{
        BufferSize:          32 * 1024, // 32KB
        CreateDirs:          true,
        PreservePermissions: false,
    },
}
Configuration Options
AuthConfig
Field Type Description Default
Host string SFTP server hostname or IP Required
Port int SFTP server port 22
Username string Authentication username Required
Method AuthMethod Auth method (AuthPassword or AuthPrivateKey) Required
Password string Password (for AuthPassword) -
PrivateKeyPath string Path to private key file -
PrivateKeyData []byte Private key data (in-memory) -
HostKeyCallback ssh.HostKeyCallback Server verification callback Insecure (accept all)
ConnectionConfig
Field Type Description Default
Timeout time.Duration Connection timeout 30s
MaxConnections int Max connections in pool 10
IdleTimeout time.Duration Idle connection timeout 5m
RetryPolicy retry.Config Retry configuration Exponential backoff
TransferConfig
Field Type Description Default
BufferSize int Transfer buffer size (bytes) 32768 (32KB)
CreateDirs bool Auto-create directories false
PreservePermissions bool Preserve file permissions false
ProgressCallback ProgressCallback Progress reporting function nil
Overwrite Policies

Control how the client handles existing files:

  • OverwriteAlways - Always overwrite existing files (default)
  • OverwriteNever - Never overwrite, return error if exists
  • OverwriteIfNewer - Overwrite only if source is newer
  • OverwriteIfDifferentSize - Overwrite only if sizes differ
  • OverwriteIfNewerOrDifferentSize - Overwrite if newer OR different size
// Upload only if local file is newer
client.Upload(ctx, "local.txt", "remote.txt", 
    sftp.WithUploadOverwriteIfNewer())

// Download only if remote file is newer
client.Download(ctx, "remote.txt", "local.txt",
    sftp.WithDownloadOverwriteIfNewer())
Connection Pool Management

Connections are automatically managed The pool will:

  • Reuse existing connections when available
  • Create new connections up to MaxConnections limit
  • Automatically close idle connections after IdleTimeout
  • Perform health checks before returning connections

// Manually close all connections (e.g., during shutdown)
defer client.Close()

Error Handling

Common Errors
  • ErrConfiguration – Invalid configuration
  • ErrAuthentication – Authentication failure
  • ErrConnection – Connection or network issues
  • ErrConnectionPoolFull – No available connections in the pool
  • ErrConnectionPoolClosed – Connection pool is closed
  • ErrFileNotFound – File does not exist, either remotely or locally
  • ErrDataTransfer – Errors during data transfer, including overwrite policy violations

Example

You can find a complete working example in the repository under framework/sftp/example.

Documentation ΒΆ

Index ΒΆ

Constants ΒΆ

This section is empty.

Variables ΒΆ

View Source
var (
	ErrConnection         = errors.New("connection error")
	ErrConnectionPoolFull = errors.New("connection pool full")
	ErrConnectionClosed   = errors.New("connection closed")
	ErrConnectionNotFound = errors.New("connection not found")
)

Error definitions for SFTP connection management

View Source
var (
	ErrFileNotFound = errors.New("file not found")
	ErrDataTransfer = errors.New("data transfer error")
)

Error definitions for file operations

View Source
var (
	ErrAuthentication = errors.New("authentication error")
)

Error definitions for authentication issues

View Source
var (
	ErrConfiguration = errors.New("configuration error")
)

Error definitions for configuration issues

Functions ΒΆ

This section is empty.

Types ΒΆ

type AuthConfig ΒΆ

type AuthConfig struct {
	Host     string // SFTP server hostname or IP address
	Port     int    // SFTP server port number
	Username string // Username for authentication

	// Method specifies the authentication method to use
	Method AuthMethod // Authentication method (AuthPassword or AuthPrivateKey)
	// AuthPassword
	Password string // Password for AuthPassword method
	// AuthPrivateKey
	PrivateKeyPath string // Path to private key file for AuthPrivateKey method
	PrivateKeyData []byte // Private key data for AuthPrivateKey method

	// HostKeyCallback is used to verify the server's host key
	HostKeyCallback ssh.HostKeyCallback // Host key callback for server verification
}

AuthConfig contains authentication-related configuration

type AuthMethod ΒΆ

type AuthMethod int

AuthMethod defines the type of authentication to use

const (
	AuthPassword AuthMethod = iota
	AuthPrivateKey
)

type AuthenticationHandler ΒΆ

type AuthenticationHandler interface {
	GetAuthMethods() ([]ssh.AuthMethod, error)
	ValidateCredentials() error
}

AuthenticationHandler manages different authentication methods

func CreateAuthHandler ΒΆ

func CreateAuthHandler(authConfig AuthConfig) (AuthenticationHandler, error)

CreateAuthHandler creates an appropriate authentication handler based on the auth config

type Client ΒΆ

type Client interface {
	// Connect validates connectivity to the SFTP server by borrowing a connection from the connection manager and releasing it back
	// It does not keep a persistent connection open
	Connect(ctx context.Context) error
	// Upload uploads a local file to the remote SFTP server
	Upload(ctx context.Context, localPath, remotePath string, opts ...UploadOption) error
	// Download downloads a remote file from the SFTP server to local storage
	Download(ctx context.Context, remotePath, localPath string, opts ...DownloadOption) error
	// List lists files and directories in the specified remote path
	List(ctx context.Context, remotePath string) ([]os.FileInfo, error)
	// Mkdir creates a directory and all necessary parent directories on the remote SFTP server
	Mkdir(ctx context.Context, remotePath string) error
	// Remove removes a file or directory and all its contents from the remote SFTP server
	Remove(ctx context.Context, remotePath string) error
	// Rename renames or moves a file or directory on the remote SFTP server
	Rename(ctx context.Context, oldPath, newPath string) error
	// Stat returns information about a file or directory on the remote SFTP server
	Stat(ctx context.Context, remotePath string) (os.FileInfo, error)
	// Close forcefully closes all connections in the SFTP connection pool, including connections currently in use.
	// This method is intended to be called during application shutdown
	Close() error
}

Client is the main interface for SFTP operations

func NewClient ΒΆ

func NewClient(config Config) (Client, error)

NewClient creates a new SFTP client with the given configuration

func NewClientWithDependencies ΒΆ

func NewClientWithDependencies(authHandler AuthenticationHandler, connectionManager ConnectionManager, transferConfig TransferConfig) (Client, error)

NewClientWithDependencies creates a new SFTP client with injected dependencies This constructor is useful for testing or when you need more control over the ConnectionManager and AuthenticationHandler implementations

type Config ΒΆ

type Config struct {
	Authentication AuthConfig       // Authentication-related configuration
	Connection     ConnectionConfig // Connection-related configuration
	Transfer       TransferConfig   // File transfer-related configuration
}

Config contains all configuration options for the SFTP client

func DefaultConfig ΒΆ

func DefaultConfig() Config

DefaultConfig returns a configuration with sensible defaults

func MergeConfig ΒΆ

func MergeConfig(userConfig Config) Config

MergeConfig merges user configuration with defaults

type ConnectionConfig ΒΆ

type ConnectionConfig struct {
	Timeout        time.Duration // Connection timeout duration
	MaxConnections int           // Maximum number of simultaneous connections in the pool
	IdleTimeout    time.Duration // Idle connection timeout duration
	RetryPolicy    retry.Config  // Retry policy for connection attempts
}

ConnectionConfig contains connection-related configuration

type ConnectionManager ΒΆ

type ConnectionManager interface {
	GetConnection(ctx context.Context) (*sftp.Client, error)
	ReleaseConnection(client *sftp.Client) error
	Close() error
}

ConnectionManager handles SSH/SFTP connection lifecycle

func NewConnectionManager ΒΆ

func NewConnectionManager(authHandler AuthenticationHandler, authConfig AuthConfig, connectionConfig ConnectionConfig) (ConnectionManager, error)

NewConnectionManager creates a new connection manager with pooling support

type DownloadConfig ΒΆ

type DownloadConfig struct {
	// CreateDirs controls whether Download should create local parent directories
	CreateDirs bool
	// PreservePermissions controls whether Download should attempt to copy the remote
	// file mode to the local file after transfer
	PreservePermissions bool
	// ProgressCallback, if set, is invoked as bytes are transferred
	ProgressCallback ProgressCallback
	// OverwritePolicy controls how Download behaves if the local path already exists
	OverwritePolicy OverwritePolicy
}

DownloadConfig configures how Download behaves

type DownloadOption ΒΆ

type DownloadOption func(*DownloadConfig)

DownloadOption defines options for download operations

func WithDownloadCreateDirs ΒΆ

func WithDownloadCreateDirs(create bool) DownloadOption

WithDownloadCreateDirs sets whether to create directories during download

func WithDownloadOverwriteAlways ΒΆ

func WithDownloadOverwriteAlways() DownloadOption

WithDownloadOverwriteAlways sets download to always overwrite existing files

func WithDownloadOverwriteIfDifferentSize ΒΆ

func WithDownloadOverwriteIfDifferentSize() DownloadOption

WithDownloadOverwriteIfDifferentSize sets download to overwrite only if file sizes differ

func WithDownloadOverwriteIfNewer ΒΆ

func WithDownloadOverwriteIfNewer() DownloadOption

WithDownloadOverwriteIfNewer sets download to overwrite only if remote file is newer

func WithDownloadOverwriteIfNewerOrDifferentSize ΒΆ

func WithDownloadOverwriteIfNewerOrDifferentSize() DownloadOption

WithDownloadOverwriteIfNewerOrDifferentSize sets download to overwrite if newer or different size

func WithDownloadOverwriteNever ΒΆ

func WithDownloadOverwriteNever() DownloadOption

WithDownloadOverwriteNever sets download to never overwrite existing files

func WithDownloadOverwritePolicy ΒΆ

func WithDownloadOverwritePolicy(policy OverwritePolicy) DownloadOption

WithDownloadOverwritePolicy sets the overwrite policy for download operations

func WithDownloadPreservePermissions ΒΆ

func WithDownloadPreservePermissions(preserve bool) DownloadOption

WithDownloadPreservePermissions sets whether to preserve file permissions during download

func WithDownloadProgress ΒΆ

func WithDownloadProgress(callback ProgressCallback) DownloadOption

WithDownloadProgress sets a progress callback for download operations

type OverwritePolicy ΒΆ

type OverwritePolicy int

OverwritePolicy defines how to handle existing files

const (
	OverwriteAlways OverwritePolicy = iota
	OverwriteNever
	OverwriteIfNewer
	OverwriteIfDifferentSize
	OverwriteIfNewerOrDifferentSize
)

type PasswordAuthHandler ΒΆ

type PasswordAuthHandler struct {
	// contains filtered or unexported fields
}

PasswordAuthHandler handles password-based authentication

func NewPasswordAuthHandler ΒΆ

func NewPasswordAuthHandler(username, password string) *PasswordAuthHandler

NewPasswordAuthHandler creates a new password authentication handler

func (*PasswordAuthHandler) GetAuthMethods ΒΆ

func (p *PasswordAuthHandler) GetAuthMethods() ([]ssh.AuthMethod, error)

GetAuthMethods returns SSH authentication methods for password auth

func (*PasswordAuthHandler) ValidateCredentials ΒΆ

func (p *PasswordAuthHandler) ValidateCredentials() error

ValidateCredentials validates password authentication credentials

type PrivateKeyAuthHandler ΒΆ

type PrivateKeyAuthHandler struct {
	// contains filtered or unexported fields
}

PrivateKeyAuthHandler handles SSH private key authentication

func NewPrivateKeyAuthHandler ΒΆ

func NewPrivateKeyAuthHandler(username, privateKeyPath string, passphrase string) *PrivateKeyAuthHandler

NewPrivateKeyAuthHandler creates a new private key authentication handler

func NewPrivateKeyAuthHandlerWithData ΒΆ

func NewPrivateKeyAuthHandlerWithData(username string, privateKeyData []byte, passphrase string) *PrivateKeyAuthHandler

NewPrivateKeyAuthHandlerWithData creates a new private key authentication handler with key data

func (*PrivateKeyAuthHandler) GetAuthMethods ΒΆ

func (k *PrivateKeyAuthHandler) GetAuthMethods() ([]ssh.AuthMethod, error)

GetAuthMethods returns SSH authentication methods for private key auth

func (*PrivateKeyAuthHandler) ValidateCredentials ΒΆ

func (k *PrivateKeyAuthHandler) ValidateCredentials() error

ValidateCredentials validates private key authentication credentials

type ProgressCallback ΒΆ

type ProgressCallback func(info ProgressInfo)

ProgressCallback is called during file transfers to report progress

type ProgressInfo ΒΆ

type ProgressInfo struct {
	BytesTransferred int64
	TotalBytes       int64
	Percentage       float64
	Speed            int64 // bytes per second
}

ProgressInfo contains information about transfer progress

type TransferConfig ΒΆ

type TransferConfig struct {
	BufferSize          int              // Size of the buffer used during file transfers (in bytes)
	CreateDirs          bool             // Whether to create missing directories during file uploads
	PreservePermissions bool             // Whether to preserve file permissions during transfers
	ProgressCallback    ProgressCallback // Optional callback for reporting progress during file transfers
}

TransferConfig contains file transfer-related configuration

type UploadConfig ΒΆ

type UploadConfig struct {
	// CreateDirs controls whether Upload should create remote parent directories
	CreateDirs bool
	// PreservePermissions controls whether Upload should attempt to copy local file mode
	// to the remote file after transfer
	PreservePermissions bool
	// ProgressCallback, if set, is invoked as bytes are transferred
	ProgressCallback ProgressCallback
	// OverwritePolicy controls how Upload behaves if the remote path already exists
	OverwritePolicy OverwritePolicy
}

UploadConfig configures how Upload behaves

type UploadOption ΒΆ

type UploadOption func(*UploadConfig)

UploadOption defines options for upload operations

func WithUploadCreateDirs ΒΆ

func WithUploadCreateDirs(create bool) UploadOption

WithUploadCreateDirs sets whether to create directories during upload

func WithUploadOverwriteAlways ΒΆ

func WithUploadOverwriteAlways() UploadOption

WithUploadOverwriteAlways sets upload to always overwrite existing files

func WithUploadOverwriteIfDifferentSize ΒΆ

func WithUploadOverwriteIfDifferentSize() UploadOption

WithUploadOverwriteIfDifferentSize sets upload to overwrite only if file sizes differ

func WithUploadOverwriteIfNewer ΒΆ

func WithUploadOverwriteIfNewer() UploadOption

WithUploadOverwriteIfNewer sets upload to overwrite only if local file is newer

func WithUploadOverwriteIfNewerOrDifferentSize ΒΆ

func WithUploadOverwriteIfNewerOrDifferentSize() UploadOption

WithUploadOverwriteIfNewerOrDifferentSize sets upload to overwrite if newer or different size

func WithUploadOverwriteNever ΒΆ

func WithUploadOverwriteNever() UploadOption

WithUploadOverwriteNever sets upload to never overwrite existing files

func WithUploadOverwritePolicy ΒΆ

func WithUploadOverwritePolicy(policy OverwritePolicy) UploadOption

WithUploadOverwritePolicy sets the overwrite policy for upload operations

func WithUploadPreservePermissions ΒΆ

func WithUploadPreservePermissions(preserve bool) UploadOption

WithUploadPreservePermissions sets whether to preserve file permissions during upload

func WithUploadProgress ΒΆ

func WithUploadProgress(callback ProgressCallback) UploadOption

WithUploadProgress sets a progress callback for upload operations

Directories ΒΆ

Path Synopsis
Package sftp_mocks is a generated GoMock package.
Package sftp_mocks is a generated GoMock package.

Jump to

Keyboard shortcuts

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