Compare commits
2 Commits
d82926a4d1
...
88a0574e86
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88a0574e86 | ||
|
|
bf02af0192 |
45
api.py
45
api.py
@@ -350,6 +350,8 @@ def generate_preview():
|
|||||||
'apache_24': ConfigGenerator.generate_apache_24,
|
'apache_24': ConfigGenerator.generate_apache_24,
|
||||||
'haproxy_acl': ConfigGenerator.generate_haproxy_acl,
|
'haproxy_acl': ConfigGenerator.generate_haproxy_acl,
|
||||||
'haproxy_lua': ConfigGenerator.generate_haproxy_lua,
|
'haproxy_lua': ConfigGenerator.generate_haproxy_lua,
|
||||||
|
"haproxy_map": ConfigGenerator.generate_haproxy_map,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
generator_key = f"{app_type}_{app_variant}"
|
generator_key = f"{app_type}_{app_variant}"
|
||||||
@@ -398,6 +400,7 @@ def generate_preview():
|
|||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
return jsonify({'success': False, 'error': str(e)}), 500
|
return jsonify({'success': False, 'error': str(e)}), 500
|
||||||
|
|
||||||
|
|
||||||
@api_blueprint.route('/api/generate/raw', methods=['POST'])
|
@api_blueprint.route('/api/generate/raw', methods=['POST'])
|
||||||
def generate_raw_cidr():
|
def generate_raw_cidr():
|
||||||
try:
|
try:
|
||||||
@@ -409,6 +412,9 @@ def generate_raw_cidr():
|
|||||||
app_type = data.get('app_type', 'raw-cidr_txt')
|
app_type = data.get('app_type', 'raw-cidr_txt')
|
||||||
use_cache = data.get('use_cache', True)
|
use_cache = data.get('use_cache', True)
|
||||||
|
|
||||||
|
as_js = bool(data.get('as_js', False))
|
||||||
|
js_var = data.get('js_var', 'geoipBlocklist')
|
||||||
|
|
||||||
if app_type == 'raw-cidr':
|
if app_type == 'raw-cidr':
|
||||||
app_type = 'raw-cidr_txt'
|
app_type = 'raw-cidr_txt'
|
||||||
|
|
||||||
@@ -419,19 +425,31 @@ def generate_raw_cidr():
|
|||||||
cached = redis_cache.get_cached_config(countries, app_type, aggregate)
|
cached = redis_cache.get_cached_config(countries, app_type, aggregate)
|
||||||
if cached:
|
if cached:
|
||||||
if 'json' in app_type:
|
if 'json' in app_type:
|
||||||
extension = 'json'
|
if as_js:
|
||||||
mimetype = 'application/json'
|
extension = 'js'
|
||||||
|
mimetype = 'application/javascript'
|
||||||
|
filename = f"blocklist_{'_'.join(sorted(countries))}.{extension}"
|
||||||
|
body = f"const {js_var} = {cached['config']};\n"
|
||||||
|
else:
|
||||||
|
extension = 'json'
|
||||||
|
mimetype = 'application/json'
|
||||||
|
filename = f"blocklist_{'_'.join(sorted(countries))}.{extension}"
|
||||||
|
body = cached['config']
|
||||||
|
|
||||||
elif 'csv' in app_type:
|
elif 'csv' in app_type:
|
||||||
extension = 'csv'
|
extension = 'csv'
|
||||||
mimetype = 'text/csv'
|
mimetype = 'text/csv'
|
||||||
|
filename = f"blocklist_{'_'.join(sorted(countries))}.{extension}"
|
||||||
|
body = cached['config']
|
||||||
|
|
||||||
else:
|
else:
|
||||||
extension = 'txt'
|
extension = 'txt'
|
||||||
mimetype = 'text/plain'
|
mimetype = 'text/plain'
|
||||||
|
filename = f"blocklist_{'_'.join(sorted(countries))}.{extension}"
|
||||||
filename = f"blocklist_{'_'.join(sorted(countries))}.{extension}"
|
body = cached['config']
|
||||||
|
|
||||||
return Response(
|
return Response(
|
||||||
cached['config'],
|
body,
|
||||||
mimetype=mimetype,
|
mimetype=mimetype,
|
||||||
headers={
|
headers={
|
||||||
'Content-Disposition': f'attachment; filename="{filename}"',
|
'Content-Disposition': f'attachment; filename="{filename}"',
|
||||||
@@ -486,18 +504,25 @@ def generate_raw_cidr():
|
|||||||
all_networks.extend(nets)
|
all_networks.extend(nets)
|
||||||
|
|
||||||
if aggregate:
|
if aggregate:
|
||||||
all_networks = ConfigGenerator.aggregate_networks(all_networks)
|
all_networks = ConfigGenerator._aggregate_networks(all_networks)
|
||||||
else:
|
else:
|
||||||
all_networks = sorted(list(set(all_networks)))
|
all_networks = sorted(list(set(all_networks)))
|
||||||
|
|
||||||
config_text = json.dumps({
|
json_text = json.dumps({
|
||||||
'countries': countries,
|
'countries': countries,
|
||||||
'networks': all_networks,
|
'networks': all_networks,
|
||||||
'count': len(all_networks),
|
'count': len(all_networks),
|
||||||
'aggregated': aggregate
|
'aggregated': aggregate
|
||||||
}, indent=2)
|
}, indent=2)
|
||||||
filename = f"blocklist_{'_'.join(sorted(countries))}.json"
|
|
||||||
mimetype = 'application/json'
|
if as_js:
|
||||||
|
config_text = f"const {js_var} = {json_text};\n"
|
||||||
|
filename = f"blocklist_{'_'.join(sorted(countries))}.js"
|
||||||
|
mimetype = 'application/javascript'
|
||||||
|
else:
|
||||||
|
config_text = json_text
|
||||||
|
filename = f"blocklist_{'_'.join(sorted(countries))}.json"
|
||||||
|
mimetype = 'application/json'
|
||||||
|
|
||||||
elif 'csv' in app_type:
|
elif 'csv' in app_type:
|
||||||
config_text = ConfigGenerator.generate_csv(country_networks, aggregate=aggregate, redis_ips=None)
|
config_text = ConfigGenerator.generate_csv(country_networks, aggregate=aggregate, redis_ips=None)
|
||||||
@@ -547,6 +572,7 @@ def generate_raw_cidr():
|
|||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
return jsonify({'success': False, 'error': str(e)}), 500
|
return jsonify({'success': False, 'error': str(e)}), 500
|
||||||
|
|
||||||
|
|
||||||
@api_blueprint.route('/api/generate', methods=['POST'])
|
@api_blueprint.route('/api/generate', methods=['POST'])
|
||||||
def generate_config():
|
def generate_config():
|
||||||
try:
|
try:
|
||||||
@@ -622,6 +648,7 @@ def generate_config():
|
|||||||
'apache_24': ConfigGenerator.generate_apache_24,
|
'apache_24': ConfigGenerator.generate_apache_24,
|
||||||
'haproxy_acl': ConfigGenerator.generate_haproxy_acl,
|
'haproxy_acl': ConfigGenerator.generate_haproxy_acl,
|
||||||
'haproxy_lua': ConfigGenerator.generate_haproxy_lua,
|
'haproxy_lua': ConfigGenerator.generate_haproxy_lua,
|
||||||
|
'haproxy_map': ConfigGenerator.generate_haproxy_map,
|
||||||
}
|
}
|
||||||
|
|
||||||
generator_key = f"{app_type}_{app_variant}"
|
generator_key = f"{app_type}_{app_variant}"
|
||||||
|
|||||||
@@ -874,7 +874,7 @@ class ConfigGenerator:
|
|||||||
config += "}\n"
|
config += "}\n"
|
||||||
|
|
||||||
# Log conversion statistics
|
# Log conversion statistics
|
||||||
print(f"[INFO] Generated nginx map: {converted_count} regex patterns", flush=True)
|
#print(f"[INFO] Generated nginx map: {converted_count} regex patterns", flush=True)
|
||||||
|
|
||||||
if failed_count > 0:
|
if failed_count > 0:
|
||||||
print(f"[WARNING] Failed to convert {failed_count} networks to regex - check config file", flush=True)
|
print(f"[WARNING] Failed to convert {failed_count} networks to regex - check config file", flush=True)
|
||||||
@@ -1144,6 +1144,68 @@ class ConfigGenerator:
|
|||||||
"""
|
"""
|
||||||
return config
|
return config
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def generate_haproxy_map(country_networks: dict, aggregate: bool = True, redis_ips: set = None) -> str:
|
||||||
|
"""
|
||||||
|
Generate HAProxy MAP file (IP COUNTRY format)
|
||||||
|
"""
|
||||||
|
countries = sorted(country_networks.keys())
|
||||||
|
|
||||||
|
redisstats = None
|
||||||
|
if redis_ips:
|
||||||
|
redisstats = {"total": len(redis_ips), "unique": len(redis_ips), "deduped": 0}
|
||||||
|
|
||||||
|
handler = GeoIPHandler()
|
||||||
|
metadata = generate_metadata(countries, country_networks, redisstats, handler)
|
||||||
|
|
||||||
|
# Aggregate networks
|
||||||
|
all_networks = []
|
||||||
|
for networks in country_networks.values():
|
||||||
|
all_networks.extend(networks)
|
||||||
|
if redis_ips:
|
||||||
|
all_networks.extend(redis_ips)
|
||||||
|
|
||||||
|
if aggregate:
|
||||||
|
all_networks = ConfigGenerator._aggregate_networks(all_networks)
|
||||||
|
else:
|
||||||
|
all_networks = sorted(list(set(all_networks)))
|
||||||
|
|
||||||
|
# Generate header
|
||||||
|
config = "# " + "="*77 + "\n"
|
||||||
|
config += "# HAProxy MAP Configuration\n"
|
||||||
|
config += f"# Generated: {metadata['timestamp']}\n"
|
||||||
|
config += "# " + "="*77 + "\n"
|
||||||
|
config += "# \n"
|
||||||
|
config += f"# Countries: {metadata['countries_string']} ({metadata['country_count']} countries)\n"
|
||||||
|
config += f"# Total networks: {len(all_networks):,}\n"
|
||||||
|
config += "# \n"
|
||||||
|
config += "# Data sources:\n"
|
||||||
|
config += metadata['sources_formatted'] + "\n"
|
||||||
|
config += "# \n"
|
||||||
|
|
||||||
|
if metadata['redis']:
|
||||||
|
config += f"# {metadata['redis']['formatted']}\n"
|
||||||
|
config += "# \n"
|
||||||
|
|
||||||
|
config += "# Cache settings:\n"
|
||||||
|
config += f"# Max age: {metadata['cache_max_age_hours']} hours ({metadata['cache_max_age_days']:.1f} days)\n"
|
||||||
|
config += f"# Database: {metadata['cache_db_path']}\n"
|
||||||
|
config += "# \n"
|
||||||
|
config += "# Usage in HAProxy:\n"
|
||||||
|
config += "# acl banned_ips src -f /path/to/this_file.acl\n"
|
||||||
|
config += "# http-request deny if banned_ips\n"
|
||||||
|
config += "# \n"
|
||||||
|
config += "# " + "="*77 + "\n"
|
||||||
|
config += "\n"
|
||||||
|
|
||||||
|
# MAP BODY
|
||||||
|
for network in all_networks:
|
||||||
|
country = next((c for c, nets in country_networks.items() if network in nets), 'XX')
|
||||||
|
config += f"{network} {country}\n"
|
||||||
|
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def generate_haproxy_lua(country_networks: dict, aggregate: bool = True, redis_ips: set = None) -> str:
|
def generate_haproxy_lua(country_networks: dict, aggregate: bool = True, redis_ips: set = None) -> str:
|
||||||
"""Generate HAProxy Lua script with detailed metadata header"""
|
"""Generate HAProxy Lua script with detailed metadata header"""
|
||||||
@@ -1283,7 +1345,6 @@ class ConfigGenerator:
|
|||||||
|
|
||||||
return config
|
return config
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def generate_csv(country_networks: dict, aggregate: bool = True, redis_ips: set = None) -> str:
|
def generate_csv(country_networks: dict, aggregate: bool = True, redis_ips: set = None) -> str:
|
||||||
"""Generate CSV format with detailed metadata header"""
|
"""Generate CSV format with detailed metadata header"""
|
||||||
|
|||||||
@@ -35,7 +35,10 @@ APP_TYPES = [
|
|||||||
'nginx_map',
|
'nginx_map',
|
||||||
'nginx_deny',
|
'nginx_deny',
|
||||||
'apache_24',
|
'apache_24',
|
||||||
|
'apache_22',
|
||||||
'haproxy_acl',
|
'haproxy_acl',
|
||||||
|
'haproxy_lua',
|
||||||
|
'haproxy_map',
|
||||||
'raw-cidr_txt',
|
'raw-cidr_txt',
|
||||||
'raw-newline_txt',
|
'raw-newline_txt',
|
||||||
'raw-json',
|
'raw-json',
|
||||||
@@ -198,6 +201,7 @@ def process_country(country, networks_count, force=False):
|
|||||||
'apache_24': ConfigGenerator.generate_apache_24,
|
'apache_24': ConfigGenerator.generate_apache_24,
|
||||||
'haproxy_acl': ConfigGenerator.generate_haproxy_acl,
|
'haproxy_acl': ConfigGenerator.generate_haproxy_acl,
|
||||||
'haproxy_lua': ConfigGenerator.generate_haproxy_lua,
|
'haproxy_lua': ConfigGenerator.generate_haproxy_lua,
|
||||||
|
'haproxy_map': ConfigGenerator.generate_haproxy_map,
|
||||||
}
|
}
|
||||||
|
|
||||||
generator = generators.get(app_type)
|
generator = generators.get(app_type)
|
||||||
|
|||||||
@@ -54,6 +54,11 @@ const APP_VARIANTS = {
|
|||||||
value: 'lua',
|
value: 'lua',
|
||||||
text: 'Lua Script',
|
text: 'Lua Script',
|
||||||
description: 'Lua-based blocking script for advanced HAProxy setups'
|
description: 'Lua-based blocking script for advanced HAProxy setups'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'map',
|
||||||
|
text: 'Map File',
|
||||||
|
description: 'HAProxy map format (for use with -m ip / map files)'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -76,11 +76,9 @@ function showProgress() {
|
|||||||
window.progressInitTimeout = setTimeout(() => {
|
window.progressInitTimeout = setTimeout(() => {
|
||||||
if (progressMessage && progressMessage.textContent === 'Initializing...') {
|
if (progressMessage && progressMessage.textContent === 'Initializing...') {
|
||||||
progressMessage.innerHTML = `
|
progressMessage.innerHTML = `
|
||||||
<div>Initializing...</div>
|
<div>Request is being processed..</div>
|
||||||
<div style="margin-top: 10px; color: #856404; background: #fff3cd; padding: 10px; border-radius: 4px; font-size: 0.9em;">
|
<div style="margin-top: 10px; color: #856404; background: #fff3cd; padding: 10px; border-radius: 4px; font-size: 0.9em;">
|
||||||
Taking longer than expected...<br>
|
The task is queued and will start automatically.
|
||||||
All workers may be busy processing other requests.<br>
|
|
||||||
Please wait for the queue to clear.
|
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@@ -183,7 +181,7 @@ async function downloadConfiguration(formData) {
|
|||||||
document.body.removeChild(a);
|
document.body.removeChild(a);
|
||||||
|
|
||||||
if (fromCache) {
|
if (fromCache) {
|
||||||
showResult(`<i class="fas fa-bolt"></i> <strong>Lightning fast!</strong> Downloaded from cache: ${filename}`, 'success');
|
showResult(`<i class="fas fa-bolt"></i> <strong>Ready!</strong> Downloaded from cache: ${filename}`, 'success');
|
||||||
} else {
|
} else {
|
||||||
showResult(`Configuration downloaded successfully: ${filename}`, 'success');
|
showResult(`Configuration downloaded successfully: ${filename}`, 'success');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -352,120 +352,231 @@ const pollProgress = setInterval(async () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Endpoint 6: Generate Raw CIDR -->
|
<!-- Endpoint 6: Generate Raw CIDR -->
|
||||||
<div class="card mb-3">
|
<div class="card mb-3">
|
||||||
<div class="card-header api-header-post" onclick="toggleEndpoint('endpoint6')">
|
<div class="card-header api-header-post" onclick="toggleEndpoint('endpoint6')">
|
||||||
<div class="d-flex justify-content-between align-items-center">
|
<div class="d-flex justify-content-between align-items-center">
|
||||||
<div>
|
<div>
|
||||||
<span class="badge bg-success me-2">POST</span>
|
<span class="badge bg-success me-2">POST</span>
|
||||||
<code class="api-path">/api/generate/raw</code>
|
<code class="api-path">/api/generate/raw</code>
|
||||||
<span class="ms-3 text-muted">Generate raw CIDR blocklist</span>
|
<span class="ms-3 text-muted">Generate raw blocklist (TXT/CSV/JSON/JS)</span>
|
||||||
</div>
|
</div>
|
||||||
<i class="fas fa-chevron-down"></i>
|
<i class="fas fa-chevron-down"></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body collapse" id="endpoint6">
|
|
||||||
<h6 class="fw-bold">Description</h6>
|
|
||||||
<p>Generates a raw CIDR blocklist without application-specific configuration. Perfect for iptables, fail2ban, or custom implementations.</p>
|
|
||||||
|
|
||||||
<h6 class="fw-bold mt-3">Request Body</h6>
|
<div class="card-body collapse" id="endpoint6">
|
||||||
<pre><code>{
|
<h6 class="fw-bold">Description</h6>
|
||||||
|
<p>
|
||||||
|
Generates a raw blocklist without application-specific configuration.
|
||||||
|
Use this endpoint for programmatic integrations when you need structured output (JSON) or a JS-wrapped JSON payload.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h6 class="fw-bold mt-3">Request Body</h6>
|
||||||
|
<pre><code>{
|
||||||
"countries": [<span class="text-warning">"CN"</span>, <span class="text-warning">"RU"</span>],
|
"countries": [<span class="text-warning">"CN"</span>, <span class="text-warning">"RU"</span>],
|
||||||
"app_variant": <span class="text-warning">"txt"</span>,
|
"app_type": <span class="text-warning">"raw-json"</span>,
|
||||||
"aggregate": <span class="text-success">true</span>,
|
"aggregate": <span class="text-success">true</span>,
|
||||||
"use_cache": <span class="text-success">true</span>
|
"use_cache": <span class="text-success">true</span>,
|
||||||
|
"as_js": <span class="text-success">false</span>,
|
||||||
|
"js_var": <span class="text-warning">"geoipBlocklist"</span>
|
||||||
}</code></pre>
|
}</code></pre>
|
||||||
|
|
||||||
<h6 class="fw-bold mt-3">Parameters</h6>
|
<h6 class="fw-bold mt-3">Parameters</h6>
|
||||||
<table class="table table-sm">
|
<table class="table table-sm">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Type</th>
|
<th>Type</th>
|
||||||
<th>Required</th>
|
<th>Required</th>
|
||||||
<th>Description</th>
|
<th>Description</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>countries</code></td>
|
<td><code>countries</code></td>
|
||||||
<td>array</td>
|
<td>array</td>
|
||||||
<td><span class="badge bg-danger">required</span></td>
|
<td><span class="badge bg-danger">required</span></td>
|
||||||
<td>List of ISO 3166-1 alpha-2 country codes</td>
|
<td>List of ISO 3166-1 alpha-2 country codes</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>app_variant</code></td>
|
<td><code>app_type</code></td>
|
||||||
<td>string</td>
|
<td>string</td>
|
||||||
<td><span class="badge bg-secondary">optional</span></td>
|
<td><span class="badge bg-secondary">optional</span></td>
|
||||||
<td>Output format: <code>txt</code> (default) or <code>csv</code></td>
|
<td>
|
||||||
</tr>
|
Output format selector. Examples:
|
||||||
<tr>
|
<code>raw-json</code> (JSON), <code>raw-json</code> + <code>as_js=true</code> (JS wrapper).
|
||||||
<td><code>aggregate</code></td>
|
</td>
|
||||||
<td>boolean</td>
|
</tr>
|
||||||
<td><span class="badge bg-secondary">optional</span></td>
|
<tr>
|
||||||
<td>Aggregate IP networks (default: true)</td>
|
<td><code>aggregate</code></td>
|
||||||
</tr>
|
<td>boolean</td>
|
||||||
<tr>
|
<td><span class="badge bg-secondary">optional</span></td>
|
||||||
<td><code>use_cache</code></td>
|
<td>Aggregate IP networks (default: true)</td>
|
||||||
<td>boolean</td>
|
</tr>
|
||||||
<td><span class="badge bg-secondary">optional</span></td>
|
<tr>
|
||||||
<td>Use Redis cache if available (default: true)</td>
|
<td><code>use_cache</code></td>
|
||||||
</tr>
|
<td>boolean</td>
|
||||||
</tbody>
|
<td><span class="badge bg-secondary">optional</span></td>
|
||||||
</table>
|
<td>Use Redis cache if available (default: true)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
Only for <code>raw-json</code>.
|
||||||
|
When <code>true</code>, wraps JSON into JavaScript and returns <code>application/javascript</code> as:
|
||||||
|
<code>const <js_var> = {...};</code>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>js_var</code></td>
|
||||||
|
<td>string</td>
|
||||||
|
<td><span class="badge bg-secondary">optional</span></td>
|
||||||
|
<td>
|
||||||
|
Variable name used by <code>as_js</code> wrapper (default: <code>geoipBlocklist</code>).
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
<h6 class="fw-bold mt-3">Response</h6>
|
<h6 class="fw-bold mt-3">Responses</h6>
|
||||||
<p>Returns plain text file with CIDR blocks (one per line) or CSV with CIDR and country columns.</p>
|
<table class="table table-sm">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Mode</th>
|
||||||
|
<th>Content-Type</th>
|
||||||
|
<th>Body</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><code>raw-cidr_txt</code></td>
|
||||||
|
<td><code>text/plain</code></td>
|
||||||
|
<td>One CIDR per line</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>raw-cidr_csv</code></td>
|
||||||
|
<td><code>text/csv</code></td>
|
||||||
|
<td>CSV export</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>raw-cidr_json</code></td>
|
||||||
|
<td><code>application/json</code></td>
|
||||||
|
<td>JSON object with <code>countries</code>, <code>networks</code>, <code>count</code>, <code>aggregated</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>raw-cidr_json</code> + <code>as_js=true</code></td>
|
||||||
|
<td><code>application/javascript</code></td>
|
||||||
|
<td><code>const <js_var> = {...};</code></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
<h6 class="fw-bold mt-3">Response Headers</h6>
|
<h6 class="fw-bold mt-3">Responses</h6>
|
||||||
<table class="table table-sm">
|
<table class="table table-sm">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Header</th>
|
<th>Mode</th>
|
||||||
<th>Description</th>
|
<th>Content-Type</th>
|
||||||
</tr>
|
<th>Body</th>
|
||||||
</thead>
|
</tr>
|
||||||
<tbody>
|
</thead>
|
||||||
<tr>
|
<tbody>
|
||||||
<td><code>X-From-Cache</code></td>
|
<tr>
|
||||||
<td><code>true</code> or <code>false</code> - indicates if served from Redis</td>
|
<td><code>raw-cidr_txt</code></td>
|
||||||
</tr>
|
<td><code>text/plain</code></td>
|
||||||
<tr>
|
<td>One CIDR per line</td>
|
||||||
<td><code>X-Cache-Type</code></td>
|
</tr>
|
||||||
<td><code>redis</code> or <code>sqlite</code> - data source type</td>
|
<tr>
|
||||||
</tr>
|
<td><code>raw-cidr_csv</code></td>
|
||||||
<tr>
|
<td><code>text/csv</code></td>
|
||||||
<td><code>X-Generated-At</code></td>
|
<td>CSV export</td>
|
||||||
<td>Timestamp when config was generated</td>
|
</tr>
|
||||||
</tr>
|
<tr>
|
||||||
</tbody>
|
<td><code>raw-json</code></td>
|
||||||
</table>
|
<td><code>application/json</code></td>
|
||||||
|
<td>JSON object with <code>generated_at</code>, <code>countries</code>, <code>networks</code>, <code>total_networks</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>raw-json</code> + <code>as_js=true</code></td>
|
||||||
|
<td><code>application/javascript</code></td>
|
||||||
|
<td><code>const <js_var> = {...};</code></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
<h6 class="fw-bold mt-3">cURL Examples</h6>
|
<h6 class="fw-bold mt-3">Response Headers</h6>
|
||||||
|
<table class="table table-sm">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Header</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><code>X-From-Cache</code></td>
|
||||||
|
<td><code>true</code> or <code>false</code> - indicates if served from Redis</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>X-Cache-Type</code></td>
|
||||||
|
<td><code>redis-full</code> or computed cache type (e.g. <code>hybrid</code>)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>X-Generated-At</code></td>
|
||||||
|
<td>Timestamp when config was generated</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
<p class="mb-2"><strong>With cache (faster):</strong></p>
|
<h6 class="fw-bold mt-3">cURL Examples</h6>
|
||||||
<pre><code>curl -X POST <span id="curlUrl2"></span>/api/generate/raw \
|
|
||||||
|
<p class="mb-2"><strong>TXT (default):</strong></p>
|
||||||
|
<pre><code>curl -X POST <span id="curlUrl2"></span>/api/generate/raw \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{
|
-d '{
|
||||||
"countries": ["CN", "RU"],
|
"countries": ["CN", "RU"],
|
||||||
"app_variant": "txt",
|
"app_type": "raw-cidr_txt",
|
||||||
"aggregate": true,
|
"aggregate": true,
|
||||||
"use_cache": true
|
"use_cache": true
|
||||||
}' \
|
}' \
|
||||||
-o blocklist.txt</code></pre>
|
-o blocklist.txt</code></pre>
|
||||||
|
|
||||||
<p class="mb-2 mt-3"><strong>Force fresh data (slower but guaranteed up-to-date):</strong></p>
|
<p class="mb-2 mt-3"><strong>CSV:</strong></p>
|
||||||
<pre><code>curl -X POST <span id="curlUrl2b"></span>/api/generate/raw \
|
<pre><code>curl -X POST <span id="curlUrl2csv"></span>/api/generate/raw \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{
|
-d '{
|
||||||
"countries": ["CN", "RU"],
|
"countries": ["CN", "RU"],
|
||||||
"app_variant": "txt",
|
"app_type": "raw-cidr_csv",
|
||||||
"aggregate": true,
|
"aggregate": true,
|
||||||
"use_cache": false
|
"use_cache": true
|
||||||
}' \
|
}' \
|
||||||
-o blocklist_fresh.txt</code></pre>
|
-o blocklist.csv</code></pre>
|
||||||
</div>
|
|
||||||
</div>
|
<p class="mb-2 mt-3"><strong>JSON:</strong></p>
|
||||||
|
<pre><code>curl -X POST <span id="curlUrl2b"></span>/api/generate/raw \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"countries": ["CN", "RU"],
|
||||||
|
"app_type": "raw-json",
|
||||||
|
"aggregate": true,
|
||||||
|
"use_cache": true
|
||||||
|
}' \
|
||||||
|
-o blocklist.json</code></pre>
|
||||||
|
|
||||||
|
<p class="mb-2 mt-3"><strong>JS-wrapped JSON:</strong></p>
|
||||||
|
<pre><code>curl -X POST <span id="curlUrl2c"></span>/api/generate/raw \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"countries": ["CN", "RU"],
|
||||||
|
"app_type": "raw-json",
|
||||||
|
"aggregate": true,
|
||||||
|
"use_cache": true,
|
||||||
|
"as_js": true,
|
||||||
|
"js_var": "geoipBlocklist"
|
||||||
|
}' \
|
||||||
|
-o blocklist.js</code></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<!-- Endpoint 7: Generate Configuration -->
|
<!-- Endpoint 7: Generate Configuration -->
|
||||||
@@ -541,7 +652,7 @@ const pollProgress = setInterval(async () => {
|
|||||||
<ul>
|
<ul>
|
||||||
<li><strong>nginx:</strong> <code>geo</code>, <code>map</code>, <code>deny</code></li>
|
<li><strong>nginx:</strong> <code>geo</code>, <code>map</code>, <code>deny</code></li>
|
||||||
<li><strong>apache:</strong> <code>22</code> (Apache 2.2), <code>24</code> (Apache 2.4)</li>
|
<li><strong>apache:</strong> <code>22</code> (Apache 2.2), <code>24</code> (Apache 2.4)</li>
|
||||||
<li><strong>haproxy:</strong> <code>acl</code>, <code>lua</code></li>
|
<li><strong>haproxy:</strong> <code>acl</code>, <code>lua</code>, <code>map</code></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h6 class="fw-bold mt-3">Response</h6>
|
<h6 class="fw-bold mt-3">Response</h6>
|
||||||
|
|||||||
Reference in New Issue
Block a user