URI, URL, URN?? Identifying resources on the web
Tags: architecture, webdev, development, learning
Published: 2022-07-21 08:14:24

---
title: URI, URL, URN?? Identifying resources on the web
published: true
description: Resources on the web can be identified through a series of technical specs. Let's dig into some RFCs!
tags: architecture, webdev, development, learning
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d7w4dzcq0meaocxsuho5.jpg
# Use a ratio of 100:42 for best results.
---

_Cover image by <a href="https://unsplash.com/@cifilter?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Shannon Potter</a> on <a href="https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>_
  

If you do web development you will, at some point, encounter 3 particular term: URI, URL and URN (this is not so familiar but you may have encountered ARNs in AWS).
You may also have seen URI and URL being used interchangeably, but it's important to note they are not the same thing even if they are used for very similar purposes: finding things and finding things on the internet.

Let's break down what do those acronyms mean:
- URI stands for Uniform Resource Indicator
- URL stands for Uniform Resource Locator
- URN stands for Uniform Resource Name

URLs and URNs are specific classifications of URIs.  
It happens that URIs are very different between each other (from [rfc3986#section-1.1.2](https://datatracker.ietf.org/doc/html/rfc3986#section-1.1.2)):
```
ftp://ftp.is.co.za/rfc/rfc1808.txt
http://www.ietf.org/rfc/rfc2396.txt
ldap://[2001:db8::7]/c=GB?objectClass?one
mailto:John.Doe@example.com
news:comp.infosystems.www.servers.unix
tel:+1-816-555-1212
telnet://192.0.2.16:80/
urn:oasis:names:specification:docbook:dtd:xml:4.1.2
```

Follow me in a deep dive into URIs, URLs and URNs and some good old RFC digging. Put on your safety 🥽, grab your ⛏ and let's go!!

## What's a URI

A Uniform Resource Identifier is a generic way to uniquely identify any resource. 

The complete definition is in [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986), where you can hunt for all the details.

It takes the form of a string with this syntax:

```
URI = scheme ":" ["//" authority] path ["?" query] ["#" fragment]
```

There are 5 components:
- [`scheme`](https://datatracker.ietf.org/doc/html/rfc3986#section-3.1) (required), arbitrary but there are popular ones like `mailto`, `https`, `ftp` or `arn`
- [`authority`](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2) (optional), for user information and top level namespace (usually a domain or IP address) with the syntax
  `authority   = [ userinfo "@" ] host [ ":" port ]`
  - [`userinfo`](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1) (optional); either a `username` or a `username` and ` password` concatenated by `:` (`username:password`)
  - [`host`](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2) (required), can be a domain or an IPv4/IPV6
  - [`port`](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.3) (optional)

- [`path`](https://datatracker.ietf.org/doc/html/rfc3986#section-3.3) (required but can be empty - you know, parsers 🤷), a hierarchical structure separated by `/`
- [`query`](https://datatracker.ietf.org/doc/html/rfc3986#section-3.4) (optional), it **starts** with `?` and can contain `?` and `/` (like `path`)
- [`fragment`](https://datatracker.ietf.org/doc/html/rfc3986#section-3.4) (optional), it starts with `#` until the end of the URI

This is quite convoluted and the RFC is incredibly detailed. The [Wikipedia page for URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) helps!

It's important to understand the URI as it's the foundation on which URL and URN are based.

## What's a URL

The Uniform Resource Locator is a string representation to for a resource available via the Internet.

It has it's own RFC, [RFC 1738](https://datatracker.ietf.org/doc/html/rfc1738), where we find all the familiar names and strings we see as Web developers.

It defines some specific schemas we all know and love:

```
   ftp                     File Transfer protocol
   http                    Hypertext Transfer Protocol
   gopher                  The Gopher protocol
   mailto                  Electronic mail address
   news                    USENET news
   nntp                    USENET news using NNTP access
   telnet                  Reference to interactive sessions
   wais                    Wide Area Information Servers
   file                    Host-specific file names
   prospero                Prospero Directory Service
```
_(wait, what is `wais`??? Think I'm too young for that!)_

and it defines the usual "Internet" scheme syntax for all URLs schemes that involve usage of an IP-based protocol:

```
//<user>:<password>@<host>:<port>/<url-path>
```

I'm young enough that I basically only used `ftp`, `http` and `mailto`! (And well.. [watching Star Wars over `telnet`](https://dev.to/kasuken/how-to-watch-star-wars-in-your-terminal-523c) 😆) Did you use some of the others? Let me know in the comment, I want to read your story!!

## What's a URN

Quite simply, it's a URI with the `urn` scheme. URNs are **location indipendent** and **persistent** identifiers. 

This means there is only 1 unique URN for a given resource in a given namespace **forever** (or until that resource doesn't exist any more).

URNs are defined by [RFC 8141](https://datatracker.ietf.org/doc/html/rfc8141).

Their properties of being **location indipendent** and **persistent** makes them useful for some very interesting use cases, especially.

Their syntax definition ([rfc8141#section-2](https://datatracker.ietf.org/doc/html/rfc8141#section-2)) is quite more complex, here a simplified version:

```
URN = "urn" ":" NID ":" NSS [ "?+" r-component ] [ "?=" q-component ] [ "#" f-component ]
```

This is more easily akin to a URI with multiple components:
- `urn` is the `scheme`
- [`NID`](https://datatracker.ietf.org/doc/html/rfc8141#section-2.1) (required), the namespace identifier
- [`NSS`](https://datatracker.ietf.org/doc/html/rfc8141#section-2.2) (required), the namespace specific string
- [`r-component`](https://datatracker.ietf.org/doc/html/rfc8141#section-2.3.1) (optional), query parameters to pass to URL resolution services, note that it's used is *discouraged*: "Thus, r-components SHOULD NOT be used for URNs before their semantics have been standardized."
- [`q-component`](https://datatracker.ietf.org/doc/html/rfc8141#section-2.3.2) (optional), query parameters for the named resource or the service supplying the named resource
- [`f-component`](https://datatracker.ietf.org/doc/html/rfc8141#section-2.3.3) (optional), a fragment representing the location or region for the named resource, ignored during URN equivalence operations.

It should be noted that a [public registry for URNs namespaces exists](https://datatracker.ietf.org/doc/html/rfc8141#section-7.2), and is [maintained at IANA](https://www.iana.org/assignments/urn-namespaces/urn-namespaces.xhtml). 

Does it mean you need to register a namespace before using it? No if you plan to use it internally, yes if you want it to be internet-global (like [`xmpp`](https://www.rfc-editor.org/rfc/rfc4854.html) or [`uuid`](https://www.rfc-editor.org/rfc/rfc4122.html)

## So cool but where to use them?

### AWS

If you have experience with [Amazon Web Services](https://aws.amazon.com/) you will have encountered ARNs: [Amazon Resource Names](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html). By their definition:

> Amazon Resource Names (ARNs) uniquely identify AWS resources. We require an ARN when you need to specify a resource unambiguously across all of AWS, such as in IAM policies, Amazon Relational Database Service (Amazon RDS) tags, and API calls.

Sounds familiar? The format too is very URN-like (there are different formats, look at the docs!):

```
arn:partition:service:region:account-id:resource-type/resource-id
```

From the look of it it does not seem to be a RFC-compliant URN, but it's extremely similar.

### GCP

Google Cloud Platform relies on URIs to identify resources on the platform.

(Resources names](https://cloud.google.com/apis/design/resource_names) are schema-less URIs similar to:

```
logging.googleapis.com/projects/myproject123/locations/global/buckets/my-bucket
```

`logging.googleapis.com` is the `authority`, the `path` the resource. Being the `path` hierarchical is possible to represent GCP resource structure this way (project -> collection -> resource).

### LinkedIn

Another at-scale example is [LinkedIn](https://docs.microsoft.com/en-us/linkedin/shared/api-guide/concepts/urns?view=li-lms-2022-07): 

> URNs are used to represent foreign associations to an entity (persons, organizations, and so on) in an API. A URN is a string-based identifier with the format:
`urn:{namespace}:{entityType}:{id}`

### Express foreign keys

Simple relational database design generally rely on (autoincrementing) `int` for rows IDs in tables. This system is effective and works in a single database scenario. 

When scaling to multiple DBs or distributed applications (es microservices) using integers is not enough anymore. Some common problems are:
- conflicting autoincrementing numbers: being auto incremental they are exposed to possible race conditions when creating records
- too generic: the system (or it's operators) is not able to know only by looking at the ID what kind of resource that ID refers to. If you think is not that important, Atlassian recently [blew up 883 customer's websites](https://www.atlassian.com/engineering/post-incident-review-april-2022-outage) due to a similar confusion: a script included IDs for websites and not apps in the Atlassian backend ecosystem. Those IDs were then used for deletion, but the thing deleted wasn't, as expected, the customer app instance but their entire website. 

---

Do you have any other examples of URNs being used in systems? I'm curious to know about them so please let me know in the comments!