You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwhisk.apache.org by mh...@apache.org on 2018/07/03 18:15:34 UTC

[incubator-openwhisk-apigateway] branch master updated: Fix Access-Control-Allow-Headers header; Fix case when cors is not set (#315)

This is an automated email from the ASF dual-hosted git repository.

mhamann pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk-apigateway.git


The following commit(s) were added to refs/heads/master by this push:
     new bac25d8  Fix Access-Control-Allow-Headers header; Fix case when cors is not set (#315)
bac25d8 is described below

commit bac25d87f7b98f8be56d4c49a1fc11644a813c8c
Author: Alex Song <al...@gmail.com>
AuthorDate: Tue Jul 3 14:15:31 2018 -0400

    Fix Access-Control-Allow-Headers header; Fix case when cors is not set (#315)
    
    * Fix Access-Control-Allow-Headers header; Fix case when cors is not set
    
    * Add tests for handling cors headers
---
 scripts/lua/cors.lua       | 11 +++++-
 tests/fakengx.lua          |  7 +++-
 tests/scripts/lua/cors.lua | 98 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 113 insertions(+), 3 deletions(-)

diff --git a/scripts/lua/cors.lua b/scripts/lua/cors.lua
index ea11579..8c0b1f5 100644
--- a/scripts/lua/cors.lua
+++ b/scripts/lua/cors.lua
@@ -25,21 +25,28 @@ function _M.processCall(resourceConfig)
   if resourceConfig.cors ~= nil then
     ngx.var.cors_origins = resourceConfig.cors.origin
     ngx.var.cors_methods = resourceConfig.cors.methods
+    -- preflight options call
     if resourceConfig.cors.origin ~= 'false' and ngx.req.get_method() == 'OPTIONS' then
+      -- 'Access-Control-Allow-Headers' response header is required for preflight requests that have 'Access-Control-Request-Headers' headers
+      local accessControlRequestHeaders = ngx.req.get_headers()['Access-Control-Request-Headers']
+      if accessControlRequestHeaders ~= nil then
+        ngx.header['Access-Control-Allow-Headers'] = accessControlRequestHeaders
+      end
       request.success(200)
     end
   end
 end
 
 function _M.replaceHeaders()
-  if ngx.var.cors_origins ~= nil then
+  if ngx.var.cors_origins ~= nil and ngx.var.cors_origins ~= '' then
     if ngx.var.cors_origins == 'false' then
       ngx.header['Access-Control-Allow-Origin'] = nil
       ngx.header['Access-Control-Allow-Methods'] = nil
+      ngx.header['Access-Control-Allow-Headers'] = nil
+      ngx.header['Access-Control-Allow-Credentials'] = nil
     else
       ngx.header['Access-Control-Allow-Origin'] = ngx.var.cors_origins == 'true' and (ngx.var.http_origin or '*') or ngx.var.cors_origins
       ngx.header['Access-Control-Allow-Methods'] = ngx.var.cors_methods or 'GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS'
-      ngx.header['Access-Control-Allow-Headers'] = ngx.req.get_headers()['Access-Control-Request-Headers']
       ngx.header['Access-Control-Allow-Credentials'] = 'true'
     end
   end
diff --git a/tests/fakengx.lua b/tests/fakengx.lua
index ed8ddfd..7a0ec1e 100644
--- a/tests/fakengx.lua
+++ b/tests/fakengx.lua
@@ -310,6 +310,7 @@ function fakengx.new()
   ngx.thread    = {}
   ngx.location  = {}
   ngx.shared    = {}
+  ngx.header    = {}
 
   -- Create shared dict API
   setmetatable(ngx.shared, {
@@ -474,7 +475,11 @@ function fakengx.new()
   end
 
   function ngx.req.get_headers()
-    return {}
+    return ngx.header
+  end
+
+  function ngx.req.get_method()
+    return
   end
 
   -- http://wiki.nginx.org/HttpLuaModule#ngx.socket.tcp
diff --git a/tests/scripts/lua/cors.lua b/tests/scripts/lua/cors.lua
new file mode 100644
index 0000000..565440c
--- /dev/null
+++ b/tests/scripts/lua/cors.lua
@@ -0,0 +1,98 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+
+local fakengx = require 'fakengx'
+local cors = require 'cors'
+local redis = require 'lib/redis'
+local cjson = require 'cjson'
+
+
+describe('Testing cors headers', function()
+  before_each(function()
+    _G.ngx = fakengx.new()
+    ngx.var.cors_origins = ''
+    ngx.var.cors_methods = ''
+    operations = {
+      GET = {
+        backendUrl = 'https://example.com',
+        backendMethod = 'GET'
+      }
+    }
+    _G.resourceObj = cjson.decode(redis.generateResourceObj(operations, nil, nil, nil))
+  end)
+
+  it('Access-Control headers should be present for preflight options call if cors is enabled', function()
+    -- mock options call
+    ngx.req.get_method = function()
+      return 'OPTIONS'
+    end
+
+    ngx.header['Access-Control-Request-Headers'] = 'test-header'
+
+    resourceObj.cors = {
+      origin = 'true',
+      methods = 'GET, POST, PUT'
+    }
+    cors.processCall(resourceObj)
+    cors.replaceHeaders()
+
+    assert.are.same(ngx.req.get_headers()['Access-Control-Allow-Origin'], '*')
+    assert.are.same(ngx.req.get_headers()['Access-Control-Allow-Methods'], 'GET, POST, PUT')
+    assert.are.same(ngx.req.get_headers()['Access-Control-Allow-Credentials'], 'true')
+    assert.are.same(ngx.req.get_headers()['Access-Control-Allow-Headers'], 'test-header')
+  end)
+
+  it('Access-Control headers should be present with cors enabled', function()
+    resourceObj.cors = {
+      origin = 'true',
+    }
+    cors.processCall(resourceObj)
+    cors.replaceHeaders()
+
+    assert.are.same(ngx.req.get_headers()['Access-Control-Allow-Origin'], '*')
+    assert.are.same(ngx.req.get_headers()['Access-Control-Allow-Methods'], 'GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS')
+    assert.are.same(ngx.req.get_headers()['Access-Control-Allow-Credentials'], 'true')
+  end)
+
+  it('Access-Control headers should not be present with cors disabled', function()
+    resourceObj.cors = {
+      origin = 'false'
+    }
+    cors.processCall(resourceObj)
+    cors.replaceHeaders()
+
+    assert.are.same(ngx.req.get_headers()['Access-Control-Allow-Origin'], nil)
+    assert.are.same(ngx.req.get_headers()['Access-Control-Allow-Methods'], nil)
+    assert.are.same(ngx.req.get_headers()['Access-Control-Allow-Headers'], nil)
+    assert.are.same(ngx.req.get_headers()['Access-Control-Allow-Credentials'], nil)
+  end)
+
+  it('Should pass through Access-Control headers if cors is not defined', function()
+    ngx.header['Access-Control-Allow-Origin'] = 'https://foo.bar'
+    ngx.header['Access-Control-Allow-Headers'] = 'Content-Type'
+
+    resourceObj.cors = nil
+
+    cors.processCall(resourceObj)
+    cors.replaceHeaders()
+
+    assert.are.same(ngx.req.get_headers()['Access-Control-Allow-Origin'], 'https://foo.bar')
+    assert.are.same(ngx.req.get_headers()['Access-Control-Allow-Headers'], 'Content-Type')
+    assert.are.same(ngx.req.get_headers()['Access-Control-Allow-Methods'], nil)
+  end)
+
+end)