My org ran into this issue when trying to set up a containerized Omeka S instance, which is built on top of Laminas, using an OpenShift cluster. In this case, the application keeps throwing exceptions when making requests via the proxy adapter to download data.
I haven’t done much web application development, and I’m looking for some direction about where to look next based on the behavior I’ve encountered.
The first indication of the issue was when Omeka S failed to download oembed links that worked on instances that weren’t containerized. The containerized instance reported the following runtime error:
Laminas\Http\Client\Adapter\Exception\RuntimeException
Unable to connect to HTTPS server through proxy: could not negotiate secure connection.
Details:
Laminas\Http\Client\Adapter\Exception\RuntimeException: Unable to connect to HTTPS server through proxy: could not negotiate secure connection. in /opt/app-root/src/omeka-s/vendor/laminas/laminas-http/src/Client/Adapter/Proxy.php:296
Stack trace:
#0 /opt/app-root/src/omeka-s/vendor/laminas/laminas-http/src/Client/Adapter/Proxy.php(165): Laminas\Http\Client\Adapter\Proxy->connectHandshake('vimeo.com', 443, '1.1', Array)
#1 /opt/app-root/src/omeka-s/vendor/laminas/laminas-http/src/Client.php(1457): Laminas\Http\Client\Adapter\Proxy->write('GET', Object(Laminas\Uri\Http), '1.1', Array, '')
#2 /opt/app-root/src/omeka-s/vendor/laminas/laminas-http/src/Client.php(945): Laminas\Http\Client->doRequest(Object(Laminas\Uri\Http), 'GET', true, Array, '')
#3 /opt/app-root/src/omeka-s/application/src/Media/Ingester/OEmbed.php(142): Laminas\Http\Client->send()
#4 /opt/app-root/src/omeka-s/application/src/Media/Ingester/OEmbed.php(73): Omeka\Media\Ingester\OEmbed->makeRequest('https://vimeo.c...', 'OEmbed URL', Object(Omeka\Stdlib\ErrorStore))
#5 /opt/app-root/src/omeka-s/application/src/Api/Adapter/MediaAdapter.php(159): Omeka\Media\Ingester\OEmbed->ingest(Object(Omeka\Entity\Media), Object(Omeka\Api\Request), Object(Omeka\Stdlib\ErrorStore))
#6 /opt/app-root/src/omeka-s/application/src/Api/Adapter/AbstractEntityAdapter.php(590): Omeka\Api\Adapter\MediaAdapter->hydrate(Object(Omeka\Api\Request), Object(Omeka\Entity\Media), Object(Omeka\Stdlib\ErrorStore))
#7 /opt/app-root/src/omeka-s/application/src/Api/Adapter/ItemAdapter.php(240): Omeka\Api\Adapter\AbstractEntityAdapter->hydrateEntity(Object(Omeka\Api\Request), Object(Omeka\Entity\Media), Object(Omeka\Stdlib\ErrorStore))
#8 /opt/app-root/src/omeka-s/application/src/Api/Adapter/AbstractEntityAdapter.php(590): Omeka\Api\Adapter\ItemAdapter->hydrate(Object(Omeka\Api\Request), Object(Omeka\Entity\Item), Object(Omeka\Stdlib\ErrorStore))
#9 /opt/app-root/src/omeka-s/application/src/Api/Adapter/AbstractEntityAdapter.php(318): Omeka\Api\Adapter\AbstractEntityAdapter->hydrateEntity(Object(Omeka\Api\Request), Object(Omeka\Entity\Item), Object(Omeka\Stdlib\ErrorStore))
#10 /opt/app-root/src/omeka-s/application/src/Api/Manager.php(224): Omeka\Api\Adapter\AbstractEntityAdapter->create(Object(Omeka\Api\Request))
#11 /opt/app-root/src/omeka-s/application/src/Api/Manager.php(78): Omeka\Api\Manager->execute(Object(Omeka\Api\Request))
#12 /opt/app-root/src/omeka-s/application/src/Mvc/Controller/Plugin/Api.php(99): Omeka\Api\Manager->create('items', Array, Array, Array)
#13 /opt/app-root/src/omeka-s/application/src/Controller/Admin/ItemController.php(207): Omeka\Mvc\Controller\Plugin\Api->create('items', Array, Array)
#14 /opt/app-root/src/omeka-s/vendor/laminas/laminas-mvc/src/Controller/AbstractActionController.php(77): Omeka\Controller\Admin\ItemController->addAction()
#15 /opt/app-root/src/omeka-s/vendor/laminas/laminas-eventmanager/src/EventManager.php(321): Laminas\Mvc\Controller\AbstractActionController->onDispatch(Object(Laminas\Mvc\MvcEvent))
#16 /opt/app-root/src/omeka-s/vendor/laminas/laminas-eventmanager/src/EventManager.php(178): Laminas\EventManager\EventManager->triggerListeners(Object(Laminas\Mvc\MvcEvent), Object(Closure))
#17 /opt/app-root/src/omeka-s/vendor/laminas/laminas-mvc/src/Controller/AbstractController.php(103): Laminas\EventManager\EventManager->triggerEventUntil(Object(Closure), Object(Laminas\Mvc\MvcEvent))
#18 /opt/app-root/src/omeka-s/vendor/laminas/laminas-mvc/src/DispatchListener.php(139): Laminas\Mvc\Controller\AbstractController->dispatch(Object(Laminas\Http\PhpEnvironment\Request), Object(Laminas\Http\PhpEnvironment\Response))
#19 /opt/app-root/src/omeka-s/vendor/laminas/laminas-eventmanager/src/EventManager.php(321): Laminas\Mvc\DispatchListener->onDispatch(Object(Laminas\Mvc\MvcEvent))
#20 /opt/app-root/src/omeka-s/vendor/laminas/laminas-eventmanager/src/EventManager.php(178): Laminas\EventManager\EventManager->triggerListeners(Object(Laminas\Mvc\MvcEvent), Object(Closure))
#21 /opt/app-root/src/omeka-s/vendor/laminas/laminas-mvc/src/Application.php(331): Laminas\EventManager\EventManager->triggerEventUntil(Object(Closure), Object(Laminas\Mvc\MvcEvent))
#22 /opt/app-root/src/omeka-s/index.php(21): Laminas\Mvc\Application->run()
#23 {main}
The runtime error was accompanied by the following php warnings captured in the container logs:
Warning: stream_socket_enable_crypto(): Peer certificate CN=`vimeo.map.fastly.net' did not match expected CN=`<http_config proxy_host value>' in /opt/app-root/src/omeka-s/vendor/laminas/laminas-http/src/Client/Adapter/Proxy.php on line 289
Warning: stream_socket_enable_crypto(): SSL/TLS already set-up for this stream in /opt/app-root/src/omeka-s/vendor/laminas/laminas-http/src/Client/Adapter/Proxy.php on line 289
Warning: stream_socket_enable_crypto(): SSL/TLS already set-up for this stream in /opt/app-root/src/omeka-s/vendor/laminas/laminas-http/src/Client/Adapter/Proxy.php on line 289
Warning: stream_socket_enable_crypto(): SSL/TLS already set-up for this stream in /opt/app-root/src/omeka-s/vendor/laminas/laminas-http/src/Client/Adapter/Proxy.php on line 289
The php warning led me to a stackoverflow answer for the Zend Framework. I disabled the ssl peer and peer name verification expecting to see the oembed functionality start working. The initial result was a grab bag of errors that were further down the line, but I was able to successfully download the oembed data after retrying the operation multiple times.
These new errors included the same proxy runtime error as above accompanied by a new php warning:
Warning: stream_socket_enable_crypto(): SSL: Handshake timed out in /opt/app-root/src/omeka-s/vendor/laminas/laminas-http/src/Client/Adapter/Proxy.php on line 289
and what appears to be an empty or malformed response from the data destination:
Laminas\Http\Exception\InvalidArgumentException
A valid response status line was not found in the provided string
Details:
Laminas\Http\Exception\InvalidArgumentException: A valid response status line was not found in the provided string in /opt/app-root/src/omeka-s/vendor/laminas/laminas-http/src/Response.php:266
Stack trace:
#0 /opt/app-root/src/omeka-s/vendor/laminas/laminas-http/src/Response.php(204): Laminas\Http\Response->parseStatusLine('')
#1 /opt/app-root/src/omeka-s/vendor/laminas/laminas-http/src/Client/Adapter/Proxy.php(271): Laminas\Http\Response::fromString('')
#2 /opt/app-root/src/omeka-s/vendor/laminas/laminas-http/src/Client/Adapter/Proxy.php(165): Laminas\Http\Client\Adapter\Proxy->connectHandshake('vimeo.com', 443, '1.1', Array)
#3 /opt/app-root/src/omeka-s/vendor/laminas/laminas-http/src/Client.php(1457): Laminas\Http\Client\Adapter\Proxy->write('GET', Object(Laminas\Uri\Http), '1.1', Array, '')
#4 /opt/app-root/src/omeka-s/vendor/laminas/laminas-http/src/Client.php(945): Laminas\Http\Client->doRequest(Object(Laminas\Uri\Http), 'GET', true, Array, '')
#5 /opt/app-root/src/omeka-s/application/src/Media/Ingester/OEmbed.php(142): Laminas\Http\Client->send()
#6 /opt/app-root/src/omeka-s/application/src/Media/Ingester/OEmbed.php(73): Omeka\Media\Ingester\OEmbed->makeRequest('https://vimeo.c...', 'OEmbed URL', Object(Omeka\Stdlib\ErrorStore))
#7 /opt/app-root/src/omeka-s/application/src/Api/Adapter/MediaAdapter.php(159): Omeka\Media\Ingester\OEmbed->ingest(Object(Omeka\Entity\Media), Object(Omeka\Api\Request), Object(Omeka\Stdlib\ErrorStore))
#8 /opt/app-root/src/omeka-s/application/src/Api/Adapter/AbstractEntityAdapter.php(590): Omeka\Api\Adapter\MediaAdapter->hydrate(Object(Omeka\Api\Request), Object(Omeka\Entity\Media), Object(Omeka\Stdlib\ErrorStore))
#9 /opt/app-root/src/omeka-s/application/src/Api/Adapter/ItemAdapter.php(240): Omeka\Api\Adapter\AbstractEntityAdapter->hydrateEntity(Object(Omeka\Api\Request), Object(Omeka\Entity\Media), Object(Omeka\Stdlib\ErrorStore))
#10 /opt/app-root/src/omeka-s/application/src/Api/Adapter/AbstractEntityAdapter.php(590): Omeka\Api\Adapter\ItemAdapter->hydrate(Object(Omeka\Api\Request), Object(Omeka\Entity\Item), Object(Omeka\Stdlib\ErrorStore))
#11 /opt/app-root/src/omeka-s/application/src/Api/Adapter/AbstractEntityAdapter.php(318): Omeka\Api\Adapter\AbstractEntityAdapter->hydrateEntity(Object(Omeka\Api\Request), Object(Omeka\Entity\Item), Object(Omeka\Stdlib\ErrorStore))
#12 /opt/app-root/src/omeka-s/application/src/Api/Manager.php(224): Omeka\Api\Adapter\AbstractEntityAdapter->create(Object(Omeka\Api\Request))
#13 /opt/app-root/src/omeka-s/application/src/Api/Manager.php(78): Omeka\Api\Manager->execute(Object(Omeka\Api\Request))
#14 /opt/app-root/src/omeka-s/application/src/Mvc/Controller/Plugin/Api.php(99): Omeka\Api\Manager->create('items', Array, Array, Array)
#15 /opt/app-root/src/omeka-s/application/src/Controller/Admin/ItemController.php(207): Omeka\Mvc\Controller\Plugin\Api->create('items', Array, Array)
#16 /opt/app-root/src/omeka-s/vendor/laminas/laminas-mvc/src/Controller/AbstractActionController.php(77): Omeka\Controller\Admin\ItemController->addAction()
#17 /opt/app-root/src/omeka-s/vendor/laminas/laminas-eventmanager/src/EventManager.php(321): Laminas\Mvc\Controller\AbstractActionController->onDispatch(Object(Laminas\Mvc\MvcEvent))
#18 /opt/app-root/src/omeka-s/vendor/laminas/laminas-eventmanager/src/EventManager.php(178): Laminas\EventManager\EventManager->triggerListeners(Object(Laminas\Mvc\MvcEvent), Object(Closure))
#19 /opt/app-root/src/omeka-s/vendor/laminas/laminas-mvc/src/Controller/AbstractController.php(103): Laminas\EventManager\EventManager->triggerEventUntil(Object(Closure), Object(Laminas\Mvc\MvcEvent))
#20 /opt/app-root/src/omeka-s/vendor/laminas/laminas-mvc/src/DispatchListener.php(139): Laminas\Mvc\Controller\AbstractController->dispatch(Object(Laminas\Http\PhpEnvironment\Request), Object(Laminas\Http\PhpEnvironment\Response))
#21 /opt/app-root/src/omeka-s/vendor/laminas/laminas-eventmanager/src/EventManager.php(321): Laminas\Mvc\DispatchListener->onDispatch(Object(Laminas\Mvc\MvcEvent))
#22 /opt/app-root/src/omeka-s/vendor/laminas/laminas-eventmanager/src/EventManager.php(178): Laminas\EventManager\EventManager->triggerListeners(Object(Laminas\Mvc\MvcEvent), Object(Closure))
#23 /opt/app-root/src/omeka-s/vendor/laminas/laminas-mvc/src/Application.php(331): Laminas\EventManager\EventManager->triggerEventUntil(Object(Closure), Object(Laminas\Mvc\MvcEvent))
#24 /opt/app-root/src/omeka-s/index.php(21): Laminas\Mvc\Application->run()
#25 {main}