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 <alexson...@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)