# Lather π§Ό
[](https://hex.pm/packages/lather)
[](https://hexdocs.pm/lather)
[](https://github.com/markcotner/lather/blob/main/LICENSE)
**A comprehensive SOAP library for Elixir** that provides both client and server capabilities with modern web interfaces. Lather can work with any SOAP service without requiring service-specific implementations, using dynamic WSDL analysis and runtime operation building.
## β¨ Key Features
- π **Universal SOAP Client**: Works with any SOAP service using WSDL analysis
- π₯οΈ **Complete SOAP Server**: Build SOAP services with a clean DSL
- π **Dynamic Operations**: Automatically discovers and builds requests for any SOAP operation  
- π‘οΈ **Enterprise Security**: WS-Security, Basic Auth, SSL/TLS support
- β‘ **High Performance**: Built on Finch with connection pooling and async support
- π§ **Phoenix Integration**: Seamless integration with Phoenix applications
- π **Type Safety**: Dynamic type mapping and validation with struct generation
- π¨ **Robust Error Handling**: Structured error types with SOAP fault parsing
## π Enhanced Features (v1.0.0)
### Multi-Protocol SOAP & REST Support
Lather v1.0.0 features a **three-layer API architecture** that serves multiple protocol types from a single service:
```
ββ SOAP 1.1 (Top - Maximum Compatibility)    β Legacy systems, .NET Framework
ββ SOAP 1.2 (Middle - Enhanced Features)     β Modern SOAP, better error handling  
ββ REST/JSON (Bottom - Modern Applications)  β Web apps, mobile, JavaScript
```
### Interactive Web Interface
Professional HTML5 testing interface similar to .NET Web Services:
- π **Interactive Forms**: Test operations directly in your browser
- π **Multi-Protocol Examples**: See SOAP 1.1, SOAP 1.2, and JSON formats
- π± **Responsive Design**: Works on desktop and mobile
- π **Dark Mode Support**: Automatically respects browser dark mode preference
- β‘ **Real-time Validation**: Type-aware parameter validation
### Enhanced WSDL Generation
Generate comprehensive WSDL documents with multiple protocol bindings:
```elixir
# Standard WSDL (SOAP 1.1 only)  
wsdl = Lather.Server.WsdlGenerator.generate(service_info, base_url)
# Enhanced WSDL (multi-protocol)
enhanced_wsdl = Lather.Server.EnhancedWSDLGenerator.generate(service_info, base_url)
# Interactive web forms
forms = Lather.Server.FormGenerator.generate_service_overview(service_info, base_url)
```
### Flexible URL Structure
- `GET  /service` β Interactive service overview with testing forms
- `GET  /service?wsdl` β Standard WSDL download
- `GET  /service?wsdl&enhanced=true` β Multi-protocol WSDL  
- `GET  /service?op=OperationName` β Interactive operation testing form
- `POST /service` β SOAP 1.1 endpoint (maximum compatibility)
- `POST /service/v1.2` β SOAP 1.2 endpoint (enhanced features)
- `POST /service/api` β JSON/REST endpoint (modern applications)
## π Quick Start
### Installation
Add `lather` to your `mix.exs` dependencies:
```elixir
def deps do
  [
    {:lather, "~> 1.0"},
    # Optional: for JSON/REST endpoints in enhanced features
    {:jason, "~> 1.4"}
  ]
end
```
### SOAP Client
Connect to any SOAP service and start making calls:
```elixir
# Create a dynamic client from any WSDL
{:ok, client} = Lather.DynamicClient.new("http://example.com/service?wsdl")
# Call any operation defined in the WSDL  
{:ok, response} = Lather.DynamicClient.call(client, "GetUser", %{
  "userId" => "12345"
})
# With authentication
{:ok, client} = Lather.DynamicClient.new(wsdl_url, [
  basic_auth: {"username", "password"},
  timeout: 30_000
])
```
### SOAP Server
Define SOAP services with a clean, macro-based DSL:
```elixir
defmodule MyApp.UserService do
  use Lather.Server
  
  @service_name "UserService"
  @target_namespace "http://myapp.com/user"
  
  defoperation get_user,
    input: [user_id: :string],
    output: [user: %{name: :string, email: :string}] do
    
    user = MyApp.Users.get!(user_id)
    {:ok, %{user: %{name: user.name, email: user.email}}}
  end
end
# Add to your Phoenix router
pipe_through :api
post "/soap/user", Lather.Server.Plug, service: MyApp.UserService
```
### Enhanced Multi-Protocol Server
```elixir
# Define a service that supports SOAP 1.1, SOAP 1.2, and JSON/REST
defmodule MyApp.UserService do
  use Lather.Server
  @namespace "http://myapp.com/users"
  @service_name "UserManagementService"
  soap_operation "GetUser" do
    description "Retrieve user information by ID"
    
    input do
      parameter "userId", :string, required: true, description: "User identifier"
      parameter "includeProfile", :boolean, required: false, description: "Include full profile"
    end
    
    output do
      parameter "user", "tns:User", description: "User information"
    end
    
    soap_action "#{@namespace}/GetUser"
  end
  def get_user(%{"userId" => user_id} = params) do
    include_profile = Map.get(params, "includeProfile", false)
    # Your business logic here
    {:ok, %{"user" => %{"id" => user_id, "name" => "John Doe"}}}
  end
end
# Phoenix router with enhanced features
scope "/api/users" do
  pipe_through :api
  
  # Multi-protocol endpoints
  match :*, "/", Lather.Server.EnhancedPlug, service: MyApp.UserService
  match :*, "/*path", Lather.Server.EnhancedPlug, service: MyApp.UserService
end
# Generate enhanced WSDL with multiple protocols
service_info = MyApp.UserService.__service_info__()
enhanced_wsdl = Lather.Server.EnhancedWSDLGenerator.generate(service_info, "https://myapp.com/api/users")
# Generate interactive web forms
overview_page = Lather.Server.FormGenerator.generate_service_overview(service_info, "https://myapp.com/api/users")
```
### Access Multiple Protocol Endpoints
Your service automatically exposes multiple endpoints:
```bash
# Interactive web interface
curl -X GET "https://myapp.com/api/users"
# Standard WSDL (SOAP 1.1)
curl -X GET "https://myapp.com/api/users?wsdl"
# Enhanced WSDL (multi-protocol)
curl -X GET "https://myapp.com/api/users?wsdl&enhanced=true"
# Interactive operation form
curl -X GET "https://myapp.com/api/users?op=GetUser"
# SOAP 1.1 request
curl -X POST "https://myapp.com/api/users" \
  -H "Content-Type: text/xml; charset=utf-8" \
  -H "SOAPAction: http://myapp.com/users/GetUser" \
  -d '<soap:Envelope>...</soap:Envelope>'
# SOAP 1.2 request
curl -X POST "https://myapp.com/api/users/v1.2" \
  -H "Content-Type: application/soap+xml; charset=utf-8; action=\"http://myapp.com/users/GetUser\"" \
  -d '<soap:Envelope>...</soap:Envelope>'
# JSON/REST request
curl -X POST "https://myapp.com/api/users/api" \
  -H "Content-Type: application/json" \
  -d '{"operation": "GetUser", "parameters": {"userId": "123"}}'
```
## π Interactive Learning with Livebooks
Lather includes comprehensive interactive documentation via **Livebooks** that you can run directly in your development environment. These tutorials provide hands-on experience with real SOAP services and practical examples.
### Available Livebooks
#### π± **Getting Started** (`livebooks/getting_started.livemd`)
Perfect introduction to Lather with step-by-step examples:
- Creating your first SOAP client
- Making basic SOAP calls
- Handling responses and errors
- Authentication basics
#### π€οΈ **Weather Service Example** (`livebooks/weather_service_example.livemd`)
Real-world example using the National Weather Service API:
- Working with document/encoded SOAP services
- Complex parameter handling
- Response parsing and data extraction
- Error handling with external services
#### π **Country Info Service Example** (`livebooks/country_info_service_example.livemd`)
Demonstrates document/literal SOAP style:
- Different SOAP encoding styles
- Namespace handling
- Complex data structures
- Service discovery
#### π₯οΈ **SOAP Server Development** (`livebooks/soap_server_development.livemd`)
Complete server development tutorial:
- Building SOAP services with Lather.Server
- Multi-protocol endpoint configuration
- Interactive web interfaces
- Testing your services
#### π§ **Advanced Types** (`livebooks/advanced_types.livemd`)
Master complex data structures:
- Working with complex types
- Arrays and nested objects
- Type validation and conversion
- Custom type mappings
#### π’ **Enterprise Integration** (`livebooks/enterprise_integration.livemd`)
Production-ready patterns and practices:
- WS-Security implementation
- SSL/TLS configuration
- Performance optimization
- Monitoring and logging
#### π **Debugging & Troubleshooting** (`livebooks/debugging_troubleshooting.livemd`)
Essential debugging techniques:
- SOAP message inspection
- Common error patterns
- Network troubleshooting
- Performance analysis
### Running Livebooks
To use the interactive tutorials:
```bash
# Install Livebook if you haven't already
mix escript.install hex livebook
# Navigate to your project directory
cd your_project
# Start Livebook
livebook server
# Open any of the tutorial files from the livebooks/ directory
```
Or run individual livebooks directly:
```bash
# Run a specific livebook
livebook server livebooks/getting_started.livemd
```
The livebooks are self-contained and include all necessary dependencies. They're perfect for:
- **Learning**: Step-by-step tutorials with explanations
- **Testing**: Try different SOAP services interactively  
- **Development**: Use as templates for your own implementations
- **Troubleshooting**: Debug issues with real examples
## ποΈ Architecture
```
βββββββββββββββββββ    ββββββββββββββββββββ    βββββββββββββββββββ
β   Application   β    β   Lather.Server  β    β  Phoenix/Plug   β
β                 β    β                  β    β                 β
β DynamicClient   βββββΊβ Service DSL      βββββΊβ HTTP Integrationβ
β WSDL Analysis   β    β WSDL Generation  β    β Request Routing β
β Type Mapping    β    β Operation Dispatchβ    β Middleware     β
βββββββββββββββββββ    ββββββββββββββββββββ    βββββββββββββββββββ
         β                       β                       β
         βΌ                       βΌ                       βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β                    Core Infrastructure                          β
β                                                                 β
β  HTTP Transport  β  XML Processing  β  Error Handling  β  Auth  β
β  (Finch)        β  (SweetXML)     β  (Structured)    β  (WS-*) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
```
## π§ Advanced Usage
### Enterprise Authentication
```elixir
# WS-Security with UsernameToken
username_token = Lather.Auth.WSSecurity.username_token("user", "pass", :digest)
security_header = Lather.Auth.WSSecurity.security_header(username_token)
{:ok, client} = Lather.DynamicClient.new(wsdl_url,
  soap_headers: [security_header],
  ssl_options: [verify: :verify_peer]
)
```
### Complex Data Structures
```elixir
{:ok, response} = Lather.DynamicClient.call(client, "CreateOrder", %{
  "order" => %{
    "customer" => %{
      "name" => "John Doe",
      "email" => "john@example.com"
    },
    "items" => [
      %{"sku" => "ITEM001", "quantity" => 2},
      %{"sku" => "ITEM002", "quantity" => 1}
    ],
    "shipping" => %{
      "method" => "express",
      "address" => %{
        "street" => "123 Main St",
        "city" => "Portland",
        "state" => "OR",
        "zip" => "97201"
      }
    }
  }
})
```
### Error Handling
```elixir
case Lather.DynamicClient.call(client, "Operation", params) do
  {:ok, response} ->
    handle_success(response)
    
  {:error, %{type: :soap_fault} = fault} ->
    Logger.error("SOAP Fault: #{fault.fault_string}")
    handle_soap_fault(fault)
    
  {:error, %{type: :http_error} = error} ->
    Logger.error("HTTP Error #{error.status}")
    handle_http_error(error)
    
  {:error, %{type: :transport_error} = error} ->
    if Lather.Error.recoverable?(error) do
      schedule_retry()
    else
      handle_fatal_error(error)
    end
end
```
## π§ͺ Testing
```bash
# Run all tests (excludes external API tests by default)
mix test
# Run with external API tests (hits real SOAP services - use sparingly!)
mix test --include external_api
# Run with coverage
mix test --cover
# Run specific test files
mix test test/lather/xml/parser_test.exs
```
### External API Tests
By default, tests that call external SOAP services are excluded to avoid:
- Overloading public APIs
- Network-dependent test failures  
- Slow test runs
External API tests validate the library against real-world services like:
- National Weather Service (document/encoded style)
- Country Info Service (document/literal style)
**Use external API tests responsibly:**
- Only when making significant SOAP-related changes
- Before releases
- When investigating service-specific issues
```bash
# Enable external API tests (be considerate!)
mix test --include external_api
```
## π§ Configuration
```elixir
# config/config.exs
config :lather,
  default_timeout: 30_000,
  ssl_verify: :verify_peer,
  finch_pools: %{
    default: [size: 25, count: 1]
  }
# Configure Finch for optimal performance
config :lather, :finch,
  pools: %{
    "https://api.example.com" => [
      size: 25,
      protocols: [:http2, :http1]
    ]
  }
```
## π€ Contributing
We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Add tests for your changes
4. Ensure all tests pass (`mix test`)
5. Commit your changes (`git commit -m 'Add amazing feature'`)
6. Push to the branch (`git push origin feature/amazing-feature`)
7. Open a Pull Request
## π License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## π Acknowledgments
- Built with [Finch](https://hex.pm/packages/finch) for HTTP transport
- XML parsing powered by [SweetXml](https://hex.pm/packages/sweet_xml)
- Inspired by the SOAP libraries of other ecosystems
## π Support
- π [Documentation](https://hexdocs.pm/lather)
- π [Issues](https://github.com/markcotner/lather/issues)
- π¬ [Discussions](https://github.com/markcotner/lather/discussions)
## πΊοΈ Roadmap
### v1.1.0 (Next Release)
- [ ] MTOM/XOP binary attachments
- [ ] Enhanced WS-Security features (XML Signature, Encryption)
- [ ] Performance optimizations and benchmarking
- [ ] Additional server examples and templates
### v1.2.0 
- [ ] WS-Addressing and WS-ReliableMessaging
- [ ] OpenAPI 3.0 SOAP extension support
- [ ] GraphQL-style query interface for SOAP
- [ ] Advanced caching strategies
### Future Releases  
- [ ] Service mesh integration patterns
- [ ] gRPC interoperability layer
- [ ] Kubernetes-native deployment tools
- [ ] Advanced monitoring and observability
---
**Lather v1.0.1** - Making SOAP integration in Elixir as smooth as possible! π§Όβ¨
*Released January 2025 with complete SOAP 1.2 support and multi-protocol capabilities.*