Can a header be added if content is served from a gateway?

Hi,

I am hosting a gateway but would like to add a header that should tell the user to install the IPFS companion addon and a local node.
This is only for content that’s served with the intent to be visible in a website.

Is this possible? If so, how?

Cheers,
Mark

1 Like

Well the IPFS gateway itself cannot do that to my knowledge, but if you are running a reverse proxy in front of the gateway (and common wisdom is that you should), then that reverse proxy may have the option to do this.

In particular nginx has ngx_http_sub_module that can be used to replace an arbitrary string in the returned output with something else. Note that that module is not build by default so depending on your configuration you have to install the module separately or build from source.
Similarly, Apache has the ext_filter_module that can launch a filtering CGI script (much slower). Here’s a StackOverflow question that lists other possible options: https://serverfault.com/q/46449

Your condition that it’s only for content that’s served with the intent to be visible in a website unfortunately does not map to any well-defined concept in HTTP, however I’d argue that there is an ancient “good-enough” proxy for this information available in the form of the User-Agent’s Mozilla/5.0 token. In short graphical webbrowsers of all kind declare themselves as compatible with this very old product, but CLI tools and text browser do not. So I’d venture to say that it is safe to make your conditional based on the presence of that string in the User-Agent request header.

Let me know if anything comes out of this!

1 Like

Note this breaks the security guarantees. You will be serving content that does not match the requested CID, as you will be modifying it. I might be wrong, but I think the cloudflare extension thing actually verified that content displayed matched what was requested.

1 Like

Hmm… I thought about that when I wrote that reply. Maybe limiting the modification of content to just IPNS would be preferable. I mean, it would still be a non-faithful reply, but at least IPNS doesn’t carry any the “content matches CID” guarantee you mentioned and is expected to change over time. It would still not be a faithful relaying of content of course, but at least it doesn’t break stuff in any obvious way.

Here’s another thing I just considered: A much cleaner way to do it could involve redirecting requests from web browser to some frame/iframe page that embeds the original content with some request parameter (such as ?embedded-notice-frame=true). Server then sees this parameter, skips the redirect to the frame page and passes it on to the IPFS gateway as usual. The actual page content will not be modified. A very nice side-effect of this, is that the HTML and styles of the parent document does not risk being accidentally or purposely being modified by the embedded page (which should be treated as untrusted content in this case).

There may be some nice way to avoid the parameter to not confuse client-side scripts looking at their page’s query string, but none of the possible headers I found for this (X-Requested-With, Cookies, Referer, Origin) looked particularly promising. [Cookies and Referer are often blocked amongst certain user groups, Origin does not appear to be send on same-origin requests and X-Requested-With is only set by some JavaScript libraries.]
Something that could work however is calling .contentWindow.history.pushState(null, "", url_with_the_parameter); (docs) on the iframe DOM element from the parent document using JavaScript as soon as possible. If JavaScript is disabled, then having the extra parameter is very unlikely to have any effect on the embedded page anyways.
Note: Generating the outer document should definitely be done on the server, not on the client using JavaScript. Good old SSI, gives a good-enough and very fast mini scripting language for this available on both Apache and nginx.

Sorry for the long reply, but when typing I just had the IFrame idea and had to research it / thing it through. :wink:

Hang on. Sorry if this is obvious. But are you saying that a go-ipfs client doesn’t validate that the returned content would generate the same CID(s) as what was requested. Or is this statement specific to the http gateway?

No, I am saying that the browser does not validate content downloaded via HTTP from a [remote] IPFS gateway.

go-ipfs of course validates everything, and if you use your local gateway you can be certain that content is validated. If you use a 3rd party gateway the browser will not tell you if that is serving you content altered in some way, though.

1 Like

This is awesome!
I did actually think about the iframe way but had no clue how to frame it (pun intended) so left it out.

I think the iframe way would be acceptable.

Just to remind people what i’m actually trying to solve.
I’m trying to make the user aware that a local IPFS client should be installed. Everything then works just fine! If the user uses a gateway then he/she should be made aware that using an IPFS client is better and you’ll get to see a banner till you get that local client. You could also go as far as rate limiting visitors that don’t use a local IPFS client.

This concept would drive adaption of IPFS as well :slight_smile:

The only downside i can see is where you’d visit a website on a device where you can’t easily get a local node installed (like on a smartphone).

Glad you like it! :slightly_smiling_face:

As for mobile devices: You can generally detect such devices by searching for the strings Mobile (all Apple mobile devices and most Android Smartphones) and Tablet (most Android Tablets) in the User-Agent string. Eventually we’d want to show a (possibly different) notification on these devices too, but for a start limiting the notification to desktop browser will suffice.

What web server are you using? If it’s nginx, I could maybe help you out some.

It is nginx.

I was tempted to stay away from iframes as it adds quite a bit more complexity as opposed to just running it with reverse proxy help (my current setup).

Note that i have barely no traffic on my gateway. I’m not advertising it or added it to the list of public gateways. But i’d like to, just as my little way of supporting IPFS a little. But then i saw the post from Pinata where they are (right now) being put in insane bandwidth usage simply because their gateway gets used more and more. Also to serve data that they themselves are not serving. So i wanted to figure out a way to still have it but not “limitless”.

To sum it up. I’d probably need:

I’m still a bit unsure how to properly do the iframe approach. As you’d want something like: “ipfs.domain.tld/ipns/” to just work on that domain. But you’d have to do some fancy magic to redirect your url to within the iframe.
Also, the iframe is “just an url” too. What prevents people from just grabbing that url which is the actual gateway? You can do more magic to only let the gateway work from that one domain with the iframe.

But now the setup does become increasingly more complicated!

@obo20 just pinging you in here too. You might find this interesting.