Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(gateway): _redirects file support #8890

Merged
merged 54 commits into from
Sep 23, 2022
Merged

feat(gateway): _redirects file support #8890

merged 54 commits into from
Sep 23, 2022

Conversation

justindotpub
Copy link
Contributor

@justindotpub justindotpub commented Apr 15, 2022

Context: ipfs/specs#290, part of ipfs/specs#257

This PR implements ipfs/specs#290.

Details

Now that #8885 has landed, I've moved my refactored _redirects changes here from #8816. This is on my personal account now, so the CircleCI permission issues should be resolved. 😅

@lidel, as mentioned at #8816 (comment), there are some challenges with trying to fully move _redirects logic out of gateway_handler.go as you requested. The changes in this PR aren't ready (full review not needed yet), but would you be able to take a look and let me know if you approve of how I've split code into handleUnixfsPathResolution and handleNonUnixfsPathResolution?

Also, note that I've intentionally not moved 404 related functions from gateway_handler.go to gateway_handler_unixfs__redirects.go yet, to avoid extra PR noise.

@justindotpub justindotpub changed the title Draft: feat(gateway): _redirects file support feat(gateway): _redirects file support Apr 15, 2022
@justindotpub
Copy link
Contributor Author

@lidel When you have time, gentle bump on getting your feedback to the comments above. I really appreciate the time and feedback you've given me already. 🙏

At this point I have what feels like the right MVP functionality working (from to [status][!] including 200 rewrite for SPA support). I have more tests to write but would really like your thoughts on how close this code is to done so I can try to get this over the finish line.

Also, related to your go-redirects comments... it feels to me like we should not use a library dedicated to parsing Netlify's _redirect file, and instead have our own library whose specific goal is to support the functionality in the redirect IPFS spec (to be written). For now I'm thinking this is essentially a fork of go-redirects that only supports from to [status][!] and the first version of the spec will only include this functionality. All of this functionality is working now on this PR's branch and justincjohnson/go-ipfs-redirects. If you are okay with this approach, I can keep this project in my personal account or we could move it to the ipfs org before this ships if that is preferable.

If you disagree and want me to stick with a repo that specifically supports Netlify's syntax, I still had to fork the repo since it is no longer maintained, and it seems to me there wouldn't be any reason to add all the existing Netlify parsing logic right away, since the MVP won't support all of those features anyway.

For convenience for anyone wanting to evaluate the changes...

# Build and run
make build
GOLOG_LOG_LEVEL="core/server=debug" ./cmd/ipfs/ipfs daemon

# web site
mkdir -p ~/testredirect/
echo "index" > ~/testredirect/index.html
echo "one" > ~/testredirect/one.html
echo "two" > ~/testredirect/two.html
echo "404" > ~/testredirect/404.html
echo "existing" > ~/testredirect/existing.html
echo "forced redirect, never to be seen" > ~/testredirect/forced-redirect.html
mkdir -p ~/testredirect/articles/2022/04/25/hello-world
echo "hello world" > ~/testredirect/articles/2022/04/25/hello-world/index.html

# _redirects file
echo "/redirect-one /one.html" > ~/testredirect/_redirects
echo "/301-redirect-one /one.html 301" >> ~/testredirect/_redirects
echo "/302-redirect-two /two.html 302" >> ~/testredirect/_redirects
echo "/200-index /index.html 200" >> ~/testredirect/_redirects
# existing file with no force, so won't redirect
echo "/existing.html /two.html 200" >> ~/testredirect/_redirects
# existing file with force, so will redirect
echo '/forced-redirect.html /index.html 301!' >> ~/testredirect/_redirects
# Redirect with placeholder.  Try /posts/2022/04/25/hello-world in browser
echo "/posts/:year/:month/:day/:title /articles/:year/:month/:day/:title 301" >> ~/testredirect/_redirects
# Try /splat/index.html or /splat/one.html
echo "/splat/* /:splat 301" >> ~/testredirect/_redirects
# Pretty 404 logic
echo "/en/* /404.html 404" >> ~/testredirect/_redirects
# SPA, as last rule 
echo "/* /index.html 200" >> ~/testredirect/_redirects

CID=$(./cmd/ipfs/ipfs add -r ~/testredirect -Q)
open http://$(echo $CID | ./cmd/ipfs/ipfs cid base32).ipfs.localhost:8080

@justindotpub
Copy link
Contributor Author

FYI, I'll be out for a few weeks but will be checking email in case there is any PR feedback. I'm sure there will be things to address but I'm going to mark this as ready for review now.

@justindotpub justindotpub marked this pull request as ready for review April 29, 2022 19:56
@justindotpub
Copy link
Contributor Author

After some discussion with @b5 and @dignifiedquire, I'm leaning toward pulling out forced redirect support to avoid a performance hit for anything other than non-existent paths (i.e. read _redirects file and check for matching redirects if and only if the path didn't resolve). If someone wants to force a redirect, they can just remove or rename the existing path that's preventing redirect rules from firing.

@justindotpub
Copy link
Contributor Author

Review status... @lidel is wrapping up specs for existing gateway functionality and then hopes to get to this, possibly next week or the week after.

Copy link
Member

@lidel lidel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First, thank you for your patience @justincjohnson 🙌

I will be OOO Thu-Fri due to Holiday, and will do proper review of go code in this PR when I am back, but to get things going, quick feedback:

Moving go-ipfs-redirects to ipfs org

Good call on making a dedicated lib.
If you add me as Admin to https://github.com/justincjohnson/go-ipfs-redirects i'll move it to ipfs org + ensure you still have your permissions.

Creating RFC with specs

We want this to be a part of web gateway specs, and not just go-ipfs feature.
Good news is that we now have all the pieces in place to do the proper spec work:

Do you mind opening a PR against HTTP Gateway specs from ipfs/specs#283 that adds:

When we have ipfs/specs PR with RFC,
I'll ping folks from other implementations to take a look and provide feedback, to ensure they are onboard too 👍

Thanks!

test/sharness/t0109-gateway-web-_redirects.sh Outdated Show resolved Hide resolved
Copy link
Member

@lidel lidel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your angelic patience @justincjohnson ❤️

I did the first pass review of this along with IPIP (specifications) at ipfs/specs#290 – some questions / asks apply to both – details inline.

General ask for this PR is to rebase on top of latest master to include new tests added in past few weeks.

core/corehttp/gateway_handler_unixfs__redirects.go Outdated Show resolved Hide resolved
test/sharness/t0109-gateway-web-_redirects.sh Outdated Show resolved Hide resolved
test/sharness/t0109-gateway-web-_redirects.sh Outdated Show resolved Hide resolved
core/corehttp/gateway_handler_unixfs__redirects.go Outdated Show resolved Hide resolved
Comment on lines 214 to 224
// Returns the root CID Path for the given path
func getRootPath(path string) (ipath.Path, error) {
if isIpfsPath(path) {
parts := strings.Split(path, "/")
return ipath.New(gopath.Join(ipfsPathPrefix, parts[2])), nil
}

if isIpnsPath(path) {
parts := strings.Split(path, "/")
return ipath.New(gopath.Join(ipnsPathPrefix, parts[2])), nil
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: if you switch path from string to contentPath ipath.Path, then you will be able to read namespace via contentPath.Namespace() and simplify this

go.mod Outdated Show resolved Hide resolved
go.mod Outdated Show resolved Hide resolved
core/corehttp/gateway_handler.go Outdated Show resolved Hide resolved
@justindotpub
Copy link
Contributor Author

@lidel I believe I've addressed all feedback now. From my perspective the only question that is outstanding is ipfs/specs#290 (comment). I did add code to handle these extra http status codes, but it still feels to me like it may not make sense.

My hope is that we are finally close to having this pushed across the finish line. 🤞

Thanks again for your assistance.

Copy link
Member

@lidel lidel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good, I've added some tests and moved library to the main org at https://github.com/ipfs/go-ipfs-redirects-file.

@justincjohnson will you have time to rebase this PR on top of master again, so it builds with go1.19? When you do that, please address small asks below + ipfs/go-ipfs-redirects-file#11

Would like to ship this in Kubo 0.16 (or 0.17, depending on external factors, such as spec work and today's Implementers review), building with 1.19 is the main blocker.

// The path can't be resolved.
// If we have origin isolation, attempt to handle any redirect rules.
if hasOriginIsolation(r) {
redirectsFile := i.getRedirectsFile(r, contentPath, logger)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: please move logic related to handling redirectsFile to serveRedirectsIfPresent similar to serveLegacy404IfPresent

Will make it easier to reason about, and easier to refactor in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lidel Do you feel strongly about this nit? I ask because refactoring this leads to a similar situation we had with past refactor suggestions where the resulting code has to return multiple bools to signal when the caller should return and with what, etc... in this case needing to return 2 paths and 2 bools. If you feel strongly, I'll see what I can do. Thank you!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I refactored as requested. Hopefully you're okay with the booleans.

core/corehttp/gateway_handler_unixfs__redirects.go Outdated Show resolved Hide resolved
core/corehttp/gateway_handler_unixfs__redirects.go Outdated Show resolved Hide resolved
core/corehttp/gateway_handler_unixfs__redirects.go Outdated Show resolved Hide resolved
@lidel
Copy link
Member

lidel commented Sep 22, 2022

- this function is core to all response types, does not belong to
  _redirects specific file
- small improvements that improve readability and remove surface for
  bugs
Copy link
Member

@lidel lidel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed again and pushed some tweaks.
No real blockers, should be good enough for inclusion in 0.16 RC, but see the ask below.

return true, toPath, err
}

if rule.Status == 410 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@justincjohnson I missed these before:

  • 410 and 451 are missing sharness tests
  • 410 and 451 should behave similarly to what we do for 404, allowing for custom error pages to be rendered informing user why content was taken down.
    • perhaps reuse i.serve404 – rename it to i.serve4xx and make it accept specific code as a parameter?
  • coreiface.ErrResolveFailed should not be used for them, create dedicated errors

lmk if you have time to address this before Monday, ideally we would include examples of these in the text fixture that is listed in specs (sadly the CID needs to be updated once again).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No problem. I'll get this done tomorrow.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, please avoid force-push this time, will make review easier.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have made the changes and pushed (not force!).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CIDs have been updated in the spec and IPIP as well.

@BigLep
Copy link
Contributor

BigLep commented Sep 23, 2022

Thanks for all the work here all! For being included in 0.16 (#9237), we'll need to have this ready for review today (2022-09-23) because the RC gets cut on 2022-09-26 Europe time.

@justindotpub
Copy link
Contributor Author

The changes are in and ready for review @BigLep 🙏

Copy link
Member

@lidel lidel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @johnnymatthews 👍 ❤️

Switched to v0.1.1 and pushed some final cleanup.

I believe this is good enough to ship in 0.16 RC (#9237) next week and take it for a spin in the real world.

Merging! (I'll squash, because we moved things around many times).

@lidel lidel merged commit bcaacdd into ipfs:master Sep 23, 2022
@justindotpub
Copy link
Contributor Author

@lidel thanks a ton for all the work you put into this!

@justindotpub justindotpub deleted the justincjohnson/redirects branch September 23, 2022 17:01
lidel added a commit to ipfs/ipfs-docs that referenced this pull request Sep 23, 2022
@lidel
Copy link
Member

lidel commented Sep 23, 2022

@justincjohnson fysa we are writing end-user docs for docs.ipfs.tech too, PR draft in ipfs/ipfs-docs#1275

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
No open projects
Archived in project
Development

Successfully merging this pull request may close these issues.

3 participants