diff --git a/gateway/src/apicast/mapping_rule.lua b/gateway/src/apicast/mapping_rule.lua
index 9a175dec3..98eef7b6b 100644
--- a/gateway/src/apicast/mapping_rule.lua
+++ b/gateway/src/apicast/mapping_rule.lua
@@ -27,7 +27,9 @@ local function hash_to_array(hash)
 end
 
 local function regexpify(pattern)
-  return pattern:gsub('?.*', ''):gsub("{.-}", '([\\w_.-]+)'):gsub("%.", "\\.")
+  -- as per the RFC: https://tools.ietf.org/html/rfc3986#section-3.3
+  local wildcard_regex = [[([\w-.~%%!$&'()*+,;=@:]+)]] -- using long Lua brackets [[...]], escaping `%`
+  return pattern:gsub('?.*', ''):gsub("{.-}", wildcard_regex):gsub("%.", "\\.")
 end
 
 local regex_variable = '\\{[-\\w_]+\\}'
diff --git a/spec/mapping_rule_spec.lua b/spec/mapping_rule_spec.lua
index f95aba75e..39b11c966 100644
--- a/spec/mapping_rule_spec.lua
+++ b/spec/mapping_rule_spec.lua
@@ -79,5 +79,20 @@ describe('mapping_rule', function()
       local match = mapping_rule:matches('POST', '/def', { x = 'y' })
       assert.is_false(match)
     end)
+
+    it('returns true when wildcard value has special characters: @ : % etc.', function()
+      local mapping_rule = MappingRule.from_proxy_rule({
+        http_method = 'GET',
+        pattern = '/foo/{wildcard}/bar',
+        querystring_parameters = { },
+        metric_system_name = 'hits',
+        delta = 1
+      })
+
+      assert.is_true(mapping_rule:matches('GET', '/foo/a@b/bar'))
+      assert.is_true(mapping_rule:matches('GET', '/foo/a:b/bar'))
+      assert.is_true(mapping_rule:matches('GET', "/foo/a%b/bar"))
+    end)
+
   end)
 end)