diff --git a/config/module.config.php b/config/module.config.php
index ab4ba3d..651f1ec 100644
--- a/config/module.config.php
+++ b/config/module.config.php
@@ -11,6 +11,7 @@
 use ZF\ContentNegotiation\AcceptListener;
 use ZF\ContentNegotiation\ContentNegotiationOptions;
 use ZF\ContentNegotiation\ContentTypeFilterListener;
+use ZF\ContentNegotiation\HttpMethodOverrideListener;
 use ZF\ContentNegotiation\ContentTypeListener;
 use ZF\ContentNegotiation\ControllerPlugin;
 use ZF\ContentNegotiation\Factory;
@@ -45,6 +46,7 @@
             AcceptFilterListener::class      => Factory\AcceptFilterListenerFactory::class,
             ContentTypeFilterListener::class => Factory\ContentTypeFilterListenerFactory::class,
             ContentNegotiationOptions::class => Factory\ContentNegotiationOptionsFactory::class,
+            HttpMethodOverrideListener::class => Factory\HttpMethodOverrideListenerFactory::class,
         ],
     ],
 
@@ -76,6 +78,11 @@
         // Array of controller service name => allowed content type pairs.
         // The allowed content type may be a string, or an array of strings.
         'content_type_whitelist' => [],
+
+        // Enable x-http method override feature
+        // When set to 'true' the  http method in the request will be overridden
+        // by the method inside the 'X-HTTP-Method-Override' header (if present)
+        'x_http_method_override_enabled' => false,
     ],
 
     'controller_plugins' => [
diff --git a/src/ContentNegotiationOptions.php b/src/ContentNegotiationOptions.php
index dfca9de..295bd8a 100644
--- a/src/ContentNegotiationOptions.php
+++ b/src/ContentNegotiationOptions.php
@@ -30,6 +30,16 @@ class ContentNegotiationOptions extends AbstractOptions
      */
     protected $contentTypeWhitelist = [];
 
+    /**
+     * @var boolean
+     */
+    protected $xHttpMethodOverrideEnabled = false;
+
+    /**
+     * @var array
+     */
+    protected $httpOverrideMethods = [];
+
     /**
      * {@inheritDoc}
      *
@@ -128,4 +138,36 @@ public function getContentTypeWhitelist()
     {
         return $this->contentTypeWhitelist;
     }
+
+    /**
+     * @param boolean $xHttpMethodOverrideEnabled
+     */
+    public function setXHttpMethodOverrideEnabled($xHttpMethodOverrideEnabled)
+    {
+        $this->xHttpMethodOverrideEnabled = $xHttpMethodOverrideEnabled;
+    }
+
+    /**
+     * @return boolean
+     */
+    public function getXHttpMethodOverrideEnabled()
+    {
+        return $this->xHttpMethodOverrideEnabled;
+    }
+
+    /**
+     * @param array $httpOverrideMethods
+     */
+    public function setHttpOverrideMethods(array $httpOverrideMethods)
+    {
+        $this->httpOverrideMethods = $httpOverrideMethods;
+    }
+
+    /**
+     * @return array
+     */
+    public function getHttpOverrideMethods()
+    {
+        return $this->httpOverrideMethods;
+    }
 }
diff --git a/src/Factory/HttpMethodOverrideListenerFactory.php b/src/Factory/HttpMethodOverrideListenerFactory.php
new file mode 100644
index 0000000..a437f0a
--- /dev/null
+++ b/src/Factory/HttpMethodOverrideListenerFactory.php
@@ -0,0 +1,27 @@
+<?php
+/**
+ * @license   http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
+ * @copyright Copyright (c) 2016 Zend Technologies USA Inc. (http://www.zend.com)
+ */
+
+namespace ZF\ContentNegotiation\Factory;
+
+use Interop\Container\ContainerInterface;
+use ZF\ContentNegotiation\ContentNegotiationOptions;
+use ZF\ContentNegotiation\HttpMethodOverrideListener;
+
+class HttpMethodOverrideListenerFactory
+{
+    /**
+     * @param  ContainerInterface $container
+     * @return HttpMethodOverrideListener
+     */
+    public function __invoke(ContainerInterface $container)
+    {
+        $options = $container->get(ContentNegotiationOptions::class);
+        $httpOverrideMethods = $options->getHttpOverrideMethods();
+        $listener = new HttpMethodOverrideListener($httpOverrideMethods);
+
+        return $listener;
+    }
+}
diff --git a/src/HttpMethodOverrideListener.php b/src/HttpMethodOverrideListener.php
new file mode 100644
index 0000000..301ea31
--- /dev/null
+++ b/src/HttpMethodOverrideListener.php
@@ -0,0 +1,85 @@
+<?php
+/**
+ * @license   http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
+ * @copyright Copyright (c) 2016 Zend Technologies USA Inc. (http://www.zend.com)
+ */
+
+namespace ZF\ContentNegotiation;
+
+use Zend\EventManager\AbstractListenerAggregate;
+use Zend\EventManager\EventManagerInterface;
+use Zend\Mvc\MvcEvent;
+use ZF\ApiProblem\ApiProblem;
+use ZF\ApiProblem\ApiProblemResponse;
+use Zend\Http\Request as HttpRequest;
+
+class HttpMethodOverrideListener extends AbstractListenerAggregate
+{
+    /**
+     * @var array
+     */
+    protected $httpMethodOverride = [];
+
+    /**
+     * HttpMethodOverrideListener constructor.
+     *
+     * @param array $httpMethodOverride
+     */
+    public function __construct(array $httpMethodOverride)
+    {
+        $this->httpMethodOverride = $httpMethodOverride;
+    }
+
+    /**
+     * Priority is set very high (should be executed before all other listeners that rely on the request method value).
+     * TODO: Check priority value, maybe value should be even higher??
+     *
+     * @param EventManagerInterface $events
+     * @param int                   $priority
+     */
+    public function attach(EventManagerInterface $events, $priority = 1)
+    {
+        $this->listeners[] = $events->attach(MvcEvent::EVENT_ROUTE, [$this, 'onRoute'], -40);
+    }
+
+    /**
+     * Checks for X-HTTP-Method-Override header and sets header inside request object.
+     *
+     * @param  MvcEvent $event
+     * @return void|ApiProblemResponse
+     */
+    public function onRoute(MvcEvent $event)
+    {
+        $request = $event->getRequest();
+
+        if (! $request instanceof HttpRequest) {
+            return;
+        }
+
+        if (! $request->getHeaders()->has('X-HTTP-Method-Override')) {
+            return;
+        }
+
+        $method = $request->getMethod();
+
+        if (! array_key_exists($method, $this->httpMethodOverride)) {
+            return new ApiProblemResponse(new ApiProblem(
+                400,
+                sprintf('Overriding %s method with X-HTTP-Method-Override header is not allowed', $method)
+            ));
+        }
+
+        $header = $request->getHeader('X-HTTP-Method-Override');
+        $overrideMethod = $header->getFieldValue();
+        $allowedMethods = $this->httpMethodOverride[$method];
+
+        if (! in_array($overrideMethod, $allowedMethods)) {
+            return new ApiProblemResponse(new ApiProblem(
+                400,
+                sprintf('Illegal override method %s in X-HTTP-Method-Override header', $overrideMethod)
+            ));
+        }
+
+        $request->setMethod($overrideMethod);
+    }
+}
diff --git a/src/Module.php b/src/Module.php
index a593d00..54d2a46 100644
--- a/src/Module.php
+++ b/src/Module.php
@@ -48,6 +48,11 @@ public function onBootstrap(MvcEvent $e)
         $services->get(AcceptFilterListener::class)->attach($eventManager);
         $services->get(ContentTypeFilterListener::class)->attach($eventManager);
 
+        $contentNegotiationOptions = $services->get(ContentNegotiationOptions::class);
+        if ($contentNegotiationOptions->getXHttpMethodOverrideEnabled()) {
+            $services->get(HttpMethodOverrideListener::class)->attach($eventManager);
+        }
+
         $sharedEventManager = $eventManager->getSharedManager();
         $sharedEventManager->attach(
             DispatchableInterface::class,
diff --git a/test/ContentNegotiationOptionsTest.php b/test/ContentNegotiationOptionsTest.php
index 70fc1a5..f6f7f55 100644
--- a/test/ContentNegotiationOptionsTest.php
+++ b/test/ContentNegotiationOptionsTest.php
@@ -16,6 +16,8 @@ public function dashSeparatedOptions()
         return [
             'accept-whitelist' => ['accept-whitelist', 'accept_whitelist'],
             'content-type-whitelist' => ['content-type-whitelist', 'content_type_whitelist'],
+            'x-http-method-override-enabled' => ['x-http-method-override-enabled', 'x_http_method_override_enabled'],
+            'http-override-methods' => ['http-override-methods', 'http_override_methods'],
         ];
     }
 
diff --git a/test/Factory/HttpMethodOverrideListenerFactoryTest.php b/test/Factory/HttpMethodOverrideListenerFactoryTest.php
new file mode 100644
index 0000000..5bf9517
--- /dev/null
+++ b/test/Factory/HttpMethodOverrideListenerFactoryTest.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * @license   http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
+ * @copyright Copyright (c) 2016 Zend Technologies USA Inc. (http://www.zend.com)
+ */
+
+namespace ZFTest\ContentNegotiation\Factory;
+
+use PHPUnit_Framework_TestCase as TestCase;
+use Prophecy\Prophecy\ObjectProphecy;
+use Zend\ServiceManager\ServiceLocatorInterface;
+use Zend\ServiceManager\ServiceManager;
+use ZF\ContentNegotiation\ContentNegotiationOptions;
+use ZF\ContentNegotiation\Factory\HttpMethodOverrideListenerFactory;
+use ZF\ContentNegotiation\HttpMethodOverrideListener;
+
+class HttpMethodOverrideListenerFactoryTest extends TestCase
+{
+    public function testCreateServiceShouldReturnContentTypeFilterListenerInstance()
+    {
+        /** @var ContentNegotiationOptions|ObjectProphecy $options */
+        $options = $this->prophesize(ContentNegotiationOptions::class);
+        $options->getHttpOverrideMethods()->willReturn([]);
+
+        /** @var ServiceManager|ObjectProphecy $container */
+        $container = $this->prophesize(ServiceManager::class);
+        $container->willImplement(ServiceLocatorInterface::class);
+        $container->get(ContentNegotiationOptions::class)->willReturn($options);
+
+        $factory = new HttpMethodOverrideListenerFactory();
+        $service = $factory($container->reveal(), HttpMethodOverrideListener::class);
+
+        $this->assertInstanceOf(HttpMethodOverrideListener::class, $service);
+    }
+}
diff --git a/test/HttpMethodOverrideListenerTest.php b/test/HttpMethodOverrideListenerTest.php
new file mode 100644
index 0000000..653385a
--- /dev/null
+++ b/test/HttpMethodOverrideListenerTest.php
@@ -0,0 +1,127 @@
+<?php
+/**
+ * @license   http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
+ * @copyright Copyright (c) 2016 Zend Technologies USA Inc. (http://www.zend.com)
+ */
+
+namespace ZFTest\ContentNegotiation;
+
+use PHPUnit_Framework_TestCase as TestCase;
+use Zend\Http\Request as HttpRequest;
+use Zend\Mvc\MvcEvent;
+use ZF\ApiProblem\ApiProblemResponse;
+use ZF\ContentNegotiation\HttpMethodOverrideListener;
+
+class HttpMethodOverrideListenerTest extends TestCase
+{
+    use RouteMatchFactoryTrait;
+
+    /**
+     * @var HttpMethodOverrideListener
+     */
+    protected $listener;
+
+    /**
+     * @var array
+     */
+    protected $httpMethodOverride = [
+        HttpRequest::METHOD_GET => [
+            HttpRequest::METHOD_HEAD,
+            HttpRequest::METHOD_POST,
+            HttpRequest::METHOD_PUT,
+            HttpRequest::METHOD_DELETE,
+            HttpRequest::METHOD_PATCH,
+        ],
+        HttpRequest::METHOD_POST => [
+        ],
+    ];
+
+    /**
+     * Set up test
+     */
+    public function setUp()
+    {
+        $this->listener = new HttpMethodOverrideListener($this->httpMethodOverride);
+    }
+
+    /**
+     * @return array
+     */
+    public function httpMethods()
+    {
+        return [
+            'head' => [HttpRequest::METHOD_HEAD],
+            'post' => [HttpRequest::METHOD_POST],
+            'put' => [HttpRequest::METHOD_PUT],
+            'delete' => [HttpRequest::METHOD_DELETE],
+            'patch' => [HttpRequest::METHOD_PATCH],
+        ];
+    }
+
+    /**
+     * @dataProvider httpMethods
+     */
+    public function testHttpMethodOverrideListener($method)
+    {
+        $listener = $this->listener;
+
+        $request = new HttpRequest();
+        $request->setMethod('GET');
+        $request->getHeaders()->addHeaderLine('X-HTTP-Method-Override', $method);
+
+        $event = new MvcEvent();
+        $event->setRequest($request);
+        $event->setRouteMatch($this->createRouteMatch([]));
+
+        $result = $listener->onRoute($event);
+        $this->assertEquals($method, $request->getMethod());
+    }
+
+    /**
+     * @dataProvider httpMethods
+     */
+    public function testHttpMethodOverrideListenerReturnsProblemResponseForMethodNotInConfig($method)
+    {
+        $listener = $this->listener;
+
+        $request = new HttpRequest();
+        $request->setMethod('PATCH');
+        $request->getHeaders()->addHeaderLine('X-HTTP-Method-Override', $method);
+
+        $event = new MvcEvent();
+        $event->setRequest($request);
+
+        $result = $listener->onRoute($event);
+        $this->assertInstanceOf(ApiProblemResponse::class, $result);
+        $problem = $result->getApiProblem();
+        $this->assertEquals(400, $problem->status);
+        $this->assertContains(
+            'Overriding PATCH method with X-HTTP-Method-Override header is not allowed',
+            $problem->detail
+        );
+    }
+
+    /**
+     * @dataProvider httpMethods
+     */
+    public function testHttpMethodOverrideListenerReturnsProblemResponseForIllegalOverrideValue($method)
+    {
+        $listener = $this->listener;
+
+        $request = new HttpRequest();
+        $request->setMethod('POST');
+        $request->getHeaders()->addHeaderLine('X-HTTP-Method-Override', $method);
+
+        $event = new MvcEvent();
+        $event->setRequest($request);
+
+        $result = $listener->onRoute($event);
+        $this->assertInstanceOf(ApiProblemResponse::class, $result);
+        $problem = $result->getApiProblem();
+        $this->assertEquals(400, $problem->status);
+        $this->assertContains(
+            sprintf('Illegal override method %s in X-HTTP-Method-Override header', $method),
+            $problem->detail
+        );
+    }
+}