Skip to main content

Overview

Gateway Mode transforms APITHON from a passive protocol analyzer into an active API gateway. After successful Session Synchronization, APITHON launches a Flask web server that accepts standard OpenAI-compatible API requests and translates them into the target service’s internal protocol.

What Gateway Mode Does

Gateway Mode provides:

Protocol Translation

Converts OpenAI /v1/chat/completions format to the target’s internal streaming protocol

Authentication Layer

Implements Bearer token authentication to secure gateway access

Network Flexibility

Supports both localhost-only and LAN-wide deployment modes

Cross-Platform CLI

Generates platform-specific curl commands for Windows (PowerShell/CMD) and Linux (Bash)

Flask Server Architecture

APItHON uses Flask as a lightweight HTTP server framework:
from flask import Flask, request, jsonify

app = Flask(__name__)
API_KEY_GATEWAY = "UnHackerEnCapital"

The Gateway Endpoint

The core endpoint is defined at line 132 in apithon.py:
@app.route('/v1/chat/completions', methods=['POST'])
def apithon_gateway():
    auth_header = request.headers.get("Authorization")
    if auth_header != f"Bearer {API_KEY_GATEWAY}":
        return jsonify({"error": "Unauthorized"}), 401
    user_input = request.json.get("messages", [{}])[-1].get("content", "")
    output_text = ejecutar_request_protocolo(user_input)
    return jsonify({
        "choices": [{
            "message": {
                "role": "assistant", 
                "content": output_text
            }
        }], 
        "model": "apithon-v3"
    })

Endpoint Breakdown

Route: /v1/chat/completions
Method: POST
Purpose: OpenAI-compatible chat completion endpoint
1

Authentication Check

Validates the Authorization header contains the correct Bearer token.
if auth_header != f"Bearer {API_KEY_GATEWAY}":
    return jsonify({"error": "Unauthorized"}), 401
2

Message Extraction

Extracts the user’s message content from the OpenAI-style request body.
user_input = request.json.get("messages", [{}])[-1].get("content", "")
3

Protocol Execution

Calls ejecutar_request_protocolo() to send the message via the captured protocol.
4

Response Formatting

Wraps the response in OpenAI-compatible JSON structure.

Request Execution Logic

The ejecutar_request_protocolo function (lines 103-129) handles the actual protocol translation:
def ejecutar_request_protocolo(user_query):
    base_domain = urllib.parse.urlparse(SESS["target_url"]).netloc
    backend_endpoint = (
        f"https://{base_domain}/_/BardChatUi/data/assistant.lamda.BardFrontendService/StreamGenerate"
        f"?bl={SESS['build_id']}&f.sid={SESS['session_id']}&hl=es-419&_reqid=2202684&rt=c"
    )
    
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36",
        "Cookie": SESS["auth_cookie"],
        "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
        "X-Same-Domain": "1",
        "Origin": f"https://{base_domain}",
        "Referer": f"https://{base_domain}/"
    }
    
    inner_structure = [
        [user_query, 0, None, None, None, None, 0], 
        ["es-419"], 
        ["", "", "", None, None, None, None, None, None, ""], 
        SESS["internal_context"], 
        "eb594bcd367d878b1514dd3b7c68bb91"
    ]
    payload = {"f.req": json.dumps([None, json.dumps(inner_structure)]), "at": ""}
    
    try:
        r = requests.post(backend_endpoint, headers=headers, data=payload, impersonate="chrome120")
        patterns = re.findall(r'rc_[a-z0-9]+.*?\[\\"(.*?)\\"\]', r.text)
        if patterns:
            return patterns[-1].replace('\\\\n', '\n').replace('\\n', '\n').replace('\\"', '"')
        return "Aviso: Flujo de datos vacío."
    except Exception as e:
        return f"Error en el túnel: {str(e)}"

Endpoint Construction

The backend URL is dynamically constructed using captured tokens:
backend_endpoint = (
    f"https://{base_domain}/_/BardChatUi/data/assistant.lamda.BardFrontendService/StreamGenerate"
    f"?bl={SESS['build_id']}&f.sid={SESS['session_id']}&hl=es-419&_reqid=2202684&rt=c"
)
Parameters:
  • bl: Build ID (captured during synchronization)
  • f.sid: Session ID (captured during synchronization)
  • hl: Language hint (hardcoded to Spanish)
  • _reqid: Request ID (static for simplicity)
  • rt: Request type (“c” for chat)

Request Headers

Critical headers for protocol compatibility:
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36"
The X-Same-Domain header is critical for bypassing CSRF protections that expect same-origin requests.

Payload Structure

The request payload follows a nested JSON structure:
inner_structure = [
    [user_query, 0, None, None, None, None, 0],  # Message with metadata
    ["es-419"],                                   # Language code
    ["", "", "", None, None, None, None, None, None, ""],  # Optional parameters
    SESS["internal_context"],                    # Critical: conversation context
    "eb594bcd367d878b1514dd3b7c68bb91"           # Protocol version/checksum
]
payload = {"f.req": json.dumps([None, json.dumps(inner_structure)]), "at": ""}
Key Components:
  1. User query in first position of first array
  2. Language code for response formatting
  3. Empty optional parameter array
  4. Internal context token (maintains conversation state)
  5. Static protocol identifier
The internal_context token is the most critical element. Without it, the backend cannot maintain conversation continuity.

TLS Fingerprinting

APItHON uses curl_cffi with Chrome 120 impersonation:
from curl_cffi import requests

r = requests.post(backend_endpoint, headers=headers, data=payload, impersonate="chrome120")
This mimics Chrome’s TLS fingerprint, helping avoid detection as a bot or automation tool.

Response Parsing

The backend response is parsed using regex to extract the assistant’s message:
patterns = re.findall(r'rc_[a-z0-9]+.*?\[\\"(.*?)\\"\]', r.text)
if patterns:
    return patterns[-1].replace('\\\\n', '\n').replace('\\n', '\n').replace('\\"', '"')
Pattern Explanation:
  • rc_[a-z0-9]+: Matches response chunk identifiers
  • .*?\[\\"(.*?)\\"\]: Captures content between escaped quotes in JSON array
  • Uses last match (most recent/complete response)
  • Unescapes newlines and quotes

OpenAI Format Compatibility

The gateway accepts standard OpenAI API request format:
{
  "messages": [
    {
      "role": "user",
      "content": "Your message here"
    }
  ]
}
And returns OpenAI-compatible responses:
{
  "choices": [
    {
      "message": {
        "role": "assistant",
        "content": "Response from the target LLM"
      }
    }
  ],
  "model": "apithon-v3"
}
This compatibility allows APITHON to work with any tool or library that supports the OpenAI API format, such as LangChain, LlamaIndex, or custom applications.

Authentication with API_KEY_GATEWAY

Gateway access is protected by Bearer token authentication:
API_KEY_GATEWAY = "UnHackerEnCapital"

auth_header = request.headers.get("Authorization")
if auth_header != f"Bearer {API_KEY_GATEWAY}":
    return jsonify({"error": "Unauthorized"}), 401
Default Key: UnHackerEnCapital
Security Recommendation: Change the API_KEY_GATEWAY value before deploying in production or LAN mode. The default key is publicly known.

Usage Example

curl http://localhost:5000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer UnHackerEnCapital" \
  -d '{"messages": [{"role": "user", "content": "Hello"}]}'

Network Deployment Modes

Gateway Mode supports two network configurations:

Local Mode (Localhost)

Restricts access to the current machine only:
def run_gateway_service(bind_all=False):
    host = "0.0.0.0" if bind_all else "127.0.0.1"
    # ...
    app.run(host=host, port=5000, debug=False, use_reloader=False)
When bind_all=False:
  • Binds to 127.0.0.1
  • Only accessible from localhost
  • Ideal for personal use and testing

Use Case: Local Development

Perfect for testing integrations or using APITHON as a personal proxy for LLM services without exposing it to your network.

LAN Mode (Network-Wide)

Exposes the gateway to all devices on the local network: When bind_all=True:
  • Binds to 0.0.0.0 (all network interfaces)
  • Accessible from any device on the LAN
  • Automatically detects and displays LAN IP address
def get_lan_ip():
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(("8.8.8.8", 80))
        ip = s.getsockname()[0]
        s.close()
        return ip
    except Exception:
        return "127.0.0.1"

Use Case: Multi-Device Access

Share gateway access across multiple devices (laptops, tablets, smartphones) without installing APITHON on each one.
Security Notice: LAN mode exposes the gateway to all devices on your network. Ensure your network is trusted and consider changing the default API key.

Dynamic Tutorial Generation

APItHON automatically generates platform-specific usage instructions:
def mostrar_tutorial(host_ip):
    es_windows = platform.system() == "Windows"
    # ... prints tutorial ...

Platform Detection

The tutorial adapts based on the operating system:
curl.exe http://192.168.1.100:5000/v1/chat/completions -H "Content-Type: application/json" -H "Authorization: Bearer UnHackerEnCapital" -d "{\"messages\": [{\"role\": \"user\", \"content\": \"Hello\"}]}"
Uses curl.exe to avoid PowerShell’s Invoke-WebRequest alias and specific quote escaping.

Gateway Lifecycle

The gateway runs in a dedicated thread:
threading.Thread(target=run_gateway_service, args=(False,), daemon=True).start()

print("\n[MANTENIENDO PASARELA... Ctrl+C para cerrar]")
while True: 
    time.sleep(1)
  • Runs as a daemon thread (terminates when main thread exits)
  • Keeps the main thread alive with an infinite sleep loop
  • User must press Ctrl+C to stop

Error Handling

Authentication Failure

if auth_header != f"Bearer {API_KEY_GATEWAY}":
    return jsonify({"error": "Unauthorized"}), 401
Returns HTTP 401 with error message.

Protocol Execution Failure

try:
    r = requests.post(backend_endpoint, headers=headers, data=payload, impersonate="chrome120")
    # ...
except Exception as e:
    return f"Error en el túnel: {str(e)}"
Captures and returns exception details to the client.

Empty Response

if patterns:
    return patterns[-1].replace('\\\\n', '\n').replace('\\n', '\n').replace('\\"', '"')
return "Aviso: Flujo de datos vacío."
Returns a warning message if no response content is found.

Diagram: Gateway Request Flow

Integration Examples

Python with Requests

import requests

response = requests.post(
    "http://localhost:5000/v1/chat/completions",
    headers={
        "Content-Type": "application/json",
        "Authorization": "Bearer UnHackerEnCapital"
    },
    json={
        "messages": [
            {"role": "user", "content": "What is protocol interception?"}
        ]
    }
)

print(response.json()["choices"][0]["message"]["content"])

JavaScript with Fetch

fetch('http://localhost:5000/v1/chat/completions', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer UnHackerEnCapital'
  },
  body: JSON.stringify({
    messages: [
      { role: 'user', content: 'Explain gateway mode' }
    ]
  })
})
.then(res => res.json())
.then(data => console.log(data.choices[0].message.content));

Next Steps

Now that you understand Gateway Mode, explore how to use it in practice:

Quickstart Guide

Follow the step-by-step guide to set up and run APITHON

Protocol Interception

Deep dive into how tokens are captured

Session Synchronization

Learn about the validation process

API Reference

Complete API documentation and examples

Build docs developers (and LLMs) love