Skip to content

Commit

Permalink
fix infinite loop update checker in a specific condition
Browse files Browse the repository at this point in the history
close issue #1527
  • Loading branch information
Ousret committed Apr 5, 2024
1 parent c859191 commit eb93eab
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
- Removed support for keeping the original casing of HTTP headers. This come from an outer constraint by newer protocols, namely HTTP/2+ that normalize header keys by default.
From the HTTPie user perspective, they are "prettified" on the output by default. e.g. "x-hello-world" is displayed as "X-Hello-World".
- Fixed multipart form data having filename not rfc2231 compliant when name contain non-ascii characters. ([#1401](https://github.com/httpie/cli/issues/1401))
- Fixed issue where the configuration directory was not created at runtime that made the update fetcher run everytime. ([#1527](https://github.com/httpie/cli/issues/1527))

The plugins are expected to work without any changes. The only caveat would be that certain plugin explicitly require `requests`.
Future contributions may be made in order to relax the constraints where applicable.
Expand Down
4 changes: 4 additions & 0 deletions httpie/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ class Config(BaseConfigDict):
def __init__(self, directory: Union[str, Path] = DEFAULT_CONFIG_DIR):
self.directory = Path(directory)
super().__init__(path=self.directory / self.FILENAME)
# this one ensure we do not init HTTPie without the proper config directory
# there's an issue where the fetch_update daemon run without having the directory present. that induce a
# loop trying to fetch latest versions information.
self.ensure_directory()
self.update(self.DEFAULTS)

@property
Expand Down
4 changes: 2 additions & 2 deletions httpie/internal/daemons.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ def _spawn(args: List[str], process_context: ProcessContext) -> None:
_spawn_posix(args, process_context)


def spawn_daemon(task: str) -> None:
args = [task, '--daemon']
def spawn_daemon(task: str, *args: str) -> None:
args = [task, '--daemon', *args]
process_context = os.environ.copy()
if not is_frozen:
file_path = os.path.abspath(inspect.stack()[0][1])
Expand Down
28 changes: 23 additions & 5 deletions httpie/internal/update_warnings.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,24 +37,42 @@ def _read_data_error_free(file: Path) -> Any:
return {}


def _fetch_updates(env: Environment) -> str:
def _fetch_updates(env: Environment) -> None:
file = env.config.version_info_file
data = _read_data_error_free(file)

response = niquests.get(PACKAGE_INDEX_LINK)
response.raise_for_status()
try:
# HTTPie have a server that can return latest versions for various
# package channels, we shall attempt to retrieve this information once in a while
if hasattr(env.args, "verify"):
if env.args.verify.lower() in {"yes", "true", "no", "false"}:
verify = env.args.verify.lower() in {"yes", "true"}
else:
verify = env.args.verify
else:
verify = True

response = niquests.get(PACKAGE_INDEX_LINK, verify=verify)
response.raise_for_status()
versions = response.json()
except (niquests.exceptions.ConnectionError, niquests.exceptions.HTTPError):
# in case of an error, let's ignore to avoid looping indefinitely.
# (spawn daemon background task maybe_fetch_update)
versions = {
BUILD_CHANNEL: httpie.__version__
}

data.setdefault('last_warned_date', None)
data['last_fetched_date'] = datetime.now().isoformat()
data['last_released_versions'] = response.json()
data['last_released_versions'] = versions

with open_with_lockfile(file, 'w') as stream:
json.dump(data, stream)


def fetch_updates(env: Environment, lazy: bool = True):
if lazy:
spawn_daemon('fetch_updates')
spawn_daemon('fetch_updates', f'--verify={env.args.verify}')
else:
_fetch_updates(env)

Expand Down
15 changes: 15 additions & 0 deletions tests/test_config.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os.path
from pathlib import Path

import pytest
Expand All @@ -23,6 +24,20 @@ def test_default_options(httpbin):
}


def test_config_dir_is_created():
dir_path = str(get_default_config_dir()) + "--fake"

try:
os.rmdir(dir_path)
except FileNotFoundError:
pass

assert not os.path.exists(dir_path)
Config(dir_path)
assert os.path.exists(dir_path)
os.rmdir(dir_path)


def test_config_file_not_valid(httpbin):
env = MockEnvironment()
env.create_temp_config_dir()
Expand Down

0 comments on commit eb93eab

Please sign in to comment.