### Example usage and output Source: https://github.com/dutchcoders/transfer.sh/blob/main/examples.md Example invocation of transfer with the w parameter to copy the Windows download command. Shows the progress bar and the printed download link and commands. ```sh $ transfer ~/temp/a.log w ######################################################################## 100.0% 1) Download link: https://transfer.sh/y0qr2c/a.log 2) Linux or macOS download command: wget https://transfer.sh/y0qr2c/a.log 3) Windows download command: Invoke-WebRequest -Uri https://transfer.sh/y0qr2c/a.log -OutFile a.log ``` -------------------------------- ### Example usage of NewLocalStorage Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/api-reference/local-storage.md Example usage of NewLocalStorage to create a store and wire it into the server. The basedir is "/data/transfersh" and the server listens on port 8080. ```go store, err := storage.NewLocalStorage("/data/transfersh", logger) if err != nil { log.Fatal(err) } // wire into the server: srvr, err := server.New(server.Listener(":8080"), server.UseStorage(store)) ``` -------------------------------- ### Run local backend with go run Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/api-reference/cmd.md Starts a local-file backend on port 8080. The output shows the server startup messages, including the temp folder and storage provider. ```bash $ go run main.go --provider=local --listener :8080 --temp-path=/tmp/ --basedir=/tmp/ Transfer.sh server started. using temp folder: /tmp/ using storage provider: local ``` -------------------------------- ### Server startup in app.Action Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/api-reference/cmd.md Starts the server using server.New with translated options. On error, logs a red error message and returns the error; otherwise runs the server and returns nil. ```go srvr, err := server.New(options...) if err != nil { logger.Println(color.RedString("Error starting server: %s", err.Error())) return err } srvr.Run() return nil ``` -------------------------------- ### Storj provider startup with environment variables Source: https://github.com/dutchcoders/transfer.sh/blob/main/README.md Sets the Storj bucket name and access grant as environment variables, then starts transfer.sh with the Storj provider. Recommended for enhanced security. ```bash export STORJ_BUCKET= export STORJ_ACCESS= transfer.sh --provider storj ``` -------------------------------- ### Install transfer.sh Helm chart Source: https://github.com/dutchcoders/transfer.sh/blob/main/k8s/transfer.sh/README.md Use this command to install the transfer.sh Helm chart from the current directory. The chart is named 'transfer-sh' and uses the local chart directory './transfer.sh'. ```bash helm install transfer-sh ./transfer.sh ``` -------------------------------- ### Run S3 provider with Minio-style path addressing Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/api-reference/cmd.md Starts the server with an S3 provider using Minio-style path addressing and legacy credential pair. Requires the s3-endpoint, s3-path-style, s3-region, bucket, and AWS credentials. ```bash $ transfersh --provider=s3 --listener :8080 \ --s3-endpoint=http://minio:9000 --s3-path-style --s3-region=us-east-1 \ --bucket=shares --aws-access-key=AKIA... --aws-secret-key=... ``` -------------------------------- ### Run transfer.sh locally with Go Source: https://github.com/dutchcoders/transfer.sh/blob/main/README.md Starts the transfer.sh server using the local provider on port 8080, with temporary and base directories set. Requires Go and GO111MODULE enabled. ```bash go run main.go --provider=local --listener :8080 --temp-path=/tmp/ --basedir=/tmp/ ``` -------------------------------- ### New() factory for CLI application Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/api-reference/cmd.md Creates and configures the CLI application with name, usage, version, flags, help template, and the version command. The Action function translates flags to server options and starts the server. ```go // New is the factory for transfer.sh func New() *Cmd { logger := log.New(os.Stdout, "[transfer.sh]", log.LstdFlags) app := cli.NewApp() app.Name = "transfer.sh" app.Authors = []*cli.Author{} app.Usage = "transfer.sh" app.Description = `Easy file sharing from the command line` app.Version = Version app.Flags = globalFlags app.CustomAppHelpTemplate = helpTemplate app.Commands = []*cli.Command{ { Name: "version", Action: versionCommand } } app.Before = func(c *cli.Context) error { return nil } app.Action = func(c *cli.Context) error { ... } return &Cmd{ App: app } } ``` -------------------------------- ### Composing options and running the server Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/api-reference/server.md Shows how to create a Server with various options including listener, temp path, max upload size, random token length, purge, HTTP auth credentials, and a local storage backend. The example imports the server and storage packages, creates a local storage, and runs the server. ```go import "github.com/dutchcoders/transfer.sh/server" import "github.com/dutchcoders/transfer.sh/server/storage" logger := log.New(os.Stdout, "[transfer.sh]", log.LstdFlags) store, err := storage.NewLocalStorage("/data/transfersh", logger) if err != nil { log.Fatal(err) } srvr, err := server.New( server.Listener(":8080"), server.TempPath("/tmp/"), server.MaxUploadSize(1024 * 1024), // 1 GiB in KB server.RandomTokenLength(10), server.Purge(30, 24), server.HTTPAuthCredentials("admin", "secret"), server.UseStorage(store), ) if err != nil { log.Fatal(err) } srvr.Run() ``` -------------------------------- ### Use transfer function to upload hello.txt Source: https://github.com/dutchcoders/transfer.sh/blob/main/README.md Example invocation of the transfer function defined above. Uploads the file hello.txt to transfer.sh and prints the resulting URL. ```bash $ transfer hello.txt ``` -------------------------------- ### Run transfer.sh with GDrive provider Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/api-reference/gdrive-storage.md Starts transfer.sh with the GDrive provider. First run prints a browser URL and prompts for the authorization code on stdin; subsequent runs reuse token.json. ```bash $ transfersh --provider=gdrive --listener :8080 \ --gdrive-client-json-filepath=/etc/transfersh/client_secret.json \ --gdrive-local-config-path=/var/lib/transfersh \ --basedir=transfersh --gdrive-chunk-size=8 ``` -------------------------------- ### Run transfer.sh with Google Drive provider Source: https://github.com/dutchcoders/transfer.sh/blob/main/README.md Starts transfer.sh using Google Drive as the storage provider. Requires the provider, gdrive-client-json-filepath, gdrive-local-config-path, and basedir options. The gdrive-client-json-filepath should point to a downloaded OAuth client JSON file, and gdrive-local-config-path is where the config will be saved. ```bash go run main.go --provider gdrive --basedir /tmp/ --gdrive-client-json-filepath /[credential_dir] --gdrive-local-config-path [directory_to_save_config] ``` -------------------------------- ### GET / Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/endpoints.md Serves the index page. Returns HTML if the client accepts text/html, otherwise plain text. Provides template variables for customization. ```APIDOC ## GET / ### Description Serves the index page. Returns HTML if the client accepts text/html, otherwise plain text. Provides template variables for customization. ### Method GET ### Endpoint / ### Response #### Success Response (200) - **body** (text/html or text/plain) - Rendered index page. - **Vary** (string) - Set to `Accept`. #### Response Example [HTML or plain text content of index page] ``` -------------------------------- ### Run transfer.sh with Storj provider Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/api-reference/storj-storage.md Starts transfer.sh with the Storj provider, binding to port 8080. Requires an access grant string and a bucket name; --purge-days=7 sets the retention period. ```bash $ transfersh --provider=storj --listener :8080 \ --storj-access="" \ --storj-bucket=transfersh --purge-days=7 ``` -------------------------------- ### Run transfer.sh with S3 provider and MinIO endpoint Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/api-reference/s3-storage.md Starts transfer.sh with the S3 provider, using legacy credentials, a custom MinIO endpoint, path-style addressing, and a 30-day purge. Requires the AWS access key, secret key, bucket, and region to be set. ```bash $ transfersh --provider=s3 --listener :8080 \ --s3-credentials-type=legacy \ --aws-access-key=KEY --aws-secret-key=SECRET \ --bucket=files --s3-region=us-east-1 \ --s3-endpoint=https://minio.example.com --s3-path-style \ --purge-days=30 ``` -------------------------------- ### LocalStorage.Get method implementation Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/api-reference/local-storage.md Opens a file for reading, optionally seeking to a range start. Returns the file reader, content length (possibly reduced by the range), and any error. The range's contentRange field is set only if accepted; unsatisfiable ranges still seek and return full size. ```go func (s *LocalStorage) Get(_ context.Context, token string, filename string, rng *Range) (reader io.ReadCloser, contentLength uint64, err error) { path := filepath.Join(s.basedir, token, filename) var file *os.File if file, err = os.Open(path); err != nil { return } if fi, err := file.Stat(); err != nil { return } else { contentLength = uint64(fi.Size()) } if rng != nil { contentLength = rng.AcceptLength(contentLength) if _, err = file.Seek(int64(rng.Start), 0); err != nil { return } } reader = file return } ``` -------------------------------- ### Handle storage errors with IsNotExist Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/errors.md Shows how to handle errors from the storage API. The first call to NewLocalStorage may not fail immediately; basedir problems surface later on first Put. The Get call returns a reader and contentLength; use store.IsNotExist to detect the 404 path, otherwise treat as generic failure. Close the reader with storage.CloseCheck. ```go store, err := storage.NewLocalStorage("/tmp/transfersh", logger) if err != nil { // startup failure, e.g. basedir problems surface later on first Put } reader, contentLength, err := store.Get(ctx, token, filename, nil) defer storage.CloseCheck(reader) if store.IsNotExist(err) { // 404 path — file truly missing } else if err != nil { // generic failure } ``` -------------------------------- ### Server struct definition Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/types.md Defines the main application object for transfer.sh. Created via server.New(...) and started via Run(). Contains configuration fields for authentication, storage, TLS, rate limiting, and more. ```go type Server struct { authUser string authPass string authHtpasswd string authIPFilterOptions *IPFilterOptions htpasswdFile *htpasswd.File authIPFilter *ipFilter logger *log.Logger tlsConfig *tls.Config profilerEnabled bool locks sync.Map maxUploadSize int64 rateLimitRequests int purgeDays time.Duration purgeInterval time.Duration storage storage.Storage forceHTTPS bool randomTokenLength int ipFilterOptions *IPFilterOptions VirusTotalKey string ClamAVDaemonHost string performClamavPrescan bool tempPath string webPath string proxyPath string proxyPort string emailContact string gaKey string userVoiceKey string TLSListenerOnly bool CorsDomains string ListenerString string TLSListenerString string ProfileListenerString string Certificate string LetsEncryptCache string } ``` -------------------------------- ### ParseRange usage example (Go) Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/api-reference/storage.md Shows how to call ParseRange with a raw Range header value. If the header is invalid or absent, ParseRange returns nil and the caller should serve the full resource; otherwise, the returned *Range is passed to storage.Get along with the token and filename. ```go rng := ParseRange(rngHeader) if rng == nil { // invalid or absent header — serve the full resource } else { reader, contentLength, err := s.storage.Get(ctx, token, filename, rng) } ``` -------------------------------- ### GET /({files:.*}).zip, GET /({files:.*}).tar, GET /({files:.*}).tar.gz Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/endpoints.md Downloads multiple files as a single archive (ZIP, TAR, or TAR.GZ). The files parameter is a comma-separated list of token/filename pairs. ```APIDOC ## GET /({files:.*}).zip, GET /({files:.*}).tar, GET /({files:.*}).tar.gz ### Description Downloads multiple files as a single archive (ZIP, TAR, or TAR.GZ). The files parameter is a comma-separated list of token/filename pairs. ### Method GET ### Endpoint `/({files:.*}).zip` or `/({files:.*}).tar` or `/({files:.*}).tar.gz` ### Parameters #### Path Parameters - **files** (string) - Required - Comma-separated list of `token/filename` pairs, e.g., `/abc123/a.txt,abc123/b.txt`. ### Response #### Success Response (200) - **Content-Type** (string) - `application/zip`, `application/x-tar`, or `application/x-gzip` depending on the archive type. - **Content-Disposition** (string) - `attachment; filename="transfersh-{n}.zip|.tar|.tar.gz"` where `{n}` is the number of files. - **Connection** (string) - Set to `close`. - **Cache-Control** (string) - Set to `no-store`. #### Error Response (404) - **Description**: `File not found` when a listed object is missing in storage. #### Error Response (500) - **Description**: Archive writer or storage failure. ``` -------------------------------- ### GET /{token}/{filename} Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/api-reference/handlers.md Handles GET requests for downloading files, supporting range requests and decryption. ```APIDOC ## GET /{token}/{filename} ### Description Serves the full download path, supporting range requests and optional decryption. It sets appropriate headers and streams the file content. ### Method GET ### Endpoint /{token}/{filename} or /{action}/{token}/{filename} ### Parameters #### Path Parameters - **token** (string) - Required - The token identifying the file. - **filename** (string) - Required - The name of the file. - **action** (string) - Optional - Action prefix (e.g., 'inline'). #### Query Parameters - **X-Decrypt-Password** (string) - Optional - Password for decryption. #### Headers - **Range** (string) - Optional - Byte range for partial content. - **X-Decrypt-Password** (string) - Optional - Password for decryption. ### Request Example ```bash $ curl -H "Range: bytes=0-99" -D - -o part.bin https://transfer.sh/BAYh0/hello.txt $ curl -H "X-Decrypt-Password: s3cret" https://transfer.sh/BAYh0/hello.txt -o hello.txt ``` ### Response #### Success Response (200) - **Content-Disposition** (string) - 'inline' or 'attachment'. - **Connection** (string) - 'keep-alive'. - **Cache-Control** (string) - 'no-store'. - **X-Remaining-Downloads** (integer) - Remaining download count. - **X-Remaining-Days** (integer) - Remaining days before expiry. - **Content-Type** (string) - MIME type of the file. - **Content-Length** (integer) - Size of the file. - **Vary** (string) - 'Range, Referer, X-Decrypt-Password'. #### Success Response (206 Partial Content) - **Content-Range** (string) - Byte range of the partial content. - **Accept-Ranges** (string) - 'bytes'. #### Error Responses - **404 Not Found** - If metadata or storage get fails. - **500 Internal Server Error** - On storage error, decryption failure, or copy error. ### Response Example ``` HTTP/1.1 206 Partial Content Content-Range: bytes 0-99/12345 Accept-Ranges: bytes Content-Type: text/plain Content-Length: 100 Connection: keep-alive Cache-Control: no-store X-Remaining-Downloads: 5 X-Remaining-Days: 30 Vary: Range, Referer, X-Decrypt-Password ``` ``` -------------------------------- ### Range struct definition Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/api-reference/storage.md Defines the Range struct with Start, Limit, and contentRange fields. Start is the first byte (inclusive), Limit is the byte count (0 means open-ended), and contentRange stores the outgoing Content-Range value. ```go type Range struct { Start uint64 Limit uint64 contentRange string } ``` -------------------------------- ### Range.AcceptLength() method Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/api-reference/storage.md Validates and adjusts the range against the content length. Returns the size of the served slice or the full contentLength when unsatisfiable. Open-ended ranges are closed to contentLength - Start; a Start at/after EOF or a slice longer than the remainder is not accepted. ```go func (r *Range) AcceptLength(contentLength uint64) (newContentLength uint64) { newContentLength = contentLength if r.Limit == 0 { r.Limit = newContentLength - r.Start } if contentLength < r.Start { return } if r.Limit > contentLength-r.Start { return } r.contentRange = fmt.Sprintf("bytes %d-%d/%d", r.Start, r.Start+r.Limit-1, contentLength) newContentLength = r.Limit return } ``` -------------------------------- ### Template initialization functions Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/api-reference/handlers.md Function signatures for template initialization and prefix stripping. ```go func stripPrefix(path string) string // handlers.go:82 func initTextTemplates() *textTemplate.Template // handlers.go:86 func initHTMLTemplates() *htmlTemplate.Template // handlers.go:94 ``` -------------------------------- ### Storage interface definition (common.go:92) Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/api-reference/storage.md Defines the Storage contract with methods for Get, Head, Put, Delete, IsNotExist, Purge, IsRangeSupported, and Type. The Get method accepts a *Range for range requests, and Put stores under token/filename with advisory contentType. ```go // Storage is the interface for storage operation type Storage interface { // Get retrieves a file from storage Get(ctx context.Context, token string, filename string, rng *Range) (reader io.ReadCloser, contentLength uint64, err error) // Head retrieves content length of a file from storage Head(ctx context.Context, token string, filename string) (contentLength uint64, err error) // Put saves a file on storage Put(ctx context.Context, token string, filename string, reader io.Reader, contentType string, contentLength uint64) error // Delete removes a file from storage Delete(ctx context.Context, token string, filename string) error // IsNotExist indicates if a file doesn't exist on storage IsNotExist(err error) bool // Purge cleans up the storage Purge(ctx context.Context, days time.Duration) error // Whether storage supports Get with Range header IsRangeSupported() bool // Type returns the storage type Type() string } ``` -------------------------------- ### GET /{action}/{token}/{filename} Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/endpoints.md Retrieves a file using an explicit action prefix: download, get, or inline. The inline action sets Content-Disposition to inline and forces text/plain when the stored content type is empty. Supports range requests, decryption, and sanitization for XSS-prone content types. ```APIDOC ## GET /{action}/{token}/{filename} ### Description Retrieves a file using an explicit action prefix: download, get, or inline. The inline action sets Content-Disposition to inline and forces text/plain when the stored content type is empty. Supports range requests, decryption, and sanitization for XSS-prone content types. ### Method GET ### Endpoint /{action}/{token}/{filename} ### Parameters #### Path Parameters - **action** (string) - Required - One of `download`, `get`, or `inline`. - **token** (string) - Required - The unique token identifying the upload. - **filename** (string) - Required - The name of the file to download. #### Request Headers - **Range** (string) - Optional - Byte range in the format `bytes=start-finish`. - **X-Decrypt-Password** (string) - Optional - Password to decrypt the file if it was uploaded encrypted. ### Response #### Success Response (200) - Content-Disposition: attachment or inline; filename="..." - Content-Type: as stored (or text/plain; charset=utf-8 for inline with empty stored type) - Content-Length: file size - Cache-Control: no-store - Connection: keep-alive - X-Remaining-Downloads: remaining downloads - X-Remaining-Days: remaining days - Vary: Range, Referer, X-Decrypt-Password - Accept-Ranges: bytes (when range honored) - Content-Range: bytes start-end/total (when range honored) #### Partial Content (206) - Returned when a range is honored. #### Error Responses - 404 - Metadata missing/expired or object not found - 500 - Storage/copy/decrypt failure (e.g., wrong decryption password) ### Notes - When X-Decrypt-Password is provided and the file is encrypted, the stream is decrypted and Content-Type/Content-Length are restored from stored metadata. - If the inline disposition is used with an XSS-prone content type, the stream is sanitized. - Unsatisfiable ranges return the full resource with 200 and an empty Content-Range header. ``` -------------------------------- ### Archive and upload directory Source: https://github.com/dutchcoders/transfer.sh/blob/main/examples.md Create a tar.gz archive of a directory and upload it. ```bash $ tar -czf - /var/log/journal | curl --upload-file - https://transfer.sh/journal.tar.gz ``` -------------------------------- ### renderFloat and formatNumber usage examples Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/api-reference/utils-token.md Example calls showing directive behavior: "0.00" disables thousands separator, "" uses default comma separator, and "0.000,000" uses comma thousands with precision 7. Exact digit layout depends on the directive grammar. ```go renderFloat("0.00", 1234.5) // "1234.50" (no thousands separator: directive form disables it) renderFloat("", 12.5) // "12.50" (default form: "," thousands separator) formatNumber("0.000,000", 1234567) // "1,234,567.0000000" (',' thousands, precision 7) ``` -------------------------------- ### Run Docker container with local provider Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/api-reference/cmd.md Runs the Docker image with the local provider. The entry point already sets --listener :8080, so only the provider and basedir need to be specified. ```bash $ docker run --publish 8080:8080 dutchcoders/transfer.sh:latest --provider local --basedir /tmp/ ``` -------------------------------- ### GET /health.html Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/endpoints.md Health check endpoint that always returns a success message. It is exempt from HTTPS redirect when forceHTTPS is enabled. ```APIDOC ## GET /health.html ### Description Health check endpoint that always returns a success message. It is exempt from HTTPS redirect when forceHTTPS is enabled. ### Method GET ### Endpoint /health.html ### Response #### Success Response (200) - **body** (string) - Plain-text success message. #### Response Example Approaching Neutral Zone, all systems normal and functioning. ``` -------------------------------- ### Upload file to VirusTotal via transfer.sh Source: https://github.com/dutchcoders/transfer.sh/blob/main/examples.md Uploads a file to transfer.sh with the /virustotal endpoint to get a VirusTotal permalink in return. ```bash $ curl -X PUT --upload-file nhgbhhj https://transfer.sh/test.txt/virustotal ``` -------------------------------- ### Download with wget Source: https://github.com/dutchcoders/transfer.sh/blob/main/examples.md Download a file using wget. ```bash $ wget https://transfer.sh/1lDau/test.txt ``` -------------------------------- ### notFoundHandler: respond with 404 status text Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/api-reference/handlers.md Installed as r.NotFoundHandler (server.go:531). Writes the HTTP status text for 404 as the response body with status code 404. ```go func (s *Server) notFoundHandler(w http.ResponseWriter, _ *http.Request) { http.Error(w, http.StatusText(404), 404) } ``` -------------------------------- ### Token usage examples Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/api-reference/utils-token.md Shows how the token function is used to generate an upload token and a deletion-token pattern. The deletion token is the concatenation of two tokens, doubling the length. ```go token(s.randomTokenLength) // upload token, e.g. "BAYh0aB9cD" target := token(10) + token(10) // deletion-token pattern used by metadataForRequest ``` -------------------------------- ### Put method for LocalStorage (local.go:114) Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/api-reference/local-storage.md Creates the token directory with mode 0700 if needed, then writes the reader content to a file with mode 0600. The content type and length are ignored; the file size is determined by the copy. Returns nil on success or a filesystem error. ```go func (s *LocalStorage) Put(_ context.Context, token string, filename string, reader io.Reader, contentType string, contentLength uint64) error { var f io.WriteCloser var err error path := filepath.Join(s.basedir, token) if err = os.MkdirAll(path, 0700); err != nil && !os.IsExist(err) { return err } f, err = os.OpenFile(filepath.Join(path, filename), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600) defer CloseCheck(f) if err != nil { return err } if _, err = io.Copy(f, reader); err != nil { return err } return nil } ``` -------------------------------- ### Middleware chain in Server.Run() Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/endpoints.md Middleware chain assembled in Server.Run() for every request. Includes panic recovery, IP filtering (403 when blocked), logging, custom headers, optional HTTPS redirect and CORS. ```go handlers.PanicHandler( ipFilterHandler( -- IP allow/deny, 403 when blocked handlers.LogHandler( LoveHandler( -- adds x-made-with / x-served-by / server headers s.RedirectHandler(cors(r))), -- HTTPS redirect (optional) + CORS (optional) ... ), s.ipFilterOptions), nil) ``` -------------------------------- ### Encrypt and decrypt with keybase on transfer.sh Source: https://github.com/dutchcoders/transfer.sh/blob/main/examples.md Shows how to track a keybase user, encrypt a file for them, upload it, and later decrypt a downloaded file using keybase. ```bash $ keybase track [them] # Encrypt for recipient(s) $ cat somebackupfile.tar.gz | keybase encrypt [them] | curl --upload-file '-' https://transfer.sh/test.txt # Decrypt $ curl https://transfer.sh/sqUFi/test.md | keybase decrypt ``` -------------------------------- ### NewS3Storage constructor Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/api-reference/s3-storage.md Constructs an S3Storage instance. It loads AWS config via `getAwsConfig`, creates an S3 client with the given region, path-style option (required for MinIO), and optional custom endpoint. Returns `nil` and an error if config loading fails. ```go func NewS3Storage(ctx context.Context, credentialsType, accessKey, secretKey, bucketName string, purgeDays int, region, endpoint string, disableMultipart bool, forcePathStyle bool, logger *log.Logger) (*S3Storage, error) { cfg, err := getAwsConfig(ctx, credentialsType, accessKey, secretKey) if err != nil { return nil, err } client := s3.NewFromConfig(cfg, func(o *s3.Options) { o.Region = region o.UsePathStyle = forcePathStyle if len(endpoint) > 0 { o.BaseEndpoint = aws.String(endpoint) } }) return &S3Storage{ bucket: bucketName, s3: client, logger: logger, noMultipart: disableMultipart, purgeDays: time.Duration(purgeDays*24) * time.Hour, }, nil } ``` -------------------------------- ### Upload a file with curl Source: https://github.com/dutchcoders/transfer.sh/blob/main/k8s/transfer.sh/templates/NOTES.txt Use this curl command to upload a file to the installed transfer.sh service. If HTTP Basic Auth is enabled, include the -u user:pass flag. Replace with the actual host. ```shell curl {{ if .Values.transfersh.httpAuth.enabled }}-u user:pass {{ end }}--upload-file ./file.txt https:///file.txt ``` -------------------------------- ### Upload with wget Source: https://github.com/dutchcoders/transfer.sh/blob/main/examples.md Upload a file using wget with the PUT method and body-file option. ```bash $ wget --method PUT --body-file=/tmp/file.tar https://transfer.sh/file.tar -O - -nv ``` -------------------------------- ### metadataForRequest: Build metadata from headers Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/api-reference/metadata.md Builds metadata from request headers. Empty or invalid Max-Downloads/Max-Days values leave defaults (-1 / zero time). Max-Days beyond ~290 years are rejected later by putHandler with 400 Invalid MaxDate... ```go func metadataForRequest(contentType string, contentLength int64, randomTokenLength int, r *http.Request) metadata { metadata := metadata{ ContentType: strings.ToLower(contentType), ContentLength: contentLength, MaxDate: time.Time{}, // zero = never expiring Downloads: 0, MaxDownloads: -1, // -1 = unlimited DeletionToken: token(randomTokenLength) + token(randomTokenLength), } // "Max-Downloads" header -> metadata.MaxDownloads (strconv.Atoi, invalid values ignored) // "Max-Days" header -> metadata.MaxDate = time.Now().Add(time.Hour * 24 * Duration(v)) // "X-Encrypt-Password" -> Encrypted = true; ContentType = "text/plain; charset=utf-8"; // DecryptedContentType = contentType return metadata } ``` -------------------------------- ### purgeHandler() periodic cleanup loop Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/api-reference/metadata.md Starts a background goroutine that periodically calls storage.Purge with the configured purgeDays. Logs errors but does not stop the loop. S3Storage.Purge and StorjStorage.Purge are no-ops because expiry is set at upload time via Expires. ```go func (s *Server) purgeHandler() { ticker := time.NewTicker(s.purgeInterval) go func() { for { <-ticker.C err := s.storage.Purge(context.TODO(), s.purgeDays) if err != nil { s.logger.Printf("error cleaning up expired files: %v", err) } } }() } ``` -------------------------------- ### StorjStorage struct definition Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/api-reference/storj-storage.md Defines the StorjStorage struct that embeds the Storage interface and holds the Storj project, bucket, purge duration, and logger. The project is opened with user agent 'transfer-sh', the bucket is ensured, and uploads get an expiration of purgeDays. ```go // StorjStorage is a storage backed by Storj type StorjStorage struct { Storage project *uplink.Project bucket *uplink.Bucket purgeDays time.Duration logger *log.Logger } ``` -------------------------------- ### Backup, encrypt and transfer MySQL dump Source: https://github.com/dutchcoders/transfer.sh/blob/main/examples.md Create a MySQL dump, compress, encrypt, and upload to transfer.sh. ```bash $ mysqldump --all-databases | gzip | gpg -ac -o- | curl -X PUT --upload-file "-" https://transfer.sh/test.txt ``` -------------------------------- ### newIPFilter constructor Source: https://github.com/dutchcoders/transfer.sh/blob/main/_autodocs/api-reference/ip-filter.md Constructs an ipFilter from IPFilterOptions. Sets a default logger if none is provided, initializes the IP map and default policy, then applies blocked and allowed IPs in order. Invalid entries are silently dropped. ```go func newIPFilter(opts *IPFilterOptions) *ipFilter { if opts.Logger == nil { flags := log.LstdFlags opts.Logger = log.New(os.Stdout, "", flags) } f := &ipFilter{ ips: map[string]bool{}, defaultAllowed: !opts.BlockByDefault, } for _, ip := range opts.BlockedIPs { f.BlockIP(ip) } for _, ip := range opts.AllowedIPs { f.AllowIP(ip) } return f } ``` -------------------------------- ### Upload using HTTPie Source: https://github.com/dutchcoders/transfer.sh/blob/main/examples.md Upload a file using HTTPie by piping it to the request. ```bash $ http https://transfer.sh/ -vv < /tmp/test.log ```