SOAP XML request works in SOAP UI, but fails in n8n (ContractFilter / SOAPAction issue)

Hi everyone,
I’m trying to send a SOAP request in n8n using the HTTP Request node. I have verified that the same request (headers, XML body, auth) works perfectly in SOAP UI, but it consistently fails in n8n.

:white_check_mark: What works in SOAP UI:

  • Method: POST
  • Headers:
    • Content-Type: text/xml; charset=utf-8
    • SOAPAction: "http://tempuri.org/SomeService/SomeMethod" ← inside double quotes
  • Auth: Basic Auth (username + password)
  • XML Body (structure similar to this):
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
  <soapenv:Header/>
  <soapenv:Body>
    <tem:SomeMethod>
      <tem:Param1>...</tem:Param1>
      <tem:Param2>...</tem:Param2>
    </tem:SomeMethod>
  </soapenv:Body>
</soapenv:Envelope>


## Describe the problem/error/question

## What is the error message (if any)?

## Please share your workflow

(Select the nodes on your canvas and use the keyboard shortcuts CMD+C/CTRL+C and CMD+V/CTRL+V to copy and paste the workflow.)


## Share the output returned by the last node

<!-- If you need help with data transformations, please also share your expected output. -->

## Information on your n8n setup

* **n8n version:**
* **Database (default: SQLite):**
* **n8n EXECUTIONS_PROCESS setting (default: own, main):**
* **Running n8n via (Docker, npm, n8n cloud, desktop app):**
* **Operating system:**

Hey @emir.kurklu hope all is good. Welcome to the community.

Ok now, this is an interesting topic to work on.

Let’s build everything from scratch, including a small mock server.


Server: app.py
from fastapi import FastAPI
from pydantic import BaseModel
from starlette.middleware.wsgi import WSGIMiddleware

from spyne import Application, ServiceBase, rpc, Unicode, Integer
from spyne.protocol.soap import Soap11
from spyne.server.wsgi import WsgiApplication


# -------- SOAP service --------
class DemoSoapService(ServiceBase):
    @rpc(Unicode, _returns=Unicode)
    def say_hello(ctx, name):
        return f"Hello, {name}"

    @rpc(Integer, Integer, _returns=Integer)
    def add(ctx, a, b):
        return a + b

    @rpc(Unicode, _returns=Unicode)
    def ping(ctx, msg):
        return f"PONG:{msg}"


soap_app = Application(
    [DemoSoapService],
    tns="urn:example.soap.demo",
    in_protocol=Soap11(validator="lxml"),
    out_protocol=Soap11(),
)
soap_wsgi = WsgiApplication(soap_app)

# -------- FastAPI (REST) --------
app = FastAPI(title="SOAP + REST Demo")

# Mount SOAP under /soap  (WSDL available at /soap/?wsdl)
app.mount("/soap", WSGIMiddleware(soap_wsgi))


class EchoIn(BaseModel):
    anything: dict | list | str | int | float | bool | None


@app.get("/")
def root():
    return {"message": "OK", "docs": "/docs", "wsdl": "/soap/?wsdl"}

@app.get("/health")
def health():
    return {"status": "healthy"}

@app.post("/echo")
def echo(body: EchoIn):
    return {"you_sent": body.anything}

It exposes a couple of endpoints, including SOAP and REST.


REQ: requirements.txt
fastapi==0.112.*
uvicorn[standard]==0.30.*
spyne==2.14.0
lxml>=4.9

nothing special here

  • fastapi - web framework for building APIs
  • uvicorn[standard] - ASGI server
  • spyne - library for building SOAP services in Python
  • lxml - XML parsing library required by Spyne for SOAP message handling

Dockerfile
FROM python:3.11-slim

ENV PYTHONDONTWRITEBYTECODE=1 \
    PYTHONUNBUFFERED=1

WORKDIR /app

# Install runtime deps
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# App
COPY app.py .

EXPOSE 8000

CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]

Copy, install, run.


Build
docker build -t soap-demo:latest .

This is to build our new Docker image with SOAP server


Docker compose service
  soap-test-server:
    image: soap-demo:latest
    container_name: soap-test-server
    hostname: soap-test-server
    restart: unless-stopped
    networks:
      - n8n-infra

Adding to the docker compose in the same network as my n8n


Time to test:

Above I pinned data from calls to two of the SOAP endpoints: say_hello and add (the responses passed through XML to JSON to be more readable.

Just in case, here are the results in text:

Request to say_hello

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
               xmlns:tns="urn:example.soap.demo">
  <soap:Body>
    <tns:say_hello>
      <tns:name>emir.kurklu</tns:name>
    </tns:say_hello>
  </soap:Body>
</soap:Envelope>

Response:

[
  {
    "soap11env:Envelope": {
      "xmlns:soap11env": "http://schemas.xmlsoap.org/soap/envelope/",
      "xmlns:tns": "urn:example.soap.demo",
      "soap11env:Body": {
        "tns:say_helloResponse": {
          "tns:say_helloResult": "Hello, emir.kurklu"
        }
      }
    }
  }
]

Request to add:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
               xmlns:tns="urn:example.soap.demo">
  <soap:Body>
    <tns:add>
      <tns:a>17</tns:a>
      <tns:b>25</tns:b>
    </tns:add>
  </soap:Body>
</soap:Envelope>

Response:

[
  {
    "soap11env:Envelope": {
      "xmlns:soap11env": "http://schemas.xmlsoap.org/soap/envelope/",
      "xmlns:tns": "urn:example.soap.demo",
      "soap11env:Body": {
        "tns:addResponse": {
          "tns:addResult": "42"
        }
      }
    }
  }
]

As you can see, no problem calling SOAP endpoints from HTTP Request node.

2 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.