utils

package module
v1.3.0 Latest Latest
Warning

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

Go to latest
Published: Sep 16, 2024 License: MIT Imports: 17 Imported by: 0

README

Utils Module

Go Reference Coverage Status

Module of simple, well-tested, and reusable Go utilities. Inspired by Trevor Sawler's "Building a Module in Go." Udemy course.

Most of the utilities in this module are based on Trevor Sawler's Toolbox module.


The utilities in this module:

RandomString()

RandomString generates and returns a string of a specified length of random characters. The characters are randomnly asembled from othe ptional characterSeed parameter, or they are sourced from the default set made up of the following characters: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_+!@#$%*

func (u *Utils) RandomString(length int, characterSeed ...[]rune) string
UploadOneFile()

UploadOneFile is a convenience method that calls UploadFiles, but expects only one file to be in the upload.

func (u *Utils) UploadOneFile(r *http.Request, uploadDir string, rename ...bool) (*UploadedFile, error) 
UploadFiles()

UploadFiles uploads one or more files from a multipart form submission contained within an http.Request to the specified uploadDir directory. It gives the files a random name. It returns a slice of UploadedFile structs, and potentially an error. If the optional last parameter is set to true, the files won't be renamed.

func (u *Utils) UploadFiles(req *http.Request, uploadDir string, rename ...bool) ([]*UploadedFile, error)
MakeDirStructure()

MakeDirStructure is a convenience method of the utils package which uses os.MkdirAll to creates a directory structure based on the slice of path strings provided. It returns nil when all the directories are successfully created, or else returns an error. The permission bits default to 0755, and are used for all directories created. If a path is already a directory, os.MkdirAll does nothing and returns nil, so MakeDirStructure will also return nil. If there's a permission issue encountered for any of the paths, the error reported by os.MkdirAll will be collected, and MakeDirStructure will return all encountered those errors as one.

func (u *Utils) MakeDirStructure(pathsToBeMade []string) error
CrawlLogPaths()

CrawlLogPaths: given a starting path, it will crawl the directory hierachy below that path, and output a log message of each full path from the specified starting path.

func (u *Utils) CrawlLogPaths(root string) error
TextToSlug()

The TextToSlug function converts accented characters to their unaccented versions, replaces all non-alphanumeric characters with dashes, trims redundant dashes, and converts the string to lowercase. This approach makes the slug both URL-friendly and human-readable.

func (u *Utils) TextToSlug(input string) string 
ForceFileDownload()

ForceFileDownload forces the browser to avoid displaying it in the browser window by setting the Content-Disposition header. It also allows specifying a custom display name for the downloaded file.

func (u *Utils) ForceFileDownload(w http.ResponseWriter, r *http.Request, pathToFile, displayName string) 
ReadJSON()

ReadJSON tries to read the body of a request and converts from json into a go data variable.

func (u *Utils) ReadJSON(w http.ResponseWriter, r *http.Request, data interface{}) error 
WriteJSON()

WriteJSON takes a response, an httpStatus code, and arbitrary data, then generates and sends json in the http response to the client.

func (u *Utils) WriteJSON(w http.ResponseWriter, httpStatus int, data interface{}, headers ...http.Header) error
ErrorJSON()

ErrorJSON takes an error and optionally an http httpStatus code, then generates and sends a json formatted error http response. If no httpStatus code is passed, http.StatusBadRequest is the defualt used.

func (u *Utils) ErrorJSON(w http.ResponseWriter, err error, httpStatus ...int) error
PushJSONToRemote()

PushJSONToRemote sends arbitrary data to a specified URL as JSON, and returns the response and http status code, or an error if any. The client parameter is optional. If none is specified, it uses the standard library's http.Client.

func (u *Utils) PushJSONToRemote(uri string, method string, data interface{}, client ...*http.Client) (*http.Response, int, error)
LoadEnvVarsFromFile()

LoadEnvVarsFromFile expects a string represnting the path to the environment variable file. This approach relies on the environment variables file existing in the file system and being readable.

func (u *Utils) LoadEnvVarsFromFile(filename string) error
LoadEnvVarsFromEmbed()

LoadEnvVarsFromEmbed expects a string resulting from having uses Go's //go:embed directive to import an embedded environment variable file. This approach relies on the environment variables file being embedded directly in the binary, which might not be ideal for sensitive data in some cases.

func (u *Utils) LoadEnvVarsFromEmbed(goEmbedReadFile string) error
UniqueRunes()

UniqueRunes takes a string and converts it to a slice of unique runes. This method preserves the order of the first appearance of runes in the input string. Because Go's rune type handles Unicode characters properly, this solution works correctly even with strings containing non-ASCII characters.

func (u *Utils) UniqueRunes(s string) []rune 
ContainsAllRunes()

ContainsAllRunes checks if all runes in a subset slice are contained in set slice. This method correctly handles cases where runes are duplicated, both in the set and subset slices. This works with Unicode characters, as Go's rune type properly supports Unicode.

func (u *Utils) ContainsAllRunes(set, subset []rune) bool

Installation

go get -u github.com/loickreitmann/utils


Usage

See the example test files, or the package doumentation on the Go Package Discovery site.

Documentation

Overview

Package of simple and well tested reusable Go utilities. Inspired by Trevor Sawler's "Building a Module in Go." Udemy course.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type JSONError added in v1.0.0

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

type JSONOptions added in v1.0.0

type JSONOptions struct {
	MaxJSONReadSize    int
	AllowUnknownFields bool
}

type JSONResponse added in v1.0.0

type JSONResponse struct {
	Error interface{} `json:"error,omitempty"`
	Data  interface{} `json:"data,omitempty"`
}

JSONResponse is the type used for sending JSON

type UploadOptions added in v0.2.0

type UploadOptions struct {
	MaxUploadFileSize int
	AllowedTypes      []string
}

type UploadedFile added in v0.2.0

type UploadedFile struct {
	NewFilename      string
	OriginalFilename string
	FileSize         int64
	Error            string
}

UploadedFile is a struct storing the information about an uploaded file.

type Utils

type Utils struct {
	UploadOptions
	JSONOptions
}

Utils is the type used to instantiate the module. Any variable of this type will have access to all the methods with the *Utils receiver.

func New added in v0.2.0

func New() *Utils

Constructor for Utils struct that defines default options necessary when using the UploadFiles and UploadOneFile methods. MaxUploadFileSize: 1GB. AllowedTypes: JPG, PNG, and GIF

func (*Utils) ContainsAllRunes added in v1.3.0

func (u *Utils) ContainsAllRunes(set, subset []rune) bool

ContainsAllRunes checks if all runes in a `subset` slice are contained in `set` slice. This method correctly handles cases where runes are duplicated, both in the set and subset slices. This works with Unicode characters, as Go's rune type properly supports Unicode.

func (*Utils) CrawlLogPaths added in v0.4.0

func (u *Utils) CrawlLogPaths(root string) error

CrawlLogPaths: given a starting path, it will crawl the directory hierachy below that path, and output a log message of each full path from the specified starting path.

func (*Utils) ErrorJSON added in v1.0.0

func (u *Utils) ErrorJSON(w http.ResponseWriter, err error, httpStatus ...int) error

ErrorJSON takes an error and optionally an http status code, then generates and sends a json formatted error http response. If no status code is passed, http.StatusBadRequest is the defualt used.

func (*Utils) ForceFileDownload added in v0.6.0

func (u *Utils) ForceFileDownload(w http.ResponseWriter, r *http.Request, pathToFile, displayName string)

ForceFileDownload forces the browser to avoid displaying it in the browser window by setting the Content-Disposition header. It also allows specifying a custom display name for the downloaded file.

Example
package main

import (
	"fmt"
	"log"
	"net/http"

	"github.com/loickreitmann/utils"
)

type forceFileDownloadExample struct{}

func main() {
	ffde := &forceFileDownloadExample{}

	mux := ffde.routes()
	fmt.Println("Starting Server on localhost:8080")
	if err := http.ListenAndServe(":8080", mux); err != nil {
		log.Fatal(err)
	}
}

func (ffde *forceFileDownloadExample) routes() http.Handler {
	mux := http.NewServeMux()

	mux.Handle("/", http.StripPrefix("/", http.FileServer(http.Dir("./testdata/force_file_download/"))))
	mux.HandleFunc("/download", ffde.download)
	return mux
}

func (ffde *forceFileDownloadExample) download(resw http.ResponseWriter, req *http.Request) {
	var u utils.Utils

	u.ForceFileDownload(resw, req, "./testdata/force_file_download/download_test.jpg", "Be like the Mandalorian, this is the way.jpg")
}

func (*Utils) LoadEnvVarsFromEmbed added in v1.1.0

func (u *Utils) LoadEnvVarsFromEmbed(goEmbedReadFile string) error

LoadEnvVarsFromEmbed expects a string resulting from having uses Go's //go:embed directive to import an embedded environment variable file. This approach relies on the environment variables file being embedded directly in the binary, which might not be ideal for sensitive data in some cases.

Example
package main

import (
	_ "embed"
	"fmt"
	"os"

	"github.com/loickreitmann/utils"
)

//go:embed testdata/.env.example
var envVarsFile string

/*
The exmple .env.example file contains:
```
API_KEY=your_api_key
# this a comment ignored by ven var parsing
DATABASE_URL=your_database_url

PORT=8080

This=is a bad=line
```
*/

func main() {
	var u utils.Utils

	if err := u.LoadEnvVarsFromEmbed(envVarsFile); err != nil {
		fmt.Printf("unexpected error loading env vars: %v\n", err)
	}

	fmt.Println("API_KEY", os.Getenv("API_KEY"))
	fmt.Println("DATABASE_URL", os.Getenv("DATABASE_URL"))
	fmt.Println("PORT", os.Getenv("PORT"))
	fmt.Println("This", os.Getenv("This")) // will be an empty string

}
Output:

API_KEY your_api_key
DATABASE_URL your_database_url
PORT 8080
This

func (*Utils) LoadEnvVarsFromFile added in v1.1.0

func (u *Utils) LoadEnvVarsFromFile(filename string) error

LoadEnvVarsFromFile expects a string represnting the path to the environment variable file. This approach relies on the environment variables file existing in the file system and being readable.

Example
package main

import (
	"fmt"
	"os"

	_ "embed"
	"github.com/loickreitmann/utils"
)

func main() {
	var u utils.Utils

	if err := u.LoadEnvVarsFromFile("testdata/.env.example"); err != nil {
		fmt.Printf("unexpected error loading env vars: %v\n", err)
	}

	fmt.Println("API_KEY", os.Getenv("API_KEY"))
	fmt.Println("DATABASE_URL", os.Getenv("DATABASE_URL"))
	fmt.Println("PORT", os.Getenv("PORT"))
	fmt.Println("This", os.Getenv("This")) // will be an empty string

}
Output:

API_KEY your_api_key
DATABASE_URL your_database_url
PORT 8080
This

func (*Utils) MakeDirStructure added in v0.3.0

func (u *Utils) MakeDirStructure(pathsToBeMade []string) error

MakeDirStructure is a convenience method of the `utils` package which uses `os.MkdirAll` to creates a directory structure based on the slice of path strings provided. It returns nil when all the directories are successfully created, or else returns an error. The permission bits default to 0755, and are used for all directories created. If a path is already a directory, os.MkdirAll does nothing and returns nil, so MakeDirStructure will also return nil. If there's a permission issue encountered for any of the paths, the error reported by os.MkdirAll will be collected, and MakeDirStructure will return all encountered those errors as one.

Example
package main

import (
	"fmt"
	"os"

	"github.com/loickreitmann/utils"
)

func main() {
	var u utils.Utils

	pathsToMake := []string{
		"./05_test/a/1",
		"./05_test/a/2",
		"./05_test/a/3",
		"./05_test/b/1",
		"./05_test/b/2",
		"./05_test/b/3",
		"./05_test/c/1",
		"./05_test/c/2",
		"./05_test/c/3",
	}
	err := u.MakeDirStructure(pathsToMake)
	if err != nil {
		fmt.Println(err.Error())
	} else {
		fmt.Println("Created the following directories:")
		u.CrawlLogPaths("05_test")
		_ = os.RemoveAll("./05_test")
	}

}
Output:

Created the following directories:
05_test
05_test/a
05_test/a/1
05_test/a/2
05_test/a/3
05_test/b
05_test/b/1
05_test/b/2
05_test/b/3
05_test/c
05_test/c/1
05_test/c/2
05_test/c/3

func (*Utils) PushJSONToRemote added in v1.0.0

func (u *Utils) PushJSONToRemote(uri string, method string, data interface{}, client ...*http.Client) (*http.Response, int, error)

PushJSONToRemote sends arbitrary data to a specified URL as JSON, and returns the response and http status code, or an error if any. The client parameter is optional. If none is specified, it uses the standard library's http.Client.

func (*Utils) RandomString

func (u *Utils) RandomString(length int, characterSeed ...[]rune) string

RandomString generates and returns a string of a specified length of random characters. The characters are randomnly asembled from othe ptional characterSeed parameter, or they are sourced from the default set made up of the following characters: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_+!@#$%*

Example
package main

import (
	"fmt"

	"github.com/loickreitmann/utils"
)

func main() {
	var u utils.Utils

	str := u.RandomString(22)

	fmt.Printf("Random string has %d characters.\n", len(str))

}
Output:

Random string has 22 characters.

func (*Utils) ReadJSON added in v1.0.0

func (u *Utils) ReadJSON(w http.ResponseWriter, r *http.Request, data interface{}) error

ReadJSON tries to read the body of a request and converts from json into a go data variable

func (*Utils) TextToSlug added in v0.5.0

func (u *Utils) TextToSlug(input string) string

The TextToSlug function converts accented characters to their unaccented versions, replaces all non-alphanumeric characters with dashes, trims redundant dashes, and converts the string to lowercase. This approach makes the slug both URL-friendly and human-readable.

Example
package main

import (
	"fmt"

	"github.com/loickreitmann/utils"
)

func main() {
	var u utils.Utils
	quotes := []string{
		"Il est grand temps de rallumer les étoiles.",             // — Guillaume Apollinaire
		"Cliché, but love conquers all.",                          // — Common English phrase
		"La vida es sueño, y los sueños, sueños son.",             // — Pedro Calderón de la Barca
		"Über den Wolken muss die Freiheit wohl grenzenlos sein.", // (Above the clouds, freedom must be boundless.) — Reinhard Mey
		"Człowiek bez marzeń jest jak ptak bez skrzydeł.",         // (A person without dreams is like a bird without wings.) — Polish proverb
	}

	for _, quote := range quotes {
		fmt.Println(u.TextToSlug(quote))
	}

}
Output:

il-est-grand-temps-de-rallumer-les-etoiles
cliche-but-love-conquers-all
la-vida-es-sueno-y-los-suenos-suenos-son
uber-den-wolken-muss-die-freiheit-wohl-grenzenlos-sein
cz-owiek-bez-marzen-jest-jak-ptak-bez-skrzyde

func (*Utils) UniqueRunes added in v1.3.0

func (u *Utils) UniqueRunes(s string) []rune

UniqueRunes takes a string and converts it to a slice of unique runes. This method preserves the order of the first appearance of runes in the input string. Because Go's rune type handles Unicode characters properly, this solution works correctly even with strings containing non-ASCII characters.

func (*Utils) UploadFiles added in v0.2.0

func (u *Utils) UploadFiles(r *http.Request, uploadDir string, rename ...bool) ([]*UploadedFile, error)

UploadFiles uploads one or more files from a multipart form submission contained within an `http.Request` to the specified `uploadDir` directory. It gives the files a random name. It returns a slice of `UploadedFile` structs, and potentially an `error`. If the optional last parameter is set to `true`, the files won't be renamed.

func (*Utils) UploadOneFile added in v0.2.0

func (u *Utils) UploadOneFile(r *http.Request, uploadDir string, rename ...bool) (*UploadedFile, error)

UploadOneFile is a convenience method that calls UploadFiles, but expects only one file to be in the upload.

func (*Utils) WriteJSON added in v1.0.0

func (u *Utils) WriteJSON(w http.ResponseWriter, httpStatus int, data interface{}, headers ...http.Header) error

WriteJSON takes a response, an httpStatus code, and arbitrary data and generates and sends json in the http response to the client

Jump to

Keyboard shortcuts

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