Skip to content
This repository was archived by the owner on Feb 12, 2024. It is now read-only.

Commit f84438a

Browse files
committed
Revise README changes and add example web page
1 parent 7b0921e commit f84438a

File tree

2 files changed

+129
-15
lines changed

2 files changed

+129
-15
lines changed

README.md

+42-15
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,11 @@ Consult the [Roadmap](/ROADMAP.md) for a complete state description of the proje
3939
- [HTTP-API](#http-api)
4040
- [IPFS Core examples (use IPFS as a module)](#ipfs-core-examples-use-ipfs-as-a-module)
4141
- [Create a IPFS node instance](#create-a-ipfs-node-instance)
42-
- [Startup (in Node.js or browser)](#startup-in-node.js-or-browser)
43-
- [Adding a file](#adding-a-file)
44-
- [Retrieving a file](#retrieving-a-file)
42+
- [Find IPFS in Node.js](#find-ipfs-in-nodejs)
43+
- [Find IPFS in the Browser](#find-ipfs-in-the-browser)
44+
- [Robust Initialization and libp2p-webrtc-star Signaling](#robust-initialization-and-libp2p-webrtc-star-signaling)
45+
- [Add a file](#add-a-file)
46+
- [Retrieve a file](#retrieve-a-file)
4547
- [More to come](#more-to-come)
4648
- [API](#api)
4749
- [Generic API](#generic-api)
@@ -146,6 +148,8 @@ The HTTP-API exposed by the js-ipfs daemon follows the [`http-api-spec`](https:/
146148

147149
#### Create a IPFS node instance
148150

151+
The basic startup flow involves (optionally) creating a Repo, creating an IPFS node, `init`-ing it so it can generate its keys, `load`-ing its configuration, and putting it online with `goOnline`. Here is a structural example:
152+
149153
```JavaScript
150154
// IPFS will need a repo, it can create one for you or you can pass
151155
// it a repo instance of the type IPFS Repo
@@ -179,18 +183,42 @@ node.init({ emptyRepo: true, bits: 2048 }, (err) => {
179183
180184
Below are some more examples of JavaScript IPFS in action.
181185
182-
#### Startup (in Node.js or browser)
186+
#### Find IPFS in Node.js
183187
184-
There's still a bit of work required to start up a node in a robust way (i.e. without requiring the user to manually `js-ipfs init`). Here is one way to do it.
188+
If you are working in Node.js and did `npm install ipfs`, or if you are working in a browser environment that exposes Node builtins like `require`, you should get an IPFS node like this:
185189
186190
```javascript
187-
// Find the IPFS implementation
188-
const IPFS = typeof Ipfs !== 'undefined' ? Ipfs // browser global
189-
: typeof require === 'function' ? require('ipfs') // cjs require
190-
: throw new Error('could not load IPFS')
191-
192-
// Make an IPFS node
191+
const IPFS = require('ipfs')
193192
var ipfs = new IPFS()
193+
```
194+
195+
#### Find IPFS in the Browser
196+
197+
If you are in a normal browser Javascript environment, and loaded IPFS via the minified build or the [unpkg CDN](#use-in-a-browser-using-a-script-tag), you should get an IPFS node like this:
198+
199+
```javascript
200+
var ipfs = new Ipfs()
201+
```
202+
203+
Make sure your script loads after the IPFS library, so that the `Ipfs` global will be defined.
204+
205+
#### Robust Initialization and libp2p-webrtc-star Signaling
206+
207+
There's still a bit of work required to start up an in-browser node in a robust way, so that it will work whether or not there is an existing initialized IPFS repo in the user's browser. If there isn't one, you need to call `init` as above, but if there is one, calling `init` will fail. Moreover, there's currently no good way to check if you need to call `init` or not.
208+
209+
Also, an in-browser node isn't able to call up normal IPFS nodes over raw TCP; it can only communicate over Websockets and WebRTC. Currently, there are no Websockets or WebRTC bootstrap nodes run by the IPFS maintainers. You will probably want to set up a [libp2p-webrtc-star signaling server](https://github.com./libp2p/js-libp2p-webrtc-star) so nodes used in your application can find each other:
210+
211+
```bash
212+
npm i libp2p-webrtc-star -g
213+
star-sig
214+
```
215+
216+
You will then want to point IPFS nodes used in your application at your signaling server, so they can connect to each other. This is accomplished by adding an address to the node's configuration referencing the signaling server, of the form `/libp2p-webrtc-star/ip4/<server-ip>/tcp/<server-port>/ws/ipfs/<peer-id>`, where `<peer-id>` is the peer ID of the node that the address is being added to. This causes the node to think of itself as being contactable through the signaling server. It will then initializes its libp2p-webrtc-star implementation and automatically peer with other nodes using the same server.
217+
218+
Below is an example which initializes an IPFS node in a browser safely, whether a node has already been initialized by the current domain or not. It also configures `libp2p-webrtc-star` communication, using a signaling server running on the local host. (Note that since IPFS node configuration information is stored in IndexedDB in browsers, opening two tabs of this code from a local file in the same browser won't work, because they'll share the same node keys and identity. Either run the code from multiple domains, or run it in two different browsers, like Chrome and Firefox.)
219+
220+
```javascript
221+
// We assume you already have your IPFS node in `ipfs`, as in the two examples above.
194222

195223
// Init a repo in the given IPFS node it if hasn't got one already. Calls the
196224
// setup callback, passing the normal callback, after first initialization.
@@ -218,7 +246,7 @@ initIfNeeded(ipfs, (callback) => {
218246
if (err) {
219247
throw err
220248
}
221-
   // Add at least one libp2p-webrtc-star address. Without an address like this
249+
// Add at least one libp2p-webrtc-star address. Without an address like this
222250
// the libp2p-webrtc-star transport won't be installed, and the resulting
223251
// node won't be able to dial out to libp2p-webrtc-star addresses.
224252
var star_addr = ('/libp2p-webrtc-star/ip4/127.0.0.1/tcp/9090/ws/ipfs/' +
@@ -250,7 +278,7 @@ initIfNeeded(ipfs, (callback) => {
250278
})
251279
```
252280
253-
#### Adding a file
281+
#### Add a file
254282
255283
Once you have an IPFS node up and running, you can add files to it from `Buffer`s, `Readable` streams, or [arrays of objects of a certain form](https://github.com./ipfs/interface-ipfs-core/tree/master/API/files#add). If you don't have `Buffer` conveniently available (say, because you're in a browser without the Node API handy), it's available as a property of the IPFS node.
256284
@@ -264,14 +292,13 @@ ipfs.files.add(ipfs.Buffer.from('Hello world'), (err, returned) => {
264292
})
265293
```
266294
267-
#### Retrieving a file
295+
#### Retrieve a file
268296
269297
To retrieve the contents of a file, you can use the [cat method](https://github.com./ipfs/interface-ipfs-core/tree/master/API/files#cat), which will call your callback with a Node.js-style `Readable` stream.
270298
271299
```javascript
272300
ipfs.files.cat('QmNRCQWfgze6AbBCaT1rkrkV5tJ2aP4oTNPb5JZcXYywve',
273301
(err, content_stream) => {
274-
275302
if (err) {
276303
throw err
277304
}

examples/in-browser/index.html

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<title>IPFS in the Browser</title>
5+
<script src="https://unpkg.com/ipfs/dist/index.min.js"></script>
6+
<script type="text/javascript">
7+
// Set this if you have a libp2p-webrtc-star server
8+
// Something like
9+
// const SIGNALING_SERVER = '/libp2p-webrtc-star/ip4/127.0.0.1/tcp/9090/ws/ipfs/'
10+
const SIGNALING_SERVER = null
11+
12+
// Make an IPFS node
13+
var ipfs = new Ipfs()
14+
15+
// Init a repo in the given IPFS node it if hasn't got one already. Calls the
16+
// setup callback, passing the normal callback, after first initialization.
17+
// Calls the normal callback directly after subsequent initializations. Calls
18+
// the normal callback with an error parameter if there is an error.
19+
function initIfNeeded (ipfs, setup, callback) {
20+
ipfs.init((err) => {
21+
if (!err) {
22+
// This is the first time we have started a node
23+
setup(callback)
24+
} else if (err.message == 'repo already exists') {
25+
// The node already exists
26+
callback()
27+
} else {
28+
callback(err)
29+
}
30+
})
31+
}
32+
33+
// Init the node
34+
initIfNeeded(ipfs, (callback) => {
35+
// On first initialization, do some setup
36+
// Get the node config we just init-ed
37+
ipfs.config.get((err, config) => {
38+
if (err) {
39+
throw err
40+
}
41+
42+
if (SIGNALING_SERVER) {
43+
44+
// Add at least one libp2p-webrtc-star address. Without an address like this
45+
// the libp2p-webrtc-star transport won't be installed, and the resulting
46+
// node won't be able to dial out to libp2p-webrtc-star addresses.
47+
var star_addr = (SIGNALING_SERVER + config.Identity.PeerID)
48+
ipfs.config.set('Addresses.Swarm[1]', star_addr, (err) => {
49+
if (err) {
50+
throw err
51+
}
52+
// Continue down the already-initialized code path
53+
callback()
54+
})
55+
} else {
56+
// No signaling server is known. Just cointinue without it.
57+
// We don't want to spam the console in our demo
58+
callback()
59+
}
60+
})
61+
}, (err) => {
62+
// If the repo was already initialized, or after the first-time initialization
63+
// code is run, we'll do this.
64+
if (err) {
65+
throw err
66+
}
67+
// Have the node set itself up
68+
ipfs.load(() => {
69+
// Go online and connect to things
70+
ipfs.goOnline(() => {
71+
console.log('Online status: ', ipfs.isOnline() ? 'online' : 'offline')
72+
document.getElementById("status").innerHTML= 'Node status: ' + (ipfs.isOnline() ? 'online' : 'offline')
73+
// TODO: Write your code here!
74+
// Use methods like ipfs.files.add, ipfs.files.get, and so on in here
75+
// Methods requiring buffers can use ipfs.Buffer
76+
})
77+
})
78+
})
79+
</script>
80+
</head>
81+
<body>
82+
<h1>IPFS in the Browser</h1>
83+
<p>This page creates an IPFS node in your browser and drops it into the global Javascript namespace as <em>ipfs</em>. Open the console to play around with it.</p>
84+
<p>Note that opening two tabs of this page in the same browser won't work well, because they will share node configuration. You'll end up trying to run two instances of the same node, with the same private key and identity, which is a Bad Idea.</p>
85+
<div id="status">Node status: offline</div>
86+
</body>
87+
</html>

0 commit comments

Comments
 (0)