1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159 | from functools import cached_property
from pydantic_settings import BaseSettings
from openfoodfacts_proxy.__about__ import __version__ as sdk_version
from openfoodfacts_proxy.core.settings_models import (
AppSettings,
ClientSettings,
DatabaseSettings,
ExternalServiceSettings,
ImageSettings,
RateLimitSettings,
ReferenceSettings,
SchedulerSettings,
SearchSettings,
SyncSettings,
TaxonomySettings,
)
class Settings(BaseSettings):
"""Application settings loaded from environment variables."""
mongodb_uri: str = "mongodb://mongodb:27017"
mongodb_db: str = "openfoodfacts"
off_base_url: str = "https://world.openfoodfacts.org"
user_agent: str = f"OpenFoodFactsProxy/{sdk_version} (https://github.com/twsl/openfoodfacts-proxy)"
product_rate_limit: int = 15
search_rate_limit: int = 10
rate_limit_window_seconds: int = 60
delta_sync_interval_hours: int = 24
delta_index_url: str = "https://static.openfoodfacts.org/data/delta/index.txt"
full_dump_url: str = "https://static.openfoodfacts.org/data/openfoodfacts-mongodbdump.gz"
upstream_timeout_seconds: float = 30.0
reference_cache_ttl_seconds: int = 21600
search_a_licious_base_url: str = "https://search.openfoodfacts.org"
robotoff_base_url: str = "https://robotoff.openfoodfacts.org"
open_prices_base_url: str = "https://prices.openfoodfacts.org"
events_base_url: str = "https://events.openfoodfacts.org"
folksonomy_base_url: str = "https://api.folksonomy.openfoodfacts.org"
taxonomy_static_base_url: str = "https://static.openfoodfacts.org/data/taxonomies"
taxonomy_sync_datasets: str = "categories,brands,countries,ingredients,labels"
taxonomy_sync_interval_hours: int = 24
taxonomy_snapshot_ttl_seconds: int = 172800
taxonomy_suggestion_limit: int = 25
typed_search_prefetch_pages: int = 5
typed_search_prefetch_page_size: int = 50
startup_sync_enabled: bool = True
scheduler_enabled: bool = True
rewrite_image_urls: bool = True
image_rewriter_mode: str = "legacy"
image_route_base_url: str = "/images"
image_bucket_name: str = "openfoodfacts-images"
image_bucket_region: str = "eu-west-3"
image_bucket_prefix: str = "data"
image_source_hosts: str = "images.openfoodfacts.org,static.openfoodfacts.org"
image_source_path_prefix: str = "/"
image_strip_source_prefix: bool = False
image_rewrite_type: str = ""
image_path_prefix: str = ""
model_config = {"env_prefix": "OFF_PROXY_"}
@cached_property
def scheduler(self) -> SchedulerSettings:
return SchedulerSettings(
delta_sync_interval_hours=self.delta_sync_interval_hours,
taxonomy_sync_interval_hours=self.taxonomy_sync_interval_hours,
)
@cached_property
def sync(self) -> SyncSettings:
return SyncSettings(
delta_index_url=self.delta_index_url,
full_dump_url=self.full_dump_url,
user_agent=self.user_agent,
)
@cached_property
def taxonomy(self) -> TaxonomySettings:
return TaxonomySettings(
taxonomy_static_base_url=self.taxonomy_static_base_url,
taxonomy_sync_datasets=self.taxonomy_sync_datasets,
taxonomy_snapshot_ttl_seconds=self.taxonomy_snapshot_ttl_seconds,
taxonomy_suggestion_limit=self.taxonomy_suggestion_limit,
upstream_timeout_seconds=self.upstream_timeout_seconds,
user_agent=self.user_agent,
)
@cached_property
def rate_limit(self) -> RateLimitSettings:
return RateLimitSettings(
product_rate_limit=self.product_rate_limit,
search_rate_limit=self.search_rate_limit,
rate_limit_window_seconds=self.rate_limit_window_seconds,
)
@cached_property
def client(self) -> ClientSettings:
return ClientSettings(
off_base_url=self.off_base_url,
upstream_timeout_seconds=self.upstream_timeout_seconds,
user_agent=self.user_agent,
)
@cached_property
def image(self) -> ImageSettings:
return ImageSettings(
rewrite_image_urls=self.rewrite_image_urls,
image_rewriter_mode=self.image_rewriter_mode,
image_route_base_url=self.image_route_base_url,
image_bucket_name=self.image_bucket_name,
image_bucket_region=self.image_bucket_region,
image_bucket_prefix=self.image_bucket_prefix,
image_source_hosts=self.image_source_hosts,
image_source_path_prefix=self.image_source_path_prefix,
image_strip_source_prefix=self.image_strip_source_prefix,
image_rewrite_type=self.image_rewrite_type,
image_path_prefix=self.image_path_prefix,
)
@cached_property
def search(self) -> SearchSettings:
return SearchSettings(
typed_search_prefetch_pages=self.typed_search_prefetch_pages,
typed_search_prefetch_page_size=self.typed_search_prefetch_page_size,
)
@cached_property
def reference(self) -> ReferenceSettings:
return ReferenceSettings(
reference_cache_ttl_seconds=self.reference_cache_ttl_seconds,
)
@cached_property
def database(self) -> DatabaseSettings:
return DatabaseSettings(
mongodb_uri=self.mongodb_uri,
mongodb_db=self.mongodb_db,
)
@cached_property
def external_services(self) -> ExternalServiceSettings:
return ExternalServiceSettings(
robotoff_base_url=self.robotoff_base_url,
open_prices_base_url=self.open_prices_base_url,
events_base_url=self.events_base_url,
folksonomy_base_url=self.folksonomy_base_url,
)
@cached_property
def app(self) -> AppSettings:
return AppSettings(
startup_sync_enabled=self.startup_sync_enabled,
scheduler_enabled=self.scheduler_enabled,
)
settings = Settings()
|