urlf

package module
v0.6.1 Latest Latest
Warning

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

Go to latest
Published: Dec 29, 2024 License: Apache-2.0 Imports: 8 Imported by: 0

README

urlf: URL formatting utility

Go Reference

urlf is a Safe URL formatting library for Go. This library wraps net.URL and provides a printf style function that is short and easy to read and escapes safely the values in the URL template to prevent URL injection.

Installation

$ go get github.com/shibukawa/urlf

Basic Usage

import (
    "net/http"
    "github.com/shibukawa/urlf"
)

http.Get(urlf.Urlf("https://example.com/api/users/{}/profile", 1000))

URL Template Rules

You can put placeholders in the following locations:

  • protocol (string or *string)
  • hostname (string or *string)
  • port (int or *int)
  • path (string or *string, int *int or []any)
  • query value (string or *string, int, *int)
  • query set (url.Values)
  • fragment (string or *string)
protocol    := "https"
hostname    := "example.com"
port        := 8080
path        := "api/users"
queryValue  := "value"
querySet, _ := url.ParseQuery("key1=value1&key2=value2")
fragment    := "fragment"
urlf.Urlf(`{}://{}:{}/{}?queryKey={}&{}#{}`, protocol, hostname, port, queryValue, querySet, fragment)

Placeholder can be written only between each delimiter (://, :, /, ?, =, &, #) and interpolated strings are escaped properly.

Path Hierarchies

Placeholders for path can accept slice or / separated string, and it supports URLs with variable path hierarchies.

areaList := []string{"japan", "tokyo", "shinjuku"};
urlf.Urlf(`https://example.com/menu/{}`, areaList)
// => 'https://example.com/menu/japan/tokyo/shinjuku'

areaStr := "japan/tokyo/shinjuku";
urlf.Urlf(`https://example.com/menu/{}`, areaStr)
// => 'https://example.com/menu/japan/tokyo/shinjuku'
nil

If the placeholder value is nil, the placeholder and related text (like query key) are removed from the resulting URL. To pass nil, the pointer type are acceptable for placeholder variables.

var port     *string
var value1   *string
var value2   *string
var fragment *string

value2 =  &[]string{"value2"}[0]

urlf.Urlf(`https://example.com:{}/api/users?key1={}&key2={}#{}`, port, value1, value2, fragment)
// => 'https://example.com/api/users?key2=value2'

This behavior is useful when you want to implement paging query that has default values than url.Values.

var word    *string
var page    *int
var perPage *int    // use default
var limit   *int    // use default

word = []string{}"spicy food"}[0]
page = []int{10}[0]

urlf.Urlf(`https://example.com/api/search?word={}&page={}&perPage={}&limit={}`, word, page, perPage, limit)
// => 'https://example.com/api/search?word=spicy+food&page=10'
Query Set

It accepts url.Values instance as a query set and merges it with other queries.

searchParams := url.Values{
    "word": []string{"spicy food"},
    "safeSearch": []string{"false"},
    "spicyLevel": []string{"Infinity"},
}
urlf.Urlf(`https://example.com/api/search?{}`, searchParams)
// => 'https://example.com/api/search?word=spicy+food&safeSearch=false'

Advanced Usage

Custom factory function can overwrite the some parts of the URL. It is good for specifies the API host that is from environment variables or credentials that should not be hard-coded in the source code:

  • protocol
  • hostname: It can contains protocol and/or port.
  • port
  • username and password: It is only available location to define in this library.
apiUrl := urlf.CustomFormatter(urlf.Opt{
    Hostname: os.Getenv("API_SERVER_HOST"),  // https://localhost:8080
    Username: os.Getenv("API_SERVER_USER"),  // user
    Password: os.Getenv("API_SERVER_PASS"),  // pAssw0rd

})

apiUrl(`https://api-server/api/users/{}/profile`, 1000)
// => 'https://user:pAssw0rd@localhost:8080/api/users/1000/profile'
// "https://api-server" is a dummy string that is replaced with customFormatter()'s hostname option.
// You can avoid hard-coding the actual hostname in your project code.

License

Apache-2.0

References

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrFormatFailed = errors.New("format failed")
View Source
var ErrParseFailed = errors.New("parse failed")

Functions

func CustomFormatter

func CustomFormatter(o Opt) func(format string, args ...any) string

CustomFormatter is a custom formatter function.

Generated function has same signature with Urlf. But it can be customized by Opt.

It is a "Must" version of TryCustomFormatter.

Example
package main

import (
	"fmt"

	"github.com/shibukawa/urlf"
)

func main() {
	formatter := urlf.CustomFormatter(urlf.Opt{
		Hostname: "api.example.com",
		Protocol: "https",
	})
	url := formatter("http://api-server/api/users/{}", 1000)
	fmt.Println(url)
}
Output:

https://api.example.com/api/users/1000

func TryCustomFormatter

func TryCustomFormatter(o Opt) func(format string, args ...any) (string, error)

TryCustomFormatter generates a custom formatter function that returns an empty string.

func TryUrlf

func TryUrlf(format string, args ...any) (string, error)

TryUrlf is a similar function to Urlf, but it returns an error if the format is invalid.

func Urlf

func Urlf(format string, args ...any) string

Urlf is a default formatter function.

It is a "Must" version of TryUrlf. It assumes URL template string is written as a static string literal and the template is not created dynamically. So, it raise panic instead of return error.

If you want to get parsing error, use TryUrlf, instead.

Types

type Opt

type Opt struct {
	Hostname string
	Port     uint16
	Protocol string
	Username string
	Password string
}

Opt is a struct for custom formatter options.

Jump to

Keyboard shortcuts

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