Savon

I’ve been struggling for the past few hours trying to get the VIES service of the European Union to work with Savon (Ruby SOAP library) in production. It worked in development but timed out in production, and I soon figured out it was only happening when IPv6 was enabled.

The response I would get when requesting the WDSL on IPv6 was a proxy timeout


* About to connect() to ec.europa.eu port 80 (#0)
*   Trying 2a01:e0b:1:143:62eb:69ff:fe8f:16e6... * Connected to ec.europa.eu (2a01:e0b:1:143:62eb:69ff:fe8f:16e6) port 80 (#0)
> GET /taxation_customs/vies/checkVatService.wsdl HTTP/1.1
Host: ec.europa.eu
Accept: */*

* HTTP 1.0, assume close after body
< HTTP/1.0 503 Service Unavailable
< Cache-Control: no-cache
< Connection: close
< Content-Type: text/html
< Content-Length: 310
< 
* Excess found in a non pipelined read: excess = 20, size = 310, maxdownload = 310, bytecount = 0
* Expire cleared
* Closing connection #0
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Error</title>
</head>
<body>
<h1>Erreur 503</h1>
<h2>Erreur proxy ipv6</

Yet, when I would do the same request with the curl command-line tool I got the correct WSDL. The only difference was the User-Agent, and apparently that was the issue! When I added something in the User-Agent header, the request fell trough. So I changed my SOAP setup to this:

Savon::Client.new do
  wsdl.document = 'http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl'
  wsdl.namespace = 'urn:ec.europa.eu:taxud:vies:services:checkVat:types'

  http.headers['User-Agent'] = 'Factr Soap Client'
  http.open_timeout = 2
  http.read_timeout = 2
end