Skip to content

Commit 6134bf0

Browse files
authored
Merge pull request #386 from suicide/ipip/gateway-interop-redirects
IPIP-0386: Subdomain Gateway Interop with _redirects
2 parents 4ba553f + 1dea175 commit 6134bf0

File tree

2 files changed

+195
-15
lines changed

2 files changed

+195
-15
lines changed

src/http-gateways/subdomain-gateway.md

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -147,22 +147,33 @@ Below MUST be implemented **in addition** to `Location` requirements defined in
147147

148148
#### Use in interop with Path Gateway
149149

150-
Returned with `301` Moved Permanently (:cite[path-gateway]) when `Host` header does
150+
The `Location` HTTP header is returned with `301` Moved Permanently
151+
(:cite[path-gateway]) when `Host` header does
151152
not follow the subdomain naming convention, but the requested URL path happens
152-
to be a valid `/ipfs/{cid}` or `/ipfs/{name}` content path.
153-
154-
This redirect allows subdomain gateway to be used as a drop-in
155-
replacement compatible with regular path gateways.
156-
157-
NOTE: the content root identifier must be converted to case-insensitive/inlined
158-
form if necessary. For example:
159-
160-
- `https://dweb.link/ipfs/QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR`
161-
returns HTTP 301 redirect to the same CID but in case-insensitive base32:
162-
- `Location: https://bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi.ipfs.dweb.link/`
163-
- `https://dweb.link/ipns/en.wikipedia-on-ipfs.org` returns HTTP 301 redirect
164-
to subdomain with DNSLink name correctly inlined:
165-
- `Location: https://en-wikipedia--on--ipfs-org.ipns.dweb.link/`
153+
to be a valid `/ipfs/{cid}[/{path}][?{query}]` or `/ipfs/..` content path.
154+
155+
This redirect allows a subdomain gateway to be used as a drop-in replacement
156+
compatible with regular path gateways, as long as the rules below are followed:
157+
158+
- Redirect from a path gateway URL to the corresponding subdomain URL MUST
159+
preserve the originally requested `{path}` and `{query}` parameters, if
160+
present.
161+
- Content path validation before the redirect SHOULD be limited to the
162+
correctness of the root CID. If the content path includes any subpath or
163+
query parameters, they SHOULD be preserved and processed after the redirect
164+
to a subdomain is completed.
165+
- Namely, additional logic, such as IPLD path traversal or processing the
166+
`_redirects` file, SHOULD only be executed by the subdomain gateway after
167+
the redirect.
168+
- Before redirecting, the content root identifier MUST be converted to
169+
case-insensitive/inlined form if necessary. For example:
170+
- `https://dweb.link/ipfs/QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR`
171+
returns HTTP 301 redirect to the same CID but in case-insensitive base32:
172+
- `Location:
173+
https://bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi.ipfs.dweb.link/`
174+
- `https://dweb.link/ipns/en.wikipedia-on-ipfs.org` returns HTTP 301 redirect
175+
to subdomain with DNSLink name correctly inlined:
176+
- `Location: https://en-wikipedia--on--ipfs-org.ipns.dweb.link/`
166177

167178
See also: [Migrate from Path to Subdomain Gateway](#migrating-from-path-to-subdomain-gateway).
168179

src/ipips/ipip-0386.md

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
---
2+
title: "IPIP-0386: Subdomain Gateway Interop with _redirects"
3+
date: 2023-03-18
4+
ipip: ratified
5+
editors:
6+
- name: suicide
7+
github: suicide
8+
relatedIssues:
9+
- https://github.com/ipfs/boxo/pull/326
10+
- https://github.com/ipfs/boxo/pull/412
11+
order: 386
12+
tags: ['ipips']
13+
---
14+
15+
## Summary
16+
17+
This IPIP provides a detailed clarification on the interoperability between the
18+
Path and Subdomain Gateway. Specifically, it ensures that features such as
19+
:cite[web-redirects-file] are executed only AFTER a redirect to a subdomain has
20+
taken place.
21+
22+
## Motivation
23+
24+
When hosting a modern Single Page Application on IPFS, one wants to use native
25+
URLs to share the app with other users, e.g. `ipns://example.org/cool/feature`.
26+
On traditional hosting, deep links are redirected or rewritten to a single
27+
entry point, e.g. `/index.html`, and the router on the client side evaluates
28+
the path segments to render the correct content.
29+
30+
The `_redirects` file, defined in :cite[web-redirects-file],
31+
supports such applications when a Subdomain Gateway is used directly. However,
32+
the current resolution of native URLs uses a Path Gateway link scheme and
33+
subsequently fails to resolve the URL correctly.
34+
35+
For example:
36+
37+
- `ipns://example.org/some/path` is resolved as
38+
- `http://{gateway}/ipns/example.org/some/path`
39+
- this request fails with 404 as the resource `/some/path` does not exist.
40+
41+
NOTE: The `kubo` (<0.20) gateway returns a 404 including a new `Location` header
42+
already pointing to the correct subdomain URL. But browsers do not follow the
43+
header as the status is 404, and the response contains a `text/plain` body
44+
string.
45+
46+
When using a Subdomain Gateway on the proper host, the path can be resolved
47+
using the `_redirects` file:
48+
49+
- `http://example-org.ipns.{gateway}/some/path` is redirected (301) to
50+
- `http://example-org.ipns.{gateway}/correct/path` as defined in
51+
`_redirects`file
52+
53+
54+
## Detailed design
55+
56+
This IPIP suggests the following resolution steps for DNSLink names, CIDs
57+
should be resolved similarly:
58+
59+
- `ipns://example.org/some/path` is resolved as
60+
- `http://{gateway}/ipns/example.org/some/path` is redirected (301) to the
61+
Subdomain Gateway
62+
- `http://example-org.ipns.{gateway}/some/path` is redirected (301) to
63+
- `http://example-org.ipns.{gateway}/correct/path` as defined in `_redirects`.
64+
65+
A Subdomain Gateway that provides interoperability with Path-Gateway-style URLs
66+
should redirect to a Subdomain-Gateway-style URL first and then try to resolve
67+
a given path. This allows the usage of a potential `_redirects` file in the
68+
root.
69+
70+
This change subsequently fixes the resolution of native URLs in browsers using
71+
the companion extension and browsers like Brave.
72+
73+
A paragraph is added to the :cite[subdomain-gateway]
74+
spec that describes the preservation of path segments and query parameters
75+
during the interop redirect. Furthermore, it specifies that gateway
76+
implementations should redirect to subdomain URLs if a resource is initially
77+
not found in the directory identified by the CID or DNSLink name.
78+
79+
## Test fixtures
80+
81+
The example from the :cite[web-redirects-file] can be re-used,
82+
`QmYBhLYDwVFvxos9h8CGU2ibaY66QNgv8hpfewxaQrPiZj`.
83+
84+
```
85+
$ ipfs ls /ipfs/QmYBhLYDwVFvxos9h8CGU2ibaY66QNgv8hpfewxaQrPiZj
86+
Qmd9GD7Bauh6N2ZLfNnYS3b7QVAijbud83b8GE8LPMNBBP 7 404.html
87+
QmSmR9NShZ89VEBrn9SBy7Xxvjw8Qe6XArD5GqtHvbtBM3 7 410.html
88+
QmVQqj9oZig9tH3ENHo4bxV5pNgssUwFCXUjAJAVcZVbJG 7 451.html
89+
QmZU3kboiyi9jV59D8Mw8wzuvsr3HmvskqhYRRhdFA8wRq 317 _redirects
90+
QmaWDLb4gnJcJbT1Df5X3j91ysiwkkyxw6329NLiC1KMDR - articles/
91+
QmS6ZNKE9s8fsHoEnArsZXnzMWijKddhXXDsAev8LdTT5z 9 index.html
92+
QmNwEgMrExwSsE8DCjZjahYfHUfkSWRhtqSkQUh4Fk3udD 7 one.html
93+
QmVe2GcTbEPZkMbjVoQ9YieVGKCHmuHMcJ2kbSCzuBKh2s - redirected-splat/
94+
QmUGVnZaofnd5nEDvT2bxcFck7rHyJRbpXkh9znjrJNV92 7 two.html
95+
```
96+
97+
The `_redirects` file is as follows.
98+
99+
```
100+
$ ipfs cat /ipfs/QmYBhLYDwVFvxos9h8CGU2ibaY66QNgv8hpfewxaQrPiZj/_redirects
101+
/redirect-one /one.html
102+
/301-redirect-one /one.html 301
103+
/302-redirect-two /two.html 302
104+
/200-index /index.html 200
105+
/posts/:year/:month/:day/:title /articles/:year/:month/:day/:title 301
106+
/splat/* /redirected-splat/:splat 301
107+
/not-found/* /404.html 404
108+
/gone/* /410.html 410
109+
/unavail/* /451.html 451
110+
/* /index.html 200
111+
```
112+
113+
Following redirects should occur:
114+
115+
```
116+
$ curl -v http://{gateway}/ipfs/QmYBhLYDwVFvxos9h8CGU2ibaY66QNgv8hpfewxaQrPiZj/redirect-one
117+
...
118+
< HTTP/1.1 301 Moved Permanently
119+
< Location: http://bafybeiesjgoros75o5meijhfvnxmy7kzkynhqijlzmypw3nry6nvsjqkzy.ipfs.{gateway}/redirect-one
120+
...
121+
```
122+
123+
Subsequent requests should comply with :cite[ipip-0002].
124+
125+
## Design rationale
126+
127+
Gateways like `kubo` (before v0.20) already support the `_redirect` and
128+
subdomain redirect, but block the redirect chain by returning a 404 when a
129+
resource is not found on the Path Gateway. By moving the 404 to occur at the
130+
subdomain, users get another chance to find the resources they are looking for.
131+
132+
### User benefit
133+
134+
Currently, users are presented with an error message when they request a
135+
resource on a Path Gateway intended for a Subdomain Gateway. Since a given
136+
gateway would redirect on a valid resource anyway, redirecting to the subdomain
137+
URL on a potentially invalid resource would improve usability and
138+
compatibility.
139+
140+
### Compatibility
141+
142+
This proposal fixes a bug in handling of `_redirects` files.
143+
144+
The current behavior is defined in :cite[path-gateway]. The
145+
404 return code indicates that a resource does not exist. Changing this to a
146+
301 redirect that is subsequently answered with a 404 from the subdomain URL
147+
is a breaking change, but the old behavior should be considered as a bug.
148+
149+
Requesting an existing resource on the Path Gateway URL in `kubo` already
150+
returns a 301 redirect: client expectation is for the behavior to be the same
151+
for invalid paths.
152+
153+
154+
### Security
155+
156+
Security should not be compromised as the resource is not delivered from the
157+
Path Gateway URL but from the subsequent subdomain URL that offers improved
158+
security due to host separation.
159+
160+
### Alternatives
161+
162+
Gateways could continue to return a 404 response for the non-existing resource,
163+
but also include an HTML body containing a redirect link. This would help users
164+
to find the requested site, but comes with worse UX than the fix proposed in
165+
this IPIP.
166+
167+
### Copyright
168+
169+
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).

0 commit comments

Comments
 (0)