From 144075841cba6a966c775f42d03e7196abc5b673 Mon Sep 17 00:00:00 2001 From: Armon Avrahamy Date: Mon, 8 Sep 2025 10:45:10 +0300 Subject: [PATCH] Add Farelogix EK proxy settings --- .pre-commit-config.yaml | 16 +++---- deployment/helm/chart/values.yaml | 33 +++++++++++++++ docker-compose.yml | 8 ++++ nginx.conf | 41 ++++++++++++++++++ start.sh | 10 +++++ tests/test_proxy.py | 70 +++++++++++++++++++++++++++++-- 6 files changed, 166 insertions(+), 12 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fd44de4..e82ec69 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v6.0.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer @@ -12,38 +12,38 @@ repos: - id: check-json - id: check-case-conflict - repo: https://github.com/google/yamlfmt - rev: v0.14.0 + rev: v0.17.2 hooks: - id: yamlfmt exclude: "^deployment/helm/chart/templates/.*" - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.3.2 + rev: v0.12.12 hooks: - id: ruff args: [--fix] - id: ruff-format - repo: https://github.com/pycqa/isort - rev: 5.13.2 + rev: 6.0.1 hooks: - id: isort args: ["--profile", "black"] - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.8.0 + rev: v1.17.1 hooks: - id: mypy additional_dependencies: [types-requests, types-PyYAML] - repo: https://github.com/shellcheck-py/shellcheck-py - rev: v0.9.0.6 + rev: v0.11.0.1 hooks: - id: shellcheck - repo: 'https://github.com/rhysd/actionlint' - rev: v1.7.4 + rev: v1.7.7 hooks: - id: actionlint args: - -shellcheck - repo: https://github.com/gruntwork-io/pre-commit - rev: v0.1.15 + rev: v0.1.30 hooks: - id: helmlint - repo: https://github.com/norwoodj/helm-docs diff --git a/deployment/helm/chart/values.yaml b/deployment/helm/chart/values.yaml index 80a5f9c..0b0763b 100644 --- a/deployment/helm/chart/values.yaml +++ b/deployment/helm/chart/values.yaml @@ -135,6 +135,39 @@ env: [] # secretKeyRef: # name: channel-proxy-farelogix-aa # key: agent-password +# +# Farelogix EK example: +# - name: WP_CHANNELS_FARELOGIX_EK_HOST +# value: "ek.farelogix.com" +# - name: WP_CHANNELS_FARELOGIX_EK_PROXY_PASS +# value: "https://ek.farelogix.com" +# - name: WP_CHANNELS_FARELOGIX_EK_AGENT +# value: "agent" +# - name: WP_CHANNELS_FARELOGIX_EK_API_KEY +# valueFrom: +# secretKeyRef: +# name: channel-proxy-farelogix-ek +# key: api-key +# - name: WP_CHANNELS_FARELOGIX_EK_USERNAME +# valueFrom: +# secretKeyRef: +# name: channel-proxy-farelogix-ek +# key: username +# - name: WP_CHANNELS_FARELOGIX_EK_PASSWORD +# valueFrom: +# secretKeyRef: +# name: channel-proxy-farelogix-ek +# key: password +# - name: WP_CHANNELS_FARELOGIX_EK_AGENT_USER +# valueFrom: +# secretKeyRef: +# name: channel-proxy-farelogix-ek +# key: agent-user +# - name: WP_CHANNELS_FARELOGIX_EK_AGENT_PASSWORD +# valueFrom: +# secretKeyRef: +# name: channel-proxy-farelogix-ek +# key: agent-password secrets: {} resources: diff --git a/docker-compose.yml b/docker-compose.yml index 76576d3..59ec2b7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -24,6 +24,14 @@ services: - WP_CHANNELS_FARELOGIX_AA_PASSWORD=test-pass - WP_CHANNELS_FARELOGIX_AA_AGENT_USER=test-agent-user - WP_CHANNELS_FARELOGIX_AA_AGENT_PASSWORD=test-agent-pass + - WP_CHANNELS_FARELOGIX_EK_HOST=mockserver + - WP_CHANNELS_FARELOGIX_EK_PROXY_PASS=http://mockserver:80 + - WP_CHANNELS_FARELOGIX_EK_API_KEY=test-ek-key + - WP_CHANNELS_FARELOGIX_EK_AGENT=test-ek-agent + - WP_CHANNELS_FARELOGIX_EK_USERNAME=test-ek-user + - WP_CHANNELS_FARELOGIX_EK_PASSWORD=test-ek-pass + - WP_CHANNELS_FARELOGIX_EK_AGENT_USER=test-ek-agent-user + - WP_CHANNELS_FARELOGIX_EK_AGENT_PASSWORD=test-ek-agent-pass depends_on: mockserver: condition: service_healthy diff --git a/nginx.conf b/nginx.conf index a0ad511..df63c26 100644 --- a/nginx.conf +++ b/nginx.conf @@ -214,6 +214,47 @@ http { } } + location ~ ^/channel/farelogix-ek/(.*) { + proxy_pass $WP_CHANNELS_FARELOGIX_EK_PROXY_PASS/$1; + proxy_set_header Host $WP_CHANNELS_FARELOGIX_EK_HOST; + proxy_ssl_server_name on; + proxy_connect_timeout 30; + proxy_send_timeout 120; + proxy_read_timeout 120; + send_timeout 120; + + # Drop HTTP headers that are not needed (Wenrix headers) + proxy_set_header x-wenrix-operation ""; + proxy_set_header x-wenrix-trace-id ""; + proxy_set_header authorization ""; + proxy_set_header x-real-ip ""; + proxy_set_header x-forwarded-for ""; + + # Add API key header + proxy_set_header Ocp-Apim-Subscription-Key "$WP_CHANNELS_FARELOGIX_EK_API_KEY"; + + lua_need_request_body on; + + access_by_lua_block { + local agent = "$WP_CHANNELS_FARELOGIX_EK_AGENT" + local username = "$WP_CHANNELS_FARELOGIX_EK_USERNAME" + local password = "$WP_CHANNELS_FARELOGIX_EK_PASSWORD" + local agent_user = "$WP_CHANNELS_FARELOGIX_EK_AGENT_USER" + local agent_password = "$WP_CHANNELS_FARELOGIX_EK_AGENT_PASSWORD" + + ngx.req.read_body() + local body = ngx.req.get_body_data() + if body then + body = ngx.re.gsub(body, "#FLX_USERNAME#", username) + body = ngx.re.gsub(body, "#FLX_PASSWORD#", password) + body = ngx.re.gsub(body, "#FLX_AGENT#", agent) + body = ngx.re.gsub(body, "#FLX_AGENT_USER#", agent_user) + body = ngx.re.gsub(body, "#FLX_AGENT_PASSWORD#", agent_password) + end + ngx.req.set_body_data(body) + } + } + location /metrics { stub_status; } diff --git a/start.sh b/start.sh index e9cb6b3..a15dc8d 100644 --- a/start.sh +++ b/start.sh @@ -145,6 +145,16 @@ export WP_CHANNELS_FARELOGIX_UA_PASSWORD=${WP_CHANNELS_FARELOGIX_UA_PASSWORD:-} export WP_CHANNELS_FARELOGIX_UA_AGENT_USER=${WP_CHANNELS_FARELOGIX_UA_AGENT_USER:-} export WP_CHANNELS_FARELOGIX_UA_AGENT_PASSWORD=${WP_CHANNELS_FARELOGIX_UA_AGENT_PASSWORD:-} +# Farelogix EK +export WP_CHANNELS_FARELOGIX_EK_HOST=${WP_CHANNELS_FARELOGIX_EK_HOST:-ek.farelogix.com} +export WP_CHANNELS_FARELOGIX_EK_PROXY_PASS=${WP_CHANNELS_FARELOGIX_EK_PROXY_PASS:-${WP_SERVER_PROXY_PASS:-"https://${WP_CHANNELS_FARELOGIX_EK_HOST}"}} +export WP_CHANNELS_FARELOGIX_EK_API_KEY=${WP_CHANNELS_FARELOGIX_EK_API_KEY:-} +export WP_CHANNELS_FARELOGIX_EK_AGENT=${WP_CHANNELS_FARELOGIX_EK_AGENT:-} +export WP_CHANNELS_FARELOGIX_EK_USERNAME=${WP_CHANNELS_FARELOGIX_EK_USERNAME:-} +export WP_CHANNELS_FARELOGIX_EK_PASSWORD=${WP_CHANNELS_FARELOGIX_EK_PASSWORD:-} +export WP_CHANNELS_FARELOGIX_EK_AGENT_USER=${WP_CHANNELS_FARELOGIX_EK_AGENT_USER:-} +export WP_CHANNELS_FARELOGIX_EK_AGENT_PASSWORD=${WP_CHANNELS_FARELOGIX_EK_AGENT_PASSWORD:-} + # --------- # Replace environment variables in the nginx configuration diff --git a/tests/test_proxy.py b/tests/test_proxy.py index 54e858a..c6d9897 100644 --- a/tests/test_proxy.py +++ b/tests/test_proxy.py @@ -56,7 +56,11 @@ def test_farelogix_aa_request(proxy_url): request_headers = {"test-header": "should-remain"} - response = requests.post(f"{proxy_url}/channel/farelogix-aa/anything", json=test_body, headers=request_headers) + response = requests.post( + f"{proxy_url}/channel/farelogix-aa/anything", + json=test_body, + headers=request_headers, + ) if response.status_code != 200: print_request_debug(response, test_body, request_headers) assert response.status_code == 200 @@ -67,7 +71,10 @@ def test_farelogix_aa_request(proxy_url): # Verify headers verify_headers( request_info["headers"], - expected_present={"Test-Header": "should-remain", "Ocp-Apim-Subscription-Key": "test-aa-key"}, + expected_present={ + "Test-Header": "should-remain", + "Ocp-Apim-Subscription-Key": "test-aa-key", + }, expected_absent=[], ) @@ -84,6 +91,54 @@ def test_farelogix_aa_request(proxy_url): assert request_info["url"].endswith("/anything") +def test_farelogix_ek_request(proxy_url): + """Test that Farelogix EK proxy correctly handles the request.""" + test_body = { + "username": "#FLX_USERNAME#", + "password": "#FLX_PASSWORD#", + "agent": "#FLX_AGENT#", + "agentUser": "#FLX_AGENT_USER#", + "agentPassword": "#FLX_AGENT_PASSWORD#", + "otherField": "unchanged", + } + + request_headers = {"test-header": "should-remain"} + + response = requests.post( + f"{proxy_url}/channel/farelogix-ek/anything", + json=test_body, + headers=request_headers, + ) + if response.status_code != 200: + print_request_debug(response, test_body, request_headers) + assert response.status_code == 200 + + # Get request details from httpbin + request_info = response.json() + + # Verify headers + verify_headers( + request_info["headers"], + expected_present={ + "Test-Header": "should-remain", + "Ocp-Apim-Subscription-Key": "test-ek-key", + }, + expected_absent=[], + ) + + # Verify body transformations + received_body = request_info["json"] + assert received_body["username"] == "test-ek-user" + assert received_body["password"] == "test-ek-pass" + assert received_body["agent"] == "test-ek-agent" + assert received_body["agentUser"] == "test-ek-agent-user" + assert received_body["agentPassword"] == "test-ek-agent-pass" + assert received_body["otherField"] == "unchanged" # Verify unchanged fields + + # Verify URL path + assert request_info["url"].endswith("/anything") + + def test_travelfusion_request(proxy_url): """Test that Travelfusion proxy correctly handles the request.""" test_headers = { @@ -105,7 +160,11 @@ def test_travelfusion_request(proxy_url): """ # Use just the base endpoint without /anything - response = requests.post(f"{proxy_url}/channel/travelfusion/anything", data=test_body, headers=test_headers) + response = requests.post( + f"{proxy_url}/channel/travelfusion/anything", + data=test_body, + headers=test_headers, + ) if response.status_code != 200: print_request_debug(response, test_body, test_headers) assert response.status_code == 200 @@ -146,7 +205,10 @@ def test_travelfusion_request(proxy_url): def test_travelfusion_request_normal_path(proxy_url): """Test that Travelfusion proxy correctly handles the request.""" - test_headers = {"x-wenrix-operation": "should-be-removed", "x-wenrix-trace-id": "should-be-removed"} + test_headers = { + "x-wenrix-operation": "should-be-removed", + "x-wenrix-trace-id": "should-be-removed", + } # Sample XML request with placeholders test_body = """