urlcat
Build correct URLs easily.
What? • Why? • How? • Typescript • API • Help • Contribute
What?
urlcat is a tiny JavaScript library that makes building URLs very convenient and prevents common mistakes.
Features:
- Friendly API
- No dependencies
- 0.6 KB minified and gzipped
- Typescript types provided
Why?
When I need to call an HTTP API, I usually need to add dynamic parameters to the URL:
const API_URL = 'https://api.example.com/';
function getUserPosts(id, blogId, limit, offset) {
const requestUrl = `${API_URL}/users/${id}/blogs/${blogId}/posts?limit=${limit}&offset=${offset}`;
// send HTTP request
}As you can see, this minimal example is already rather hard to read. It is also incorrect:
- I forgot that there was a trailing slash at the end of the
API_URLconstant so the slash got duplicated (https://api.example.com//users) - The embedded values need to be escaped using
encodeURIComponent
I can use the built-in URL class to prevent duplicate slashes and URLSearchParams to escape the query string. But I still need to escape all path parameters manually.
const API_URL = 'https://api.example.com/';
function getUserPosts(id, blogId, limit, offset) {
const escapedId = encodeURIComponent(id);
const escapedBlogId = encodeURIComponent(blogId);
const path = `/users/${escapedId}/blogs/${escapedBlogId}`;
const url = new URL(path, API_URL);
url.search = new URLSearchParams({ limit, offset });
const requestUrl = url.href;
// send HTTP request
}Such a simple task and yet very hard to read and tedious to write! This is why I made this tiny library:
const API_URL = 'https://api.example.com/';
function getUserPosts(id, limit, offset) {
const requestUrl = urlcat(API_URL, '/users/:id/posts', { id, limit, offset });
// send HTTP request
}The library handles:
- escaping all parameters
- concatenating all parts (there will always be exactly one / and ? character between them)
How?
Install
Currently, the package is distributed via npm. Zip downloads and a CDN are coming soon.
npm install --save urlcatUsage with Node
Node 10 and above are officially supported. Since the code uses the URL and URLSearchParams classes internally, which aren’t available below v10, we cannot support those versions.
If you want to build full URLs (most common use case):
const urlcat = require('urlcat').default;If you want to use any of the utility functions:
const { query, subst, join } = require('urlcat');If you want to use everything:
const { default: urlcat, query, subst, join } = require('urlcat');Usage with Typescript
Typescript 2.1 and above are officially supported.
If you want to build full URLs (most common use case):
import urlcat from 'urlcat';If you want to use any of the utility functions:
import { query, subst, join } from 'urlcat';If you want to use everything:
import urlcat, { query, subst, join } from 'urlcat';Typescript
This library provides its own type definitions. “It just works”, no need to install anything from @types.
API
ParamMap: an object with string keys
type ParamMap = Record<string, any>;For example, { firstParam: 1, 'second-param': 2 } is a valid ParamMap.
urlcat: build full URLs
function urlcat(baseUrl: string, pathTemplate: string, params: ParamMap): string
function urlcat(baseUrl: string, pathTemplate: string): string
function urlcat(baseTemplate: string, params: ParamMap): stringExamples
-
urlcat('https://api.example.com', '/users/:id/posts', { id: 123, limit: 10, offset: 120 })
→'https://api.example.com/users/123/posts?limit=10&offset=120' -
urlcat('http://example.com/', '/posts/:title', { title: 'Letters & "Special" Characters' })
→'http://example.com/posts/Letters%20%26%20%22Special%22%20Characters' -
urlcat('https://api.example.com', '/users')
→'https://api.example.com/users' -
urlcat('https://api.example.com/', '/users')
→'https://api.example.com/users' -
urlcat('http://example.com/', '/users/:userId/posts/:postId/comments', { userId: 123, postId: 987, authorId: 456, limit: 10, offset: 120 })
→'http://example.com/users/123/posts/987/comments?authorId=456&limit=10&offset=120'
query: build query strings
function query(params: ParamMap): stringBuilds a query string using the key-value pairs specified. Keys and values are escaped, then joined by the '&' character.
Examples
params | result |
|---|---|
{} | '' |
{ query: 'some text' } | 'query=some%20text' |
{ id: 42, 'comment-id': 86 } | 'id=42&comment-id=86' |
{ id: 42, 'a name': 'a value' } | 'id=42&a%20name=a%20value' |
subst: substitute path parameters
function subst(template: string, params: ParamMap): stringSubstitutes parameters with values in a template string. template may contain 0 or more parameter placeholders. Placeholders start with a colon (:), followed by a parameter name that can only contain uppercase or lowercase letters. Any placeholders found in the template are replaced with the value under the corresponding key in params.
Examples
template | params | result |
|---|---|---|
':id' | { id: 42 } | '42' |
'/users/:id' | { id: 42 } | '/users/42' |
'/users/:id/comments/:commentId' | { id: 42, commentId: 86 } | '/users/42/comments/86' |
'/users/:id' | { id: 42, foo: 'bar' } | '/users/42' |
join: join two strings using exactly one separator
function join(part1: string, separator: string, part2: string): stringJoins the two parts using exactly one separator. If a separator is present at the end of part1 or the beginning of part2, it is removed, then the two parts are joined using separator.
Examples
part1 | separator | part2 | result |
|---|---|---|---|
'first' | ',' | 'second' | 'first,second' |
'first,' | ',' | 'second' | |
'first' | ',' | ',second' | |
'first,' | ',' | ',second' |
Help
Thank you for using urlcat!
If you need any help using this library, feel free to create a GitHub issue and ask your questions. I’ll try to answer as quickly as possible.
Contribute
Contributions of any kind (pull requests, bug reports, feature requests, documentation, design) are more than welcome! If you like this project and want to help, but feel like you are stuck, feel free to contact the maintainer (Botond Balázs <balazsbotond@gmail.com>).
Building from source
Building the project should be quick and easy. If it isn’t, it’s the maintainer’s fault. Please report any problems with building in a GitHub issue.
You need to have a reasonably recent version of node.js to build urlcat. My node version is 12.18.3, npm is at 6.14.6.
First, clone the git repository:
git clone git@github.com:balazsbotond/urlcat.gitThen switch to the newly created urlcat directory and install the dependencies:
cd urlcat
npm installYou can then run the unit tests to verify that everything works correctly:
npm testAnd finally, build the library:
npm run buildThe output will appear in the dist directory.
Happy hacking!