UNPKG

27.5 kBMarkdownView Raw
1# dweb-transports API
2Mitra Ardron, Internet Archive, mitra@mitra.biz
3
4This doc provides a concise API specification for the Dweb Javascript Transports Libraries.
5
6It was last revised (to match the code) on 23 April 2018.
7
8If you find any discrepancies please add an issue here.
9
10See [Dweb document index](./DOCUMENTINDEX.md) for a list of the repos that make up the Internet Archive's Dweb project, and an index of other documents.
11See [Writing Shims](./WRITINGSHIMS.md) for guidelines for adding a new Transport and adding shims to the Archive
12
13## General API notes and conventions
14We were using a naming convention that anything starting “p_” returns a promise so you know to "await" it if you want a result,
15this is being phased out as many functions now take a callback or promise.
16
17Ideally functions should take a String, Buffer or where applicable Object as parameters with automatic conversion.
18And anything that takes a URL should take either a string or parsed URL object.
19
20Note that example_block.html collects this from the URL and passes it to the library,
21which is intended to be a good way to see what is happening.
22
23Note: I am gradually (March2018) changing the API to take an opts {} dict. This process is incomplete, but I’m happy to see it accelerated if there is any code built on this, just let mitra@archive.org know.
24
25## Overview
26
27The Transport layer provides a layer that is intended to be independent of the underlying storage/transport mechanism.
28
29There are a set of classes:
30* *Transport*: superclass of each supported transport,
31* *TransportHTTP*: Connects to generic http servers, and handles contenthash: through a known gateway
32* *TransportIPFS*: Connects to IPFS, currently (April 2018) via WebSocketsStar (WSS)
33* *TransportYJS*: Implements shared lists, and dictionaries. Uses IPFS for transport
34* *TransportWEBTORRENT*: Integrates to Feross's WebTorrent library
35* *TransportGUN*: Integrates to the Gun DB
36* *Transports*: manages the list of conencted transports, and directs api calls to them.
37
38Calls are generally made through the Transports class which knows how to route them to underlying connections.
39
40Documents are retrieved by a list of URLs, where in each URL, the left side helps identify the transport, and the right side can be the internal format of the underlying transport BUT must be identifiable e.g. ipfs:/ipfs/12345abc or https://dweb.me/contenthash/Qm..., this format will evolve if a standard URL for the decentralized space is defined.
41
42The actual urls used might change as the Decentralized Web universe reaches consensus (for example dweb:/ipfs/Q123 is an alternative seen in some places)
43
44This spec will in the future probably add a variation that sends events as the block is retrieved to allow for streaming.
45
46## Transport Class
47
48Fields| 
49:---|---
50options | Holds options passed to constructor
51name|Short name of transport e.g. “HTTP”, “IPFS”
52supportURLs|Array of url prefixes supported e.g. [‘ipfs’,’http’]
53supportFunctions|Array of functions supported on those urls, current (April 2018) full list would be: `['fetch', 'store', 'add', 'list', 'reverse', 'newlisturls', "get", "set", "keys", "getall", "delete", "newtable", "newdatabase", "listmonitor"]`
54status|Numeric indication of transport status: Started(0); Failed(1); Starting(2); Loaded(3)
55
56### Setup of a transport
57Transport setup is split into 3 parts, this allows the Transports class to do the first phase on all the transports synchronously,
58then asynchronously (or at a later point) try and connect to all of them in parallel.
59
60##### static setup0 (options)
61First part of setup, create obj, add to Transports but dont attempt to connect, typically called instead of p_setup if want to parallelize connections. In almost all cases this will call the constructor of the subclass
62Should be synchronous and leave `status=STATUS_LOADED`
63```
64options Object fields including those needed by transport layer
65Resolves to Instance of subclass of Transport
66```
67Default options should be set in each transport, but can be overwritten,
68for example to overwrite the options for HTTP call it with
69`options={ http: { urlbase: “https://dweb.me:443/” } }`
70
71##### async p_setup1 (, cb)
72Setup the resource and open any P2P connections etc required to be done just once.
73Asynchronous and should leave `status=STATUS_STARTING` until it resolves, or `STATUS_FAILED` if fails.
74```
75cb (t)=>void If set, will be called back as status changes (so could be multiple times)
76Resolves to the Transport instance
77```
78
79##### async p_setup2 (, cb)
80Works like p_setup1 but runs after p_setup1 has completed for all transports.
81This allows for example YJS to wait for IPFS to be connected in TransportIPFS.setup1()
82and then connect itself using the IPFS object.
83```
84cb (t)=>void If set, will be called back as status changes (so could be multiple times)
85Resolves to the Transport instance
86```
87
88##### async p_setup(options, cb)
89A deprecated utility to simply setup0 then p_setup1 then p_setup2 to allow a transport to be started
90in one step, normally `Transports.p_setup` should be called instead.
91
92#### togglePaused(cb)
93Switch the state of the transport between STATUS_CONNECTED and STATUS_PAUSED,
94in the paused state it will not be used for transport but, in some cases, will still do background tasks like serving files.
95```
96cb(transport)=>void a callback called after this is run, may be used for example to change the UI
97```
98
99##### async p_status ()
100Check the status of the underlying transport. This may update the "status" field from the underlying transport.
101```
102returns: a numeric code for the status of a transport.
103```
104
105Code|Name|Means
106---|---|---
1070|STATUS_CONNECTED|Connected and can be used
1081|STATUS_FAILED|Setup process failed, can rerun if required
1092|STATUS_STARTING|Part way through the setup process
1103|STATUS_LOADED|Code loaded but havent tried to connect
1114|STATUS_PAUSED|It was launched, probably connected, but now paused so will be ignored by validfor()
112
113##### async stop(refreshstatus, cb)
114Stop the transport,
115```
116refreshstatus (optional) callback(transport instance) to the UI to update status on display
117cb(err, this)
118```
119### Transport: General storage and retrieval of objects
120##### p_rawstore(data)
121Store a opaque blob of data onto the decentralised transport.
122```
123data string|Buffer data to store - no assumptions made to size or content
124Resolves to url of data stored
125```
126
127##### p_rawfetch(url, {timeoutMS, start, end, relay})
128Fetch some bytes based on a url, no assumption is made about the data in terms of size or structure.
129
130Where required by the underlying transport it should retrieve a number if its "blocks" and concatenate them.
131
132There may also be need for a streaming version of this call, at this point undefined.
133```
134url string url of object being retrieved in form returned by link or p_rawstore
135timeoutMS Max time to wait on transports that support it (IPFS for fetch)
136start,end Inclusive byte range wanted (must be supported, uses a "slice" on output if transport ignores it.
137relay If first transport fails, try and retrieve on 2nd, then store on 1st, and so on.
138Resolves to string The object being fetched, (note currently (April 2018) returned as a string, may refactor to return Buffer)
139throws: TransportError if url invalid - note this happens immediately, not as a catch in the promise
140```
141
142### Transport: Handling lists
143##### p_rawadd(url, sig)
144Store a new list item, it should be stored so that it can be retrieved either by "signedby" (using p_rawlist)
145or by "url" (with p_rawreverse).
146
147The underlying transport can, but does not need to verify the signature,
148an invalid item on a list should be rejected by higher layers.
149```
150url String identifying list to add sig to.
151sig Signature data structure (see below - contains url, date, signedby, signature)
152 date - date of signing in ISO format,
153 urls - array of urls for the object being signed
154 signature - verifiable signature of date+urls
155 signedby - url of data structure (typically CommonList) holding public key used for the signature
156```
157##### seed({directoryPath, fileRelativePath, ipfsHash, urlToFile, torrentRelativePath}, cb)
158Seed the file to any transports that can handle it.
159```
160ipfsHash: When passed as a parameter, its checked against whatever IPFS calculates.
161 Its reported, but not an error if it doesn't match. (the cases are complex, for example the file might have been updated).
162urlFile: The URL where that file is available, this is to enable transports (e.g. IPFS) that just map an internal id to a URL.
163directoryPath: Absolute path to the directory, for transports that think in terms of directories (e.g. WebTorrent)
164 this is the unit corresponding to a torrent, and should be where the torrent file will be found or should be built
165fileRelativePath: Path (relative to directoryPath) to the file to be seeded.
166torrentRelativePath: Path within directory to torrent file if present.
167```
168
169##### p_rawlist(url)
170Fetch all the objects in a list, these are identified by the url of the public key used for signing.
171Note this is the 'signedby' parameter of the p_rawadd call, not the 'url' parameter.
172List items may have other data (e.g. reference ids of underlying transport)
173```
174url String with the url that identifies the list
175 (this is the 'signedby' parameter of the p_rawadd call, not the 'url' parameter
176Resolves to Array: An array of objects as stored on the list. Each of which is …..
177```
178Each item of the list is a dict: {"url": url, "date": date, "signature": signature, "signedby": signedby}
179
180##### p_rawreverse (url)
181Similar to p_rawlist, but return the list item of all the places where the object url has been listed.
182(not supported by most transports)
183```
184url String with the url that identifies the object put on a list
185 This is the “url” parameter of p_rawadd
186Resolves to Array objects as stored on the list (see p_rawlist for format)
187```
188
189##### listmonitor (url, cb, { current})
190Setup a callback called whenever an item is added to a list, typically it would be called immediately after a p_rawlist to get any more items not returned by p_rawlist.
191```
192url Identifier of list (as used by p_rawlist and "signedby" parameter of p_rawadd
193cb(obj) function(obj) Callback for each new item added to the list
194current true to send existing members as well as new
195 obj is same format as p_rawlist or p_rawreverse
196```
197
198##### async p_newlisturls(cl)
199Obtain a pair of URLs for a new list. The transport can use information in the cl to generate this or create something random (the former is encouraged since it means repeat tests might not generate new lists). Possession of the publicurl should be sufficient to read the list, the privateurl should be required to read (for some transports they will be identical, and higher layers should check for example that a signature is signed.
200```
201cl CommonList instance that can be used as a seed for the URL
202Returns [privateurl, publicurl]
203```
204
205### Transport: Support for KeyValueTable
206##### async p_newdatabase(pubkey) {
207Create a new database based on some existing object
208```
209pubkey: Something that is, or has a pubkey, by default support Dweb.PublicPrivate, KeyPair
210 or an array of strings as in the output of keypair.publicexport()
211returns: {publicurl, privateurl} which may be the same if there is no write authentication
212```
213
214##### async p_newtable(pubkey, table) {
215Create a new table,
216```
217pubkey: Is or has a pubkey (see p_newdatabase)
218table: String representing the table - unique to the database
219returns: {privateurl, publicurl} which may be the same if there is no write authentication
220```
221
222##### async p_set(url, keyvalues, value)
223Set one or more keys in a table.
224```
225url: URL of the table
226keyvalues: String representing a single key OR dictionary of keys
227value: String or other object to be stored (its not defined yet what objects should be supported, e.g. any object ?
228```
229
230##### async p_get(url, keys)
231Get one or more keys from a table
232```
233url: URL of the table
234keys: Array of keys
235returns: Dictionary of values found (undefined if not found)
236```
237
238##### async p_delete(url, keys)
239Delete one or more keys from a table
240```
241url: URL of the table
242keys: Array of keys
243```
244
245##### async p_keys(url)
246Return a list of keys in a table (suitable for iterating through)
247```
248url: URL of the table
249returns: Array of strings
250```
251
252##### async p_getall(url)
253Return a dictionary representing the table
254```
255url: URL of the table
256returns: Dictionary of Key:Value pairs, note take care if this could be large.
257```
258
259### Transports - other functions
260##### static async p_f_createReadStream(url, {wanturl, preferredTransports=[] })
261Provide a function of the form needed by <VIDEO> tag and renderMedia library etc
262```
263url Urls of stream
264wanturl True if want the URL of the stream (for service workers)
265preferredTransports: preferred order to select stream transports (usually determined by application)
266returns f(opts) => stream returning bytes from opts.start || start of file to opts.end-1 || end of file
267```
268
269##### static createReadStream(urls, opts, cb)
270Different interface, more suitable when just want a stream, now.
271```
272urls: Url or [urls] of the stream
273opts{
274 start, end: First and last byte wanted (default to 0...last)
275 preferredTransports: preferred order to select stream transports (usually determined by application)
276}
277returns open readable stream from the net via cb or promise
278```
279
280##### supports(url, funcl)
281Determines if the Transport supports url’s of this form. For example TransportIPFS supports URLs starting ipfs:
282```
283url identifier of resource to fetch or list
284Returns True if this Transport supports that type of URL
285throw TransportError if invalid URL
286```
287
288##### validFor(url, func, opts)
289True if the url and/or function is supported and the Transport is connected appropriately.
290
291##### p_info() and info(cb)
292Return a JSON with info about the server via promise or callback
293
294## Transports class
295The Transports Class manages multiple transports
296
297##### Properties
298```
299_transports List of transports loaded (internal)
300namingcb If set will be called cb(urls) => urls to convert to urls from names.
301_transportclasses All classes whose code is loaded e.g. {HTTP: TransportHTTP, IPFS: TransportIPFS}
302_optionspaused Saves paused option for setup
303
304```
305
306##### static _connected()
307```
308returns Array of transports that are connected (i.e. status=STATUS_CONNECTED)
309```
310
311##### static async p_connectedNames(cb)
312```
313returns via Promise or cb: Array of names transports that are connected (i.e. status=STATUS_CONNECTED)
314```
315##### static async p_connectedNamesParm()
316```
317resolves to: part of URL string for transports e.g. 'transport=HTTP&transport=IPFS"
318```
319
320##### static async p_statuses()
321```
322resolves to: a dictionary of statuses of transports e.g. { TransportHTTP: STATUS_CONNECTED }
323```
324
325##### static validFor(urls, func, options) {
326Finds an array or Transports that are STARTED and can support this URL.
327```
328urls: Array of urls
329func: Function to check support for: fetch, store, add, list, listmonitor, reverse
330 - see supportFunctions on each Transport class
331options checks supportFeatures
332Returns: Array of pairs of url & transport instance [ [ u1, t1], [u1, t2], [u2, t1]]
333```
334
335##### static async p_urlsValidFor(urls, func, options) {
336Async version of validFor for serviceworker and TransportsProxy
337
338
339##### static http()
340```
341returns instance of TransportHTTP if connected
342```
343
344##### static ipfs()
345```
346returns instance of TransportIPFS if connected
347```
348
349##### static webtorrent()
350```
351returns instance of TransportWEBTORRENT if connected
352```
353
354##### static gun()
355```
356returns instance of TransportGUN if connected
357```
358
359##### static async p_resolveNames(urls)
360See Naming below
361```
362urls mix of urls and names
363names if namingcb is set, will convert any names to URLS (this requires higher level libraries)
364```
365
366##### static async resolveNamesWith(cb)
367Called by higher level libraries that provide name resolution function.
368See Naming below
369```
370cb(urls) => urls Provide callback function
371```
372#### togglePaused(name, cb)
373Switch the state of a named transport between STATUS_CONNECTED and STATUS_PAUSED,
374in the paused state it will not be used for transport but, in some cases, will still do background tasks like serving files.
375```
376cb(transport)=>void a callback called after this is run, may be used for example to change the UI
377```
378
379##### static addtransport(t)
380```
381t: Add a Transport instance to _transports
382```
383
384##### static setup0(transports, options, cb)
385Calls setup0 for each transport based on its short name. Specially handles ‘LOCAL’ as a transport pointing at a local http server (for testing).
386```
387transports Array of short names of transports e.g. [‘IPFS’,’HTTP’,’GUN’]
388options Passed to setup0 on each transport
389cb Callback to be called each time status changes
390Returns: Array of transport instances
391```
392
393##### static async p_setup1(, cb)
394Call p_setup1 on all transports that were created in setup0(). Completes when all setups are complete.
395
396##### static async p_setup2(, cb)
397Call p_setup2 on all transports that were created in setup0(). Completes when all setups are complete.
398
399##### static async refreshstatus(t)
400Set the class of t.statuselement (if set) to transportstatus0..transportstatus4 depending on its status.
401```
402t Instance of transport
403```
404
405##### static connect({options}, cb)
406```
407options {
408 transports Array of abbreviations of transports e.g. ["HTTP","IPFS"] as provided in URL
409 defaulttransports Array of abbreviations of transports to use if transports is unset
410 paused Array of abbreviations of transports that should be paused (not started)
411 statuselement HTML element to build status display under
412 ... Entire options is passed to each setup0 and will include options for each Transport
413 cb If found called - no parameters else a promise is returned that resolves to undefined
414```
415}
416
417##### static async p_connect({options})
418Main connection process for a browser based application,
419```
420options - see connect() above
421```
422
423##### static async p_urlsFrom(url)
424Utility to convert to urls form wanted for Transports functions, e.g. from user input
425```
426url: Array of urls, or string representing url or representing array of urls
427return: Array of strings representing url
428```
429
430##### static async p_httpfetchurl(url)
431Return URLS suitable for caller to pass to fetch.
432```
433url: Array of urls, or string representing url or representing array of urls
434return: Array of strings representing url
435```
436
437### Multi transport calls
438Each of the following is attempted across multiple transports
439For parameters refer to underlying Transport call
440
441Call|Returns|Behavior
442---|---|---
443static async p_rawstore(data)|[urls]|Tries all and combines results
444static async p_rawfetch(urls, {timeoutMS, start, end, relay})|data|See note
445static async p_rawlist(urls)|[sigs]|Tries all and combines results
446static async p_rawadd(urls, sig)||Tries on all urls, error if none succeed
447static listmonitor(urls, cb, { current})||Tries on all urls (so note cb may be called multiple times)
448static p_newlisturls(cl)|[urls]|Tries all and combines results
449static async p_f_createReadStream(urls, options)|f(opts)=>stream|Returns first success
450static async p_get(urls, keys)|currently (April 2018) returns on first success, TODO - will combine results and relay across transports
451static async p_set(urls, keyvalues, value)|Tries all, error if none succeed
452static async p_delete(urls, keys)|Tries all, error if none succeed
453static async p_keys(urls|[keys]|currently (April 2018) returns on first success, TODO - will combine results and relay across transports
454static async p_getall(urls)|dict|currently (April 2018) returns on first success, TODO - will combine results and relay across transports
455static async p_newdatabase(pubkey)|{privateurls: [urls], publicurls: [urls]}|Tries all and combines results
456static async p_newtable(pubkey, table)|{privateurls: [urls], publicurls: [urls]}|Tries all and combines results
457static async p_connection(urls)||Tries all parallel
458static monitor(urls, cb, { current})||Tries all sequentially
459
460##### static async p_rawfetch(urls, {timeoutMS, start, end, relay})
461FOR NEW CODE USE `fetch` instead of p_rawfetch
462
463Tries to fetch on all valid transports until successful. See Transport.p_rawfetch
464```
465timeoutMS: Max time to wait on transports that support it (IPFS for fetch)
466start,end Inclusive byte range wanted - passed to
467relay If first transport fails, try and retrieve on 2nd, then store on 1st, and so on.
468```
469
470##### fetch(urls, {timeoutMS, start, end, relay}, cb)
471As for p_rawfetch but returns either via callback or Promise
472
473## httptools
474A utility class to support HTTP with or without TransportHTTP
475e.g. `httptools.http().p_httpfetch("http://foo.com/bar", {method: 'GET'} )`
476
477##### Common parameters
478```
479httpurl HTTP or HTTPS url
480wantstream True if want a stream returned
481retries Number of times to retry on failure at network layer (i.e. 404 doesnt trigger a retry)
482noCache Add Cache-Control: no-cache header
483```
484
485##### p_httpfetch(httpurl, init, {wantstream=false, retries=undefined})
486Fetch a url.
487
488```
489init: {headers}
490returns: Depends on mime type;
491 If application/json returns a Object,
492 If text/* returns text
493 Oherwise Buffer
494```
495
496##### p_GET(httpurl, {start, end, noCache, retries=12}, cb)
497Shortcut to do a HTTP/POST get, sets `mode: cors, redirect: follow, keepalive: true, cache: default`
498```
499start: First byte to retrieve
500end: Last byte to retrieve (undefined means end of file)
501returns (via Promise or cb) from p_httpfetch
502```
503Note that it passes start and end as the Range header, most servers support it,
504but it does not (yet) explicitly check the result.
505
506##### p_POST(httpurl, {contenttype, data, retries=0})
507Shortcut to do a HTTP/HTTPS POST. sets same options as p_GET
508```
509data: Data to send to fetch, typically the body,
510contenttype: Currently not passed as header{Content-type} because fetch appears to ignore it.
511returns (via Promise or cb) from p_httpfetch
512```
513
514## TransportHTTP
515A subclass of Transport for handling HTTP connections - both directly and for contenthash: urls.
516
517It looks at `options { http }` for its options.
518
519Option|Default|Meaning
520------|-------|-------
521urlbase|https://dweb.me:443|Connect to dweb.me for contenthash urls
522supportURLS|http:*, https:*, contenthash:*}| (TODO: may in the future support `dweb:/contenthash/*`)
523supportFunctions|fetch, store, add, list, reverse, newlisturls, get, set, keys, getall, delete, newtable, newdatabase|
524supportFeatures|fetch.range, noCache|it will fetch a range of bytes if specified in {start, end} to p_rawfetch()
525
526
527## TransportIPFS
528A subclass of Transport for handling IPFS connections
529
530The code works, however there are a number of key IPFS issues <TODO document here> that mean that not
531every IPFS `CID` will be resolvable, since:
532* IPFS javascript doesnt yet support CIDv1 so can't recognize the CIDs starting with "z"
533* WSS only can find blocks known about by peers connected to the same star.
534* urlstore on the archive.org gateway is not advertising the files in a way that WSS finds them.
535* Protocol Labs (IPFS)) have been unable to get WSS to connect to our gateway machine
536
537Other parts of this code work but just note that usage should be aware that problems may be to do
538with your specific configuration and use cases.
539
540It looks at `options { ipfs }` for its options.
541
542Option|Default|Meaning
543------|-------|-------
544repo|/tmp/dweb_ipfsv2700|Local file system (only relevant if running under Node)
545config Addresses |Swarm: ['/dns4/ws-star.discovery.libp2p.io/tcp/443/wss/p2p-websocket-star']}|Connects currently (April 2018) to ipfs.io, this may change.
546EXPERIMENTAL pubsub|true|Requires pubsub for list monitoring etc
547
548supportURLS = `ipfs:*` (TODO: may in the future support `dweb:/ipfs/*`)
549SupportFunctions (note YJS uses IPFS and supports some other functions):
550 `fetch, store`
551SupportFeatures:
552 fetch.range Not supported (currently May 2019))
553 noCache: Not actually supported, but immutable
554
555Currently there is code for p_f_createReadStream. It works but because IPFS cannot return an error even if it
556cannot open the stream, IPFS is usually set as the last choice transport for streams.
557
558## TransportYJS
559A subclass of Transport for handling YJS connections.
560Uses IPFS as its transport (other transports are possible with YJS and may be worth experimenting with)
561
562supportURLS = `yjs:*` (TODO: may in the future support `dweb:/yjs/*`)
563supportFunctions (note YJS uses IPFS and supports some other functions):
564 `fetch, add, list, listmonitor, newlisturls, connection, get, set, getall, keys, newdatabase, newtable, monitor`
565supportFeatures:
566 fetch.range Not supported (currently May 2019)
567 noCache: Not supported (currently May 2019)
568
569## TransportWEBTORRENT
570A subclass of Transport for handling WEBTORRENT connections (similar to, with interworking with BitTorrent)
571
572Note that currently (April 2018) this won't work properly in the ServiceWorker (SW) because SW dont support WebRTC
573When used with a SW, it will attempt to retrieve from the http backup URL that is in many magnet links.
574In the SW it will also generate errors about trackers because the only reason to use trackers is to get the WebRTC links.
575
576supportURLS = `magnet:*` (TODO: may in the future support `dweb:/magnet/*`)
577
578supportFunctions:
579 `fetch`, `createReadStream`
580
581supportFeatures:
582 fetch.range Not supported (currently May 2019)
583 noCache: Not actually supported, but immutable
584
585## TransportGUN
586A subclass of Transport for handling GUN connections (decentralized database)
587
588supportURLS = `gun:*` (TODO: may in the future support `dweb:/gun/*`)
589
590supportFunctions = `add`, `list`, `listmonitor`, `newlisturls`, `connection`, `get`, `set`, `getall`, `keys`, `newdatabase`, `newtable`, `monitor`
591supportFeatures:
592 noCache: Not supported (and cache flushing is hard)
593
594## TransportWOLK
595A subclass of Transport for handling the WOLK transport layer (decentralized, block chain based, incentivised storage)
596
597supportURLs = ['wolk'];
598
599supportFunctions = [ 'fetch', 'connection', 'get', 'set', ]; // 'store' - requires chunkdata; 'createReadStream' not implemented
600
601## Naming
602Independently from the transport, the Transport library can resolve names if provided an appropriate callback.
603See p_resolveNames(urls) and resolveNamesWith(cb)
604
605In practice this means that an application should do.
606```
607require('@internetarchive/dweb-transports)
608```
609When setup this way, then calls to most functions that take an array of urls will first try and expand names.
610
611The format of names currently (April 2018) is under development but its likely to be something like
612`dweb:/arc/archive.org/details/foo`
613to allow smooth integration with existing HTTP urls that are moving to decentralization.
614
\No newline at end of file