diff --git a/doc/source/crossdomain.xml b/doc/source/crossdomain.xml
new file mode 100644
index 0000000000..3bdb43d908
--- /dev/null
+++ b/doc/source/crossdomain.xml
@@ -0,0 +1,55 @@
+========================
+Cross-domain Policy File
+========================
+
+A cross-domain policy file allows web pages hosted elsewhere to use client
+side technologies such as Flash, Java and Silverlight to interact
+with the Swift API.
+
+See http://www.adobe.com/devnet/articles/crossdomain_policy_file_spec.html for
+a description of the purpose and structure of the cross-domain policy
+file. The cross-domain policy file is installed in the root of a web
+server (i.e., the path is /crossdomain.xml).
+
+The crossdomain middleware responds to a path of /crossdomain.xml with an
+XML document such as::
+
+
+
+
+
+
+
+You should use a policy appropriate to your site. The examples and the
+default policy are provided to indicate how to syntactically construct
+a cross domain policy file -- they are not recommendations.
+
+-------------
+Configuration
+-------------
+
+To enable this middleware, add it to the pipeline in your proxy-server.conf
+file. It should be added before any authentication (e.g., tempauth or
+keystone) middleware. In this example ellipsis (...) indicate other
+middleware you may have chosen to use::
+
+ [pipeline:main]
+ pipeline = ... crossdomain ... authtoken ... proxy-server
+
+And add a filter section, such as::
+
+ [filter:crossdomain]
+ use = egg:swift#crossdomain
+ cross_domain_policy =
+
+
+For continuation lines, put some whitespace before the continuation
+text. Ensure you put a completely blank line to terminate the
+cross_domain_policy value.
+
+The cross_domain_policy name/value is optional. If omited, the policy
+defaults as if you had specified::
+
+ cross_domain_policy =
+
+
diff --git a/doc/source/index.rst b/doc/source/index.rst
index 89b6102b92..55a84b8e10 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -54,6 +54,7 @@ Overview and Concepts
overview_container_sync
overview_expiring_objects
cors
+ crossdomain
associated_projects
Developer Documentation
diff --git a/setup.py b/setup.py
index 0702feb4b4..229dc97e18 100644
--- a/setup.py
+++ b/setup.py
@@ -89,6 +89,7 @@ setup(
],
'paste.filter_factory': [
'healthcheck=swift.common.middleware.healthcheck:filter_factory',
+ 'crossdomain=swift.common.middleware.crossdomain:filter_factory',
'memcache=swift.common.middleware.memcache:filter_factory',
'ratelimit=swift.common.middleware.ratelimit:filter_factory',
'cname_lookup=swift.common.middleware.cname_lookup:filter_factory',
diff --git a/swift/common/middleware/crossdomain.py b/swift/common/middleware/crossdomain.py
new file mode 100644
index 0000000000..ea9b759e09
--- /dev/null
+++ b/swift/common/middleware/crossdomain.py
@@ -0,0 +1,90 @@
+# Copyright (c) 2013 OpenStack Foundation.
+#
+# Licensed 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.
+
+from swift.common.swob import Request, Response
+
+
+class CrossDomainMiddleware(object):
+
+ """
+ Cross domain middleware used to respond to requests for cross domain
+ policy information.
+
+ If the path is /crossdomain.xml it will respond with an xml cross domain
+ policy document. This allows web pages hosted elsewhere to use client
+ side technologies such as Flash, Java and Silverlight to interact
+ with the Swift API.
+
+ To enable this middleware, add it to the pipeline in your proxy-server.conf
+ file. It should be added before any authentication (e.g., tempauth or
+ keystone) middleware. In this example ellipsis (...) indicate other
+ middleware you may have chosen to use::
+
+ [pipeline:main]
+ pipeline = ... crossdomain ... authtoken ... proxy-server
+
+ And add a filter section, such as::
+
+ [filter:crossdomain]
+ use = egg:swift#crossdomain
+ cross_domain_policy =
+
+
+ For continuation lines, put some whitespace before the continuation
+ text. Ensure you put a completely blank line to terminate the
+ cross_domain_policy value.
+
+ The cross_domain_policy name/value is optional. If omited, the policy
+ defaults as if you had specified::
+
+ cross_domain_policy =
+
+
+ """
+
+ def __init__(self, app, conf, *args, **kwargs):
+ self.app = app
+ self.conf = conf
+ default_domain_policy = ''
+ self.cross_domain_policy = self.conf.get('cross_domain_policy',
+ default_domain_policy)
+
+ def GET(self, req):
+ """Returns a 200 response with cross domain policy information """
+ body = '\n' \
+ '\n' \
+ '\n' \
+ '%s\n' \
+ '' % self.cross_domain_policy
+ return Response(request=req, body=body,
+ content_type="application/xml")
+
+ def __call__(self, env, start_response):
+ req = Request(env)
+ if req.path == '/crossdomain.xml' and req.method == 'GET':
+ return self.GET(req)(env, start_response)
+ else:
+ return self.app(env, start_response)
+
+
+def filter_factory(global_conf, **local_conf):
+ conf = global_conf.copy()
+ conf.update(local_conf)
+
+ def crossdomain_filter(app):
+ return CrossDomainMiddleware(app, conf)
+ return crossdomain_filter
diff --git a/test/unit/common/middleware/test_crossdomain.py b/test/unit/common/middleware/test_crossdomain.py
new file mode 100644
index 0000000000..3031981896
--- /dev/null
+++ b/test/unit/common/middleware/test_crossdomain.py
@@ -0,0 +1,85 @@
+# Copyright (c) 2013 OpenStack Foundation.
+#
+# Licensed 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.
+
+import unittest
+
+from swift.common.swob import Request, Response
+
+from swift.common.middleware import crossdomain
+
+
+class FakeApp(object):
+
+ def __call__(self, env, start_response):
+ return "FAKE APP"
+
+
+def start_response(*args):
+ pass
+
+
+class TestCrossDomain(unittest.TestCase):
+
+ def setUp(self):
+ self.app = crossdomain.CrossDomainMiddleware(FakeApp(), {})
+
+ # GET of /crossdomain.xml (default)
+ def test_crossdomain_default(self):
+ expectedResponse = '\n' \
+ '\n' \
+ '\n' \
+ '\n' \
+ ''
+
+ req = Request.blank('/crossdomain.xml',
+ environ={'REQUEST_METHOD': 'GET'})
+ resp = self.app(req.environ, start_response)
+ self.assertEquals(resp, [expectedResponse])
+
+ # GET of /crossdomain.xml (custom)
+ def test_crossdomain_custom(self):
+ conf = {'cross_domain_policy': '\n'}
+ self.app = crossdomain.CrossDomainMiddleware(FakeApp(), conf)
+ expectedResponse = '\n' \
+ '\n' \
+ '\n' \
+ '\n' \
+ '\n' \
+ ''
+
+ req = Request.blank('/crossdomain.xml',
+ environ={'REQUEST_METHOD': 'GET'})
+ resp = self.app(req.environ, start_response)
+ self.assertEquals(resp, [expectedResponse])
+
+ # GET to a different resource should be passed on
+ def test_crossdomain_pass(self):
+ req = Request.blank('/', environ={'REQUEST_METHOD': 'GET'})
+ resp = self.app(req.environ, start_response)
+ self.assertEquals(resp, 'FAKE APP')
+
+ # Only GET is allowed on the /crossdomain.xml resource
+ def test_crossdomain_get_only(self):
+ for method in ['HEAD', 'PUT', 'POST', 'COPY', 'OPTIONS']:
+ req = Request.blank('/crossdomain.xml',
+ environ={'REQUEST_METHOD': method})
+ resp = self.app(req.environ, start_response)
+ self.assertEquals(resp, 'FAKE APP')
+
+
+if __name__ == '__main__':
+ unittest.main()