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

ipfs for image assets #173

Merged
merged 5 commits into from
Sep 28, 2016
Merged

ipfs for image assets #173

merged 5 commits into from
Sep 28, 2016

Conversation

WardCunningham
Copy link
Member

@WardCunningham WardCunningham commented Sep 18, 2016

Ping for and then use local gateway to fetch high resolution images when an ipfs version is available.

This pull request is on hold.

After all of these months I can't believe we still can't get CORS headers on IPFS requests.
https://github.com/ipfs/go-ipfs/search?q=CORS&type=Issues&utf8=%E2%9C%93

Update. We can get CORS headers.
screen shot 2016-09-18 at 6 07 29 am

@WardCunningham WardCunningham changed the title ping for and then use local gateway when ipfs version available ipfs for image assets Sep 18, 2016
@@ -12,6 +12,10 @@ emit = ($item, item) ->

bind = ($item, item) ->
$item.dblclick -> editor.textEditor $item, item
$item.find('img').dblclick -> dialog.open item.text, this
url = item.url
if item.ipfs?
Copy link
Member

Choose a reason for hiding this comment

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

I wonder if this is the best way of doing this - surely if the item is stored on ipfs the item.url will be a gateway address! Worth looking at the browser IPFS gateway plugins for inspiration, the Firefox on looks for ULRs that match the pattern https?://<public_gateway>/(ipfs|ipns)/$RESOURCE where by default <public_gateway> is ipfs.io gateway.ipfs.io ipfs.pics.

Copy link
Member Author

@WardCunningham WardCunningham Sep 18, 2016

Choose a reason for hiding this comment

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

The item url will be for the postcard image, a dataurl. Folks who want nothing to do with ipfs will get the same old postcards they use to get. Those who like ipfs will run local nodes and get fabulous service unavailable from public gateways.

$item.find('img').dblclick -> dialog.open item.text, this
url = item.url
if item.ipfs?
$.get "http://localhost:8080/ipfs/#{item.ipfs}", ->
Copy link
Member

Choose a reason for hiding this comment

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

This is likely to be slow. The Firefox plugin checks for the local gateway by polling it using the IPFS API.

Copy link
Member Author

Choose a reason for hiding this comment

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

I initiate the get when the page is rendered. I don't expect a result until the user double-clicks to enlarge the image. If ipfs is slow one can try later, then it will be fast because images are stored in the local node.

@WardCunningham
Copy link
Member Author

Ok, hold is off. This pull request is ready to merge.

The kind folks on IPFS IRC explained how to configure HTTPHeaders in the daemon. I've included these instructions in the demo page. I have this branch installed there for testing.

http://ward.asia.wiki.org/assets-in-ipfs.html

image

Copy link
Member

@paul90 paul90 left a comment

Choose a reason for hiding this comment

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

A couple of things I'm not sure about.

  • There appears to be an assumption that the item is being stored twice - at some URL, and also in IPFS. Wouldn't it make sense to just store it in IPFS and make the URL a IPFS gateway link? This would mitigate the risk of the two copies being different.
  • The check for a local IPFS gateway is probably best done centrally - rather than for each item (image in this case).
  • Would be good to add IPNS support.

@WardCunningham
Copy link
Member Author

I ask for each item because I want to initiate the ipfs retrieval of each item. There could be some wasted transfers from localhost to browser memory, but only in the case where someone has configured their local ipfs daemon which is their declaration of affinity toward ipfs. I'm happy to keep ipfs at arm's length until I discover I can't live without it.

@almereyda
Copy link

So a fallback to the public IPFS gateways is out of question?
I am just asking, as already hardcoding localhost:8080 seems to rather invite for a configurable ENV var, at least. Then, as a farm operator, I could decide where I want my user's IPFS access attempts are being directed.
This would also turn out useful if different IPFS federations serve different assetts for the same hash (highly unlikely).

@paul90
Copy link
Member

paul90 commented Sep 18, 2016

So a fallback to the public IPFS gateways is out of question?

At this stage this is very much a work in progress. We had some discussion about a fallback strategy for if a local gateway does not exist. Probably involves looking for a gateway on the origin site, then any sites the page has been forked from, before using the public IPFS gateway. N.B. the public gateways current still don't seem to set CORS headers correctly, so this is currently academic.

Personally, I think it would be nice if there was a way to leverage the IPFS gateway browser plugins. But, they look to have quite different capabilities currently, so that might not be practical.

@WardCunningham
Copy link
Member Author

It is certainly fair to question this implementation which sets a direction that is very different from anything we have done before. I've struggled to understand what benefit we get from ipfs that we couldn't do better ourselves by managing an assets directory next to the pages directory on every wiki-server install.

So a fallback to the public IPFS gateways is out of question?

The mere existence of the public gateway has been a source of confusion for me. The breakthrough in my own thinking is to realize that large images need not ever travel over http. There are surely weaknesses in how I am suggesting we engage ipfs but if we do only this much then the result could be glorious.

Wikipedia has Commons as a centralized web service to the world. We could make the public ipfs gateway our Commons. But if we use ipfs end-to-end then we've engaged a network that makes Commons unnecessary.

Consider Pluto, Common's image of the year.
http://ward.asia.wiki.org/pluto-image-of-the-year.html

The url encoded postcard Pluto in the json serves as both thumbnail and so-so expanded image. But if someone wants to admire the true beauty of the image they have to navigate to Wikipedia's download links and find the 70 MB version. Let's see if ipfs can better this experience.

image

@Kubuxu
Copy link

Kubuxu commented Sep 18, 2016

I would suggest to try using possible browser support for ipfs.

There isn't and really nice way of checking if it works but the best I can think off is to try downloading html representation of empty directory from web+fs:/ protocol.

Empty file would be better (or file with some short text) but I don't we have anything like that available in default ipfs repo.

Simple example using jQuery of checking if there is fs protocol support:

jQuery.get('web+fs:/ipfs/QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn').always((_, code) => { var fsIpfsWorks = (code === "success"); console.log(fsIpfsWorks)})

We are using web+fs scheme as it is possible that Chrome won't allow us to register fs: protocol as it might require web+ prefix. In Firefox supports both web+fs and `fs.

@paul90
Copy link
Member

paul90 commented Sep 18, 2016

Oh, and the other problem with how this current identifies a local IPFS gateway is that it performs a drive-by get of the resource identified by the hash. Which may never look at.

The problem really starts getting nasty if the hash points to something that is either copyright, or illegal in the user's jurisdiction.

Currently the IPFS server lacks the ability of placing a limit on its resource usage. This is potentially a problem unless I have plenty of spare bandwidth and disk space that IPFS can use (currently the server lacks means any limits on either). There are long running issues in both ipfs/faq and ipfs/go-ipfs about this.

There are similar related issues with public gateways - I see plenty of questions, and issues, raised in the various forums, but no real answer provided.

@Kubuxu
Copy link

Kubuxu commented Sep 18, 2016

There is limit on disk usage (by default 10GiB), there is no real limit on the network usage but it is something we are working on.

@paul90
Copy link
Member

paul90 commented Sep 18, 2016

I would suggest to try using possible browser support for ipfs.

If we are going to rely on a browser plug-in, far better to simply provide a link to the resource via the public IPFS gateway URL, and let the plug-in (if its installed) handle the routing to a local gateway.

@WardCunningham
Copy link
Member Author

WardCunningham commented Sep 18, 2016

I see the "drive-by get of the resource" Paul mentions as a feature of the wiki/ipfs interaction. It would be better if I were to just hint to ipfs that a retrieval request might be coming. Is this possible? And can I retrieve from the ipfs network once and then have my local storage released eventually? I recognize that I am now projecting my immediate application needs onto a system that provides for many other uses. These questions expose this pull request as an experiment. I'm excited to see what we discover.

This drive-by is similar to chrome doing a dns lookup of every link on pages it displays. Clicks work faster that way. Of course Google might have other motivations given that they often hit their own dns at 8.8.8.8, but privacy is another thread for another day.

@Kubuxu
Copy link

Kubuxu commented Sep 18, 2016

If we are going to rely on a browser plug-in, far better to simply provide a link to the resource via the public IPFS gateway URL, and let the plug-in (if its installed) handle the routing to a local gateway.

I wouldn't say so. Global gateways addresses are the hack and local redirection of them is hack on a hack. Global gateways are created for compatibility with old software, not to be exploited in a new software. The fs schema is proper solution for browsers as for now (on browsers that support it), as it is much cleaner and explicit.

@paul90
Copy link
Member

paul90 commented Sep 18, 2016

So, what would be nice is an IPFS request that simply confirms the availability of the requested item - looking at the IPFS commands nothing jumps out. This is why I suggested earlier that the presence of a local gateway is checked in the same way as the plug-in does it.

There is limit on disk usage (by default 10GiB)

Would be a case of the kettle calling the pot black, but this does not appear to be documented.

The fs schema is proper solution for browsers as for now (on browsers that support it)

And this requires the browser plugin to work, so is only supported on Firefox, Chrome, and Chromium?

@Kubuxu
Copy link

Kubuxu commented Sep 18, 2016

Yes and if browser plugin is installed.

Downloading from global gateway is not better than downloading from origin server just a bit less efficient as global gateways have to fetch this file too.

url = item.url
if item.ipfs?
$.get "http://localhost:8080/ipfs/#{item.ipfs}", ->
url = "http://localhost:8080/ipfs/#{item.ipfs}"
$item.find('img').dblclick -> dialog.open item.text, "<img style=\"width:100%\" src=\"#{url}\">"
$item.find('img').dblclick (event) ->
event.stopPropagation()
Copy link
Member Author

@WardCunningham WardCunningham Sep 18, 2016

Choose a reason for hiding this comment

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

This long-standing omission caused both dblclick handers to run.

@paul90
Copy link
Member

paul90 commented Sep 21, 2016

There is limit on disk usage (by default 10GiB)

Assume this is referring Datastore.StorageMax? I see a note from Nov 2015 that it was implemented, but from May this year I see: -

The Datastore.StorageMax setting does not limit how much diskspace the datastore can use. It's used only by the GC, together with Datastore.GCWatermark, to determine whether or not to run GC.

@Kubuxu
Copy link

Kubuxu commented Sep 21, 2016

Yes, and when GC runs it deletes all unpinned content.

EDIT: The message was changed as it isn't hard limit but only a hint. We wanted to implement it as hard limit but it is harder than we thought initially.

@paul90
Copy link
Member

paul90 commented Sep 21, 2016

Thanks

@WardCunningham
Copy link
Member Author

There has been some discussion of pinning on matrix.
https://vector.im/beta/#/room/#fedwiki:matrix.org

I suggest we discuss the way forward for this experiment in our wednesday hangout, 10am pacific. That's real soon now.
https://hangouts.google.com/hangouts/_/fqvicfjqsjgf5kfo7dtuswhxxae

@WardCunningham
Copy link
Member Author

I'll be amending this pull request with some suggestions that came up on our dev/user call this morning. There were lots of good ideas, but this is what I think is needed to get this request merged.

  • Add a timeout to the ipfs gateway request.
  • Manage the number of gateway requests.
  • Bonus: Add some console.log to watch this logic work.

This is understood to be only one step toward using ipfs well for image asset management. Other issues include authoring, pinning, and server-side participation in ipfs.

@ghost
Copy link

ghost commented Sep 22, 2016

Hey, just wanted to briefly announce that we released go-ipfs v0.4.3 the other day, which contains ipfs/kubo#2778 mentioned above. Cheers :)

@WardCunningham
Copy link
Member Author

@lgierth, thanks for the head's up. I'll make note of this in our install documentation and leave out anything about configuring cors. Of course we're hoping to spawn more intersections between our works.

@WardCunningham
Copy link
Member Author

Temporary workflow for posting ipfs backed images.

Install, init and launch ipfs daemon where you launch your browser. download

ipfs init
ipfs daemon

Drop your image into ipfs using the ipfs localhost webui. localhost
image
Copy the hash that ipfs provides. Drop your image into wiki. Edit the ipfs hash into your wiki json.

vi .wiki/yourwiki.org/pages/your-new-page
    {
      "type": "image",
      "ipfs": "QmXNVRJoSq8N3KHecropuvfh7iQ1Lth11jpVL2xkpdLxCA",
      "id": "ab5e7395fde139d1",
      "url": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABA...
      "caption": "Uploaded image"
    },

Browse to your new page from a wiki with this pull request installed.

open 'http://asia.wiki.org/yourwiki.org/your-new-page'

Post links to your wiki pages for us to view.

@WardCunningham
Copy link
Member Author

WardCunningham commented Sep 25, 2016

I have made the changes to this pull request promised in the comment above.

  • Add a timeout to the ipfs gateway request, 30 seconds, in background.
  • Manage the number of gateway requests, one only on plugin (wiki-client) load.
  • Bonus: Add some console.log to watch this logic work, described below.

We now test for the existence of a localhost ipfs gateway by fetching a sentinel value, wiki, by its unique ipfs id. We encourage early adopters to pin this to their localhost repo before starting the ipfs daemon.

echo wiki | ipfs add
ipfs daemon

We perform the sentinel check only once per wiki-client load and log the ajax status as follows.

ipfs gateway success
ipfs gateway error
ipfs gateway timeout

@Kubuxu suggested this detection approach. ipfs/kubo#3256

@WardCunningham
Copy link
Member Author

We agreed to focus on rendering from ipfs as a motivator for writing transporters or other software with specialized and privileged access to an ipfs node. This is still an important use case. But I wonder, if someone bothers to setup a daemon on their browser localhost, how can that be used to safely write?

@jbenet offered this suggestion a year ago: #130.

I can see two concerns, authorization and privacy.

Authorization

We authorize wiki writes to the authenticated owner of a server-hosted site. We can further restrict some functions (server-side components) to the server administrator. A farm can have many site owners but only one server administrator. An adjacent ipfs node would seem to deserve administrator privilege.

I'm personally excited by the thought of end users engaging their own ipfs localhost node when they are authoring pages on a farm where they are only guest owner. This brings the authorization to a space where they have some native write privilege. Unfortunately browsers protect users from the javascript they load.

Electron offers the ability to sidestep some browser protections. @nrn got us started with electron but we couldn't figure out why we needed it. This might be it.

Privacy

We respect the firewalls that surround personal machines and corporate networks. Mostly we've accepted their restrictions as facts to be lived with by concentrating logic in the browser where it can cross multiple firewalls the right way.

The ipfs protocols jump firewalls in order to preserve the data it holds. The ids provide some security by obscurity but an additional layer of crypto would be needed to be seriously private. It is possible to configure an ipfs network of peers independent of the public network, but this seems error prone.

Proxy

A simple experiment would be to support the logic of #130 with a single function, cors enabled, post to add, localhost visible, proxy.

A proxy could be configured as the server-side of an IPFS plugin for those who run wiki on localhost, a stand-alone application for those who don't, or as additional configuration options on the existing go-ipfs gateway.

Transporter

Transporters don't have a good authorization story to tell. They are also http services at their core which disrespects the alternative networking aspect of ipfs. Finally, the postcard squeeze logic wants to run close to the html5 dom which isn't available outside the dom.

@WardCunningham
Copy link
Member Author

Added banner when ipfs version is available but not used because not yet configured. This links to here for now. This could be trying to help too much. I could see hating it.
image

@paul90
Copy link
Member

paul90 commented Sep 26, 2016

That is way too intrusive. It is also potentially wrong, it might not be available if the IPFS server(s) it was pinned to are not currently themselves available.

For those seeing this will probably be asking: "What is IPFS?", "What does it give me?" and "Why would I want it?" and just maybe how to install it. But, this is really something for the wiki owner to be concerned with. Not something that should concern the casual visitor to the wiki for who this should all be transparent.

To use the image of Pluto, above, as an example. Just because a user has IPFS installed does not mean that they want the full 8000x8000 (or even have a display that can do it justice, though if they did they'd have to break it out of the jQuery Dialog to do it any justice).

The postcard sized image viewer really need to change from the current jQuery Dialog to a proper browser window/tab. As with the thumbnail, it should display the image at a size that is appropriate for the window. If other resolutions of the image are available it would be good to provide links, that way the user could download a higher resolution version should they choose - much like the wikimedia commons.

@WardCunningham
Copy link
Member Author

Ok, I'll back this out.

@WardCunningham
Copy link
Member Author

WardCunningham commented Sep 28, 2016

I've removed the banner notice that additional content is available on an alternate network, the ipfs. An author that provides on that network can include a link to network participation information in the image caption. This is consistent with the posture that we are providing alternative network services to authors and readers, not improving the capabilities of our http-based network with the alternative service. This does not prevent us from developing our own large asset management capabilities within our own servers.

The ipfs network provides an alternative approach to crossing the firewalls that we encounter at each edge of the public internet. I remain personally interested in their experiment and would like to participate. But we must consider ourselves ultimately responsible for the quality and uniformity of service within our own federation.

image

@paul90 paul90 merged commit 42eaa73 into master Sep 28, 2016
@paul90 paul90 deleted the ward/ipfs branch September 28, 2016 16:35
@paul90
Copy link
Member

paul90 commented Sep 28, 2016

Published as part of + wiki-client@0.8.1

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

Successfully merging this pull request may close these issues.

4 participants