parseurl

package
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Jul 18, 2026 License: MIT Imports: 2 Imported by: 0

Documentation

Overview

Package parseurl parses the URL of an incoming HTTP request into its components, a stdlib-only Go port of the npm package "parseurl" (https://www.npmjs.com/package/parseurl). In the Node/Express world parseurl is the tiny utility that turns a request's raw target string (req.url) into a structured URL object with fields such as path, query and pathname, and it underpins routing, static file serving and any middleware that needs to reason about the request path independently of the query string.

The reason parseurl exists at all in Node is performance and correctness of caching. Parsing a URL is not free, and a single request typically has its URL inspected by many layers of middleware, so the original library memoizes the parsed result on the request object and reparses only when the underlying req.url string has changed. It also distinguishes the current URL (which Express may rewrite as it strips mounted route prefixes) from the original, unmodified request target, exposing the latter through parseurl.original.

This Go port maps those two concepts onto net/http and net/url. Parse returns the request's effective URL as a *url.URL, and OriginalURL returns the original request target; both read from req.RequestURI, the raw target line as received, and fall back to the request's already-parsed req.URL field when RequestURI is empty or unparseable. A nil request yields a nil result rather than panicking, mirroring parseurl's tolerance of a missing url. ParseString is a thin convenience wrapper over url.Parse for parsing an arbitrary URL string directly.

Because Go's http.Request already carries a parsed URL and an immutable RequestURI, this port does not need parseurl's memoization machinery: parsing RequestURI with net/url is cheap and the raw target does not mutate underneath you the way req.url can in Express, so each call simply parses afresh and no per-request cache is stored. Parse first tries url.ParseRequestURI, which is the correct strict parser for an HTTP request target, and only falls back to the more lenient url.Parse (and finally to req.URL) if that fails, so well-formed absolute paths and absolute-form targets are both handled.

The resulting *url.URL exposes the same information the Node object does, just under Go's field names: Path holds the decoded path, EscapedPath preserves the original percent-encoding, and RawQuery (or the parsed Query map) holds the query string. Parity with Node is therefore behavioral rather than literal — you get the request's path and query parsed the way net/url parses them, with the original request target available separately — which is exactly what the downstream routing and static-serving ports in this module consume.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func OriginalURL

func OriginalURL(req *http.Request) *url.URL

OriginalURL parses the request's original URL. Like Parse, it uses req.RequestURI as the source of the original, unmodified request target.

func Parse

func Parse(req *http.Request) *url.URL

Parse parses the request's effective URL, using req.RequestURI and falling back to req.URL when RequestURI is empty or cannot be parsed. It returns nil when req is nil.

Example

ExampleParse builds an HTTP request with a path and query string and parses its effective URL into structured components. Parse reads the request's raw target and returns a *url.URL, from which the decoded path and the raw query string can be read directly. The query can also be decoded into individual parameters via the returned URL's Query method. This mirrors how Node's parseurl turns req.url into a structured object for routing and middleware.

package main

import (
	"fmt"
	"net/http/httptest"

	"github.com/malcolmston/express/parseurl"
)

func main() {
	req := httptest.NewRequest("GET", "/foo/bar?baz=1&qux=2", nil)

	u := parseurl.Parse(req)
	fmt.Println("path:", u.Path)
	fmt.Println("query:", u.RawQuery)
	fmt.Println("baz:", u.Query().Get("baz"))
}
Output:
path: /foo/bar
query: baz=1&qux=2
baz: 1
Example (Encoded)

ExampleParse_encoded shows that percent-encoded path segments are handled correctly. The request target contains a space encoded as %20 in both the path and a query value. Parse returns a URL whose Path field holds the decoded value while EscapedPath preserves the original encoding. This lets callers compare against decoded paths yet still reconstruct the exact on-the-wire form when needed.

package main

import (
	"fmt"
	"net/http/httptest"

	"github.com/malcolmston/express/parseurl"
)

func main() {
	req := httptest.NewRequest("GET", "/foo%20bar?a=b%20c", nil)

	u := parseurl.Parse(req)
	fmt.Println("decoded path:", u.Path)
	fmt.Println("escaped path:", u.EscapedPath())
}
Output:
decoded path: /foo bar
escaped path: /foo%20bar

func ParseString

func ParseString(rawurl string) (*url.URL, error)

ParseString parses a raw URL string into a *url.URL.

Example

ExampleParseString parses an arbitrary absolute URL string directly, without needing an *http.Request. It is a thin convenience wrapper over the standard library's url.Parse. The returned URL exposes the host, path and query as separate fields. This is handy when you already hold a URL string rather than a request, for example when parsing a configured upstream target.

package main

import (
	"fmt"

	"github.com/malcolmston/express/parseurl"
)

func main() {
	u, err := parseurl.ParseString("http://example.com/a/b?c=d")
	if err != nil {
		fmt.Println("error:", err)
		return
	}
	fmt.Println("host:", u.Host)
	fmt.Println("path:", u.Path)
	fmt.Println("query:", u.RawQuery)
}
Output:
host: example.com
path: /a/b
query: c=d

Types

This section is empty.

Jump to

Keyboard shortcuts

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