-
Notifications
You must be signed in to change notification settings - Fork 325
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: recover from failed HTTP requests to third party gateways #783
feat: recover from failed HTTP requests to third party gateways #783
Conversation
add-on/src/lib/ipfs-request.js
Outdated
} | ||
// if error cannot be recovered via DNSLink | ||
// direct the request to the public gateway | ||
const recoverableViaPubGw = isRecoverableViaPubGw(request, state, ipfsPathValidator) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Including the redirect functionality was necessary in both onCompleted and onErrorOccurred, because of the different types of gateway failures. Many requests result in failure, others return 4xx or 5xx error codes.
Thank you for opening this @colinfruit! |
Hi @lidel, the basic structure is fine to review. I'm working on tests, finding a clean way to stub promises (browser.tabs.query/create), and reviewing the error codes that were added, to make sure I have all that we want, and none that we don't want. Glad to hear your comments! |
To elaborate a little more on the testing part of my work, I've been going through a couple of different libraries to see if any of them can promisify sinon-chrome. The only two that could theoretically work are then-chrome and chrome-promise. chrome-promise is no longer maintained, just bug fixes, and then-chrome is outdated and seemingly abandoned. The only other option afaik is stubbing the needed APIs manually. Has this been discussed before for this project, and is there a better way to accomplish this? |
@colinfruit I stumbled upon similar problem with testing WebExtension APIs before. On top of the problem with abandoned libraries, sometimes Chromium and Firefox have slight changes in some APIs, making a generic library not feasible. In redirect tests I ended up writing bare minimim input-output/side-effect tests for I think we should be fine with adding Let me know if you got any questions, will be glad to help if I can :) |
@lidel, that sounds good, except for the fact that it requires reworking the way the
I was under the impression that it would be bad practice to add a return value solely for the purposes of testing, but I'm happy to add them if you're OK with that? |
@lidel just added my tests as a working example so it's easier to see what I am doing, will remove them if your previous comment is what you want. :) |
|
||
before(function () { | ||
global.URL = URL | ||
browser.tabs = { ...browser.tabs, query: sinon.stub().resolves([{ id: 20 }]) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Otherwise this query will throw an error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great, thank you @colinfruit!
The current setup doesn't return anything, so in my current test setup I am checking that browser.create was called with the expected arguments
The way you wrote tests is absolutely correct. Most of request APIs are input-output based, but ones related to error recovery need to produce side-effect (new tab). All good.
A few final asks before we merge this:
- Let's frame language and names around "recovering from failed HTTP requests". Public gateway is a way of recovering, but its just an implementation detail that may change in the future while most of this code remains. This means we want to:
- rename
recoverViaPublicGateway
(config option) to something likerecoverFailedRequests
- rename funcitons and variables from
recoverableViaPubGw
torecoverable
- rename
- Would it be possible to recover from broken subdomain gateway links?
- example: https://bafybeiemxf5abjwjbikoz4mc3a3dla6ual3jsgpdr4cjr3oz3evfyavhwq.ipfs.broken-example.com/wiki/ fails at DNS lookup stage, would be cool to recover from this by redirecting subdomain-based gateways to
https://bafybeiemxf5abjwjbikoz4mc3a3dla6ual3jsgpdr4cjr3oz3evfyavhwq.ipfs.dweb.link/wiki/
- This is not a blocker, if you feel it requires additional work, we can add this in a separate PR.
- example: https://bafybeiemxf5abjwjbikoz4mc3a3dla6ual3jsgpdr4cjr3oz3evfyavhwq.ipfs.broken-example.com/wiki/ fails at DNS lookup stage, would be cool to recover from this by redirecting subdomain-based gateways to
recoverableErrorCodes.has(request.statusCode) | ||
if (recoverableViaPubGw) { | ||
const redirectUrl = ipfsPathValidator.resolveToPublicUrl(request.url, state.pubGwURLString) | ||
const redirect = { redirectUrl } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we drop redirect
and use redirectUrl
directly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like this is the cleanest way to do this. Without it we would have to worry about the dnslink redirect, and do something like const redirectUrl = redirect ? redirect.redirectUrl : null
to be able to use this with the same createTabWithURL
function.
thanks for the review, @lidel, resolved most of your suggestions. It would be cool to recover broken sub-domains. Maybe a separate issue to track this would be good? I'm glad to take a look at it if I have some time. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you! LGTM, excited about this!
I'll fill a new issue for subdomains shortly.
This change builds on top of #783 and: - adds support for recovery from DNS lookup failures - enables recovery for all HTTP Codes >= 400 - recovers `.eth` DNS failures bu reopening website on EthDNS gateway at `.eth.link` - simplifies some code paths and adds more tests Motivation: When a third-party IPFS gateway is discontinued or censored at DNS level, the IPFS Companion should retry request using currently active gateway set by the user (public or local). We also want to recover in situation when website with DNSLink has a valid DNS `TXT` record, but HTTP behind `A` record is down or unreachable. *Note*: right now the only real use for DNS recovery is support of .eth TLD via .eth.link gateway, however in the future this could provide means of working around DNS-based censorship (eg. by executing DNSLink lookups over libp2p as a fallback). closes #678, closes #640
This PR closes #640, enabling dead public gateways to be redirected to the default public gateway. Added as an experimental option, defaulting to
false
.