|
1 | 1 | import io
|
| 2 | +import os |
| 3 | +import platform |
2 | 4 | import time
|
3 | 5 | import weakref
|
| 6 | +from functools import lru_cache |
| 7 | +from pathlib import Path |
| 8 | +import warnings |
4 | 9 |
|
5 | 10 | import asyncio
|
6 | 11 | import aiohttp
|
7 | 12 |
|
8 | 13 | from fsspec.asyn import AsyncFileSystem, sync, sync_wrapper
|
9 | 14 | from fsspec.exceptions import FSTimeoutError
|
10 | 15 |
|
11 |
| -from .utils import get_default_gateways |
12 |
| - |
13 | 16 | import logging
|
14 | 17 |
|
15 | 18 | logger = logging.getLogger("ipfsspec")
|
@@ -248,19 +251,92 @@ async def get_client(**kwargs):
|
248 | 251 | return aiohttp.ClientSession(**kwargs)
|
249 | 252 |
|
250 | 253 |
|
251 |
| -DEFAULT_GATEWAY = None |
| 254 | +def gateway_from_file(gateway_path): |
| 255 | + if gateway_path.exists(): |
| 256 | + with open(gateway_path) as gw_file: |
| 257 | + ipfs_gateway = gw_file.readline().strip() |
| 258 | + logger.debug("using IPFS gateway from %s: %s", gateway_path, ipfs_gateway) |
| 259 | + return AsyncIPFSGateway(ipfs_gateway) |
| 260 | + return None |
252 | 261 |
|
253 | 262 |
|
| 263 | +@lru_cache |
254 | 264 | def get_gateway():
|
255 |
| - global DEFAULT_GATEWAY |
256 |
| - if DEFAULT_GATEWAY is None: |
257 |
| - use_gateway(*get_default_gateways()) |
258 |
| - return DEFAULT_GATEWAY |
259 |
| - |
260 |
| - |
261 |
| -def use_gateway(*urls): |
262 |
| - global DEFAULT_GATEWAY |
263 |
| - DEFAULT_GATEWAY = MultiGateway([AsyncIPFSGateway(url) for url in urls]) |
| 265 | + """ |
| 266 | + Get IPFS gateway according to IPIP-280 |
| 267 | +
|
| 268 | + see: https://github.com/ipfs/specs/pull/280 |
| 269 | + """ |
| 270 | + |
| 271 | + # IPFS_GATEWAY environment variable should override everything |
| 272 | + ipfs_gateway = os.environ.get("IPFS_GATEWAY", "") |
| 273 | + if ipfs_gateway: |
| 274 | + logger.debug("using IPFS gateway from IPFS_GATEWAY environment variable: %s", ipfs_gateway) |
| 275 | + return AsyncIPFSGateway(ipfs_gateway) |
| 276 | + |
| 277 | + # internal configuration: accept IPFSSPEC_GATEWAYS for backwards compatibility |
| 278 | + if ipfsspec_gateways := os.environ.get("IPFSSPEC_GATEWAYS", ""): |
| 279 | + ipfs_gateway = ipfsspec_gateways.split()[0] |
| 280 | + logger.debug("using IPFS gateway from IPFSSPEC_GATEWAYS environment variable: %s", ipfs_gateway) |
| 281 | + warnings.warn("The IPFSSPEC_GATEWAYS environment variable is deprecated, please configure your IPFS Gateway according to IPIP-280, e.g. by using the IPFS_GATEWAY environment variable or using the ~/.ipfs/gateway file.", DeprecationWarning) |
| 282 | + return AsyncIPFSGateway(ipfs_gateway) |
| 283 | + |
| 284 | + # check various well-known files for possible gateway configurations |
| 285 | + if ipfs_path := os.environ.get("IPFS_PATH", ""): |
| 286 | + if ipfs_gateway := gateway_from_file(Path(ipfs_path) / "gateway"): |
| 287 | + return ipfs_gateway |
| 288 | + |
| 289 | + if home := os.environ.get("HOME", ""): |
| 290 | + if ipfs_gateway := gateway_from_file(Path(home) / ".ipfs" / "gateway"): |
| 291 | + return ipfs_gateway |
| 292 | + |
| 293 | + if config_home := os.environ.get("XDG_CONFIG_HOME", ""): |
| 294 | + if ipfs_gateway := gateway_from_file(Path(config_home) / "ipfs" / "gateway"): |
| 295 | + return ipfs_gateway |
| 296 | + |
| 297 | + if ipfs_gateway := gateway_from_file(Path("/etc") / "ipfs" / "gateway"): |
| 298 | + return ipfs_gateway |
| 299 | + |
| 300 | + system = platform.system() |
| 301 | + |
| 302 | + if system == "Windows": |
| 303 | + candidates = [ |
| 304 | + Path(os.environ.get("LOCALAPPDATA")) / "ipfs" / "gateway", |
| 305 | + Path(os.environ.get("APPDATA")) / "ipfs" / "gateway", |
| 306 | + Path(os.environ.get("PROGRAMDATA")) / "ipfs" / "gateway", |
| 307 | + ] |
| 308 | + elif system == "Darwin": |
| 309 | + candidates = [ |
| 310 | + Path(os.environ.get("HOME")) / "Library" / "Application Support" / "ipfs" / "gateway", |
| 311 | + Path("/Library") / "Application Support" / "ipfs" / "gateway", |
| 312 | + ] |
| 313 | + elif system == "Linux": |
| 314 | + candidates = [ |
| 315 | + Path(os.environ.get("HOME")) / ".config" / "ipfs" / "gateway", |
| 316 | + Path("/etc") / "ipfs" / "gateway", |
| 317 | + ] |
| 318 | + else: |
| 319 | + candidates = [] |
| 320 | + |
| 321 | + for candidate in candidates: |
| 322 | + if ipfs_gateway := gateway_from_file(candidate): |
| 323 | + return ipfs_gateway |
| 324 | + |
| 325 | + # if we reach this point, no gateway is configured |
| 326 | + raise RuntimeError("IPFS Gateway could not be found!\n" |
| 327 | + "In order to access IPFS, you must configure an " |
| 328 | + "IPFS Gateway using a IPIP-280 configuration method. " |
| 329 | + "Possible options are: \n" |
| 330 | + " * set the environment variable IPFS_GATEWAY\n" |
| 331 | + " * write a gateway in the first line of the file ~/.ipfs/gateway\n" |
| 332 | + "\n" |
| 333 | + "It's always best to run your own IPFS gateway, e.g. by using " |
| 334 | + "IPFS Desktop (https://docs.ipfs.tech/install/ipfs-desktop/) or " |
| 335 | + "the command line version Kubo (https://docs.ipfs.tech/install/command-line/). " |
| 336 | + "If you can't run your own gateway, you may also try using the " |
| 337 | + "public IPFS gateway at https://ipfs.io or https://dweb.link . " |
| 338 | + "However, this is not recommended for productive use and you may experience " |
| 339 | + "severe performance issues.") |
264 | 340 |
|
265 | 341 |
|
266 | 342 | class AsyncIPFSFileSystem(AsyncFileSystem):
|
|
0 commit comments