Skip to content

Commit

Permalink
Merge pull request #416 from 3scale/cors-example
Browse files Browse the repository at this point in the history
[example] update CORS example
  • Loading branch information
mikz authored Sep 1, 2017
2 parents 50ac300 + bb2dab0 commit aaff93f
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 46 deletions.
12 changes: 12 additions & 0 deletions examples/configuration/echo.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@
"pattern": "/",
"metric_system_name": "hits",
"delta": 1
},
{
"http_method": "POST",
"pattern": "/",
"metric_system_name": "hits",
"delta": 1
},
{
"http_method": "PUT",
"pattern": "/",
"metric_system_name": "hits",
"delta": 1
}
]
}
Expand Down
2 changes: 1 addition & 1 deletion examples/cors/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
FROM registry.access.redhat.com/3scale-amp20/apicast-gateway:1.0

COPY apicast_cors.lua /opt/app-root/app/src/
COPY cors.lua /opt/app-root/app/src/
COPY cors.conf /opt/app-root/app/apicast.d/

20 changes: 10 additions & 10 deletions examples/cors/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ This example shows how CORS ([Cross Origin Resource Sharing](https://developer.m

There are two code snippets that do the following:

1. `apicast_cors.lua` is a custom module (see [this example](https://github.com/3scale/apicast/tree/master/examples/custom-module) for more info) that overrides the default APIcast's rewrite phase handler to include the following logic:
1. `cors.lua` is a custom module (see [this example](https://github.com/3scale/apicast/tree/master/examples/custom-module) for more info) that overrides the default APIcast's rewrite phase handler to include the following logic:

when the request method is `OPTIONS`, and `Origin` and `Access-Control-Request-Method` headers are present, the request is considered to be CORS preflight request, and APIcast returns a `204` request with the response headers defined in `set_cors_headers()` method. In this case the request will not pass through 3scale access control.

Expand All @@ -18,18 +18,18 @@ There are two code snippets that do the following:

### Native APIcast

Place `apicast_cors.lua` to `apicast/src`, and `cors.conf` to `apicast/apicast.d` and start APIcast:
Place `cors.lua` to `apicast/src`, and `cors.conf` to `apicast/apicast.d` and start APIcast:

```
THREESCALE_PORTAL_ENDPOINT=https://ACCESS-TOKEN@ACCOUNT-admin.3scale.net APICAST_MODULE=apicast_cors bin/apicast
THREESCALE_PORTAL_ENDPOINT=https://ACCESS-TOKEN@ACCOUNT-admin.3scale.net APICAST_MODULE=cors bin/apicast
```

### Docker

Attach the above files as volumes to the container and set `APICAST_MODULE` environment variable.

```
docker run --name apicast --rm -p 8080:8080 -v $(pwd)/examples/cors/apicast_cors.lua:/opt/app-root/src/src/apicast_cors.lua:ro -v $(pwd)/examples/cors/cors.conf:/opt/app-root/src/apicast.d/cors.conf:ro -e THREESCALE_PORTAL_ENDPOINT=https://ACCESS-TOKEN@ACCOUNT-admin.3scale.net -e APICAST_MODULE=apicast_cors quay.io/3scale/apicast:master
docker run --name apicast --rm -p 8080:8080 -v $(pwd)/examples/cors/cors.lua:/opt/app-root/src/src/cors.lua:ro -v $(pwd)/examples/cors/cors.conf:/opt/app-root/src/apicast.d/cors.conf:ro -e THREESCALE_PORTAL_ENDPOINT=https://ACCESS-TOKEN@ACCOUNT-admin.3scale.net -e APICAST_MODULE=cors quay.io/3scale/apicast:master
```

### OpenShift
Expand All @@ -44,7 +44,7 @@ A new image with the customization can be rebuild, using a simple `Dockerfile` (
FROM quay.io/3scale/apicast:master
# Copy customized source code to the appropriate directories
COPY ./examples/cors/apicast_cors.lua /opt/app-root/src/src/
COPY ./examples/cors/cors.lua /opt/app-root/src/src/
COPY ./examples/cors/cors.conf /opt/app-root/src/apicast.d/
```

Expand All @@ -57,7 +57,7 @@ oc new-app -f https://raw.githubusercontent.com/3scale/apicast/master/openshift/
Set the environment variable `APICAST_MODULE`:

```
oc env dc/apicast APICAST_MODULE=apicast_cors
oc env dc/apicast APICAST_MODULE=cors
```

Alternatively, you can add the above Dockerfile to your own fork of the `apicast` Git repository, and have OpenShift do the build. For example:
Expand All @@ -74,25 +74,25 @@ You can add the customized files as ConfigMaps and mount them as volumes to an e
2. Create ConfigMaps from the provided files:

```
oc create configmap apicast-cors --from-file=./examples/cors/apicast_cors.lua
oc create configmap apicast-cors --from-file=./examples/cors/cors.lua
oc create configmap cors-conf --from-file=./examples/cors/cors.conf
```

3. Create volumes for the container, and mount them to the appropriate paths:

```
oc set volume dc/apicast --add --name=apicast-cors --mount-path /opt/app-root/src/src/apicast_cors.lua --source='{"configMap":{"name":"apicast-cors","items":[{"key":"apicast_cors.lua","path":"apicast_cors.lua"}]}}'
oc set volume dc/apicast --add --name=apicast-cors --mount-path /opt/app-root/src/src/cors.lua --source='{"configMap":{"name":"apicast-cors","items":[{"key":"cors.lua","path":"cors.lua"}]}}'
oc set volume dc/apicast --add --name=cors-conf --mount-path /opt/app-root/src/apicast.d/cors.conf --source='{"configMap":{"name":"cors-conf","items":[{"key":"cors.conf","path":"cors.conf"}]}}'
```

4. The `oc volume` command doesn't support adding subpaths, so a patch needs to be applied:

```
oc patch dc/apicast --type=json -p '[{"op": "add", "path": "/spec/template/spec/containers/0/volumeMounts/0/subPath", "value":"apicast_cors.lua"},{"op": "add", "path": "/spec/template/spec/containers/0/volumeMounts/1/subPath", "value":"cors.conf"}]'
oc patch dc/apicast --type=json -p '[{"op": "add", "path": "/spec/template/spec/containers/0/volumeMounts/0/subPath", "value":"cors.lua"},{"op": "add", "path": "/spec/template/spec/containers/0/volumeMounts/1/subPath", "value":"cors.conf"}]'
```

5. As in previous example, set the environment variable `APICAST_MODULE`:

```
oc env dc/apicast APICAST_MODULE=apicast_cors
oc env dc/apicast APICAST_MODULE=cors
```
35 changes: 0 additions & 35 deletions examples/cors/apicast_cors.lua

This file was deleted.

54 changes: 54 additions & 0 deletions examples/cors/cors.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
local apicast = require('apicast').new()

local _M = { _VERSION = apicast._VERSION, _NAME = 'APIcast with CORS' }

local mt = { __index = setmetatable(_M, { __index = apicast }) }

function _M.new()
return setmetatable({}, mt)
end

local function set_cors_headers()
local origin = ngx.var.http_origin

if not origin then return end

ngx.header['Access-Control-Allow-Headers'] = ngx.var.http_access_control_request_headers
ngx.header['Access-Control-Allow-Methods'] = ngx.var.http_access_control_request_method
ngx.header['Access-Control-Allow-Origin'] = origin
ngx.header['Access-Control-Allow-Credentials'] = 'true'
end

local function cors_preflight_response()
set_cors_headers()
ngx.status = 204
ngx.exit(ngx.status)
end

local function cors_preflight()
return (
ngx.req.get_method() == 'OPTIONS' and
ngx.var.http_origin and
ngx.var.http_access_control_request_method
)
end

-- header_filter is used to manipulate response headers
function _M.header_filter()
set_cors_headers()

return apicast:header_filter()
end

-- rewrite is the first phase executed and can hijack the whole request handling
function _M.rewrite()
-- for CORS preflight sent by the browser, return a 204 status code
if cors_preflight() then
return cors_preflight_response()
else
-- if the request is not CORS preflight jut continue with APIcast flow
return apicast:rewrite()
end
end

return _M

0 comments on commit aaff93f

Please sign in to comment.