REST API

Cross-Origin Resource Sharing (CORS)

Updated: July 17, 2023

If you do cross-domain requests from any JavaScript client to access WebEngine resources or Automation APIs, there's a chance that your browser forbids it. Since version 5.7.2, CORS allows you to communicate with Nuxeo from another domain using XMLHttpRequests.

Nuxeo uses a filter to handle those cases. It is based on Vladimir Dzhuvinov's universal CORS filter, and allows you to configure on which URLs cross-origin headers are needed. You'll be able to configure each URL independently.

Here is a the simplest contribution, to allow cross-domain request on the whole foobar site:

Simplest contribution

  <extension target="org.nuxeo.ecm.platform.web.common.requestcontroller.service.RequestControllerService" point="corsConfig">
    <corsConfig name="foobar">
      <pattern>/nuxeo/site/foobar/.*</pattern>
    </corsConfig>
  </extension>

Configuration

Here is the list of all contribution attributes. There are all optional.

Attribute nameDescriptionDefault valuePossible values ("|" separates possible values)
allowGenericHttpRequests If false, only valid and accepted CORS requests that be allowed (strict CORS filtering). truetrue | false
allowOrigin The whitespace-separated list of origins that the CORS filter must allow. * *&nbsp;| <span class="nolink"><span class="nolink">http://example.com</span>&nbsp;</span> <span class="nolink"><span class="nolink">http://example.com:8080</span></span>
allowSubdomains If true the CORS filter will allow requests from any origin which is a sub-domain origin of the allowed origins. falsetrue | false
supportedMethodsThe list of the supported HTTP methods.<span style="color: rgb(61,61,61);">GET, POST, HEAD, OPTIONS</span>"," separates list of HTTP methods
supportedHeadersThe names of the supported author request headers.** | "," separates list of headers
exposedHeaders The list of the response headers other than simple response headers that the browser should expose to the author of the cross-domain request through the XMLHttpRequest.getResponseHeader() method. -"," separates list of headers
supportsCredentials Indicates whether user credentials, such as cookies, HTTP authentication or client-side certificates, are supported. truetrue | false
maxAge Indicates how long the results of a preflight request can be cached by the web browser, in seconds. -1integer

For instance, a fooly complete contribution could looks like:

Fooly contribution

      <extension target="org.nuxeo.ecm.platform.web.common.requestcontroller.service.RequestControllerService" point="corsConfig">
        <corsConfig name="fooly" allowGenericHttpRequests="true"
          allowOrigin="http://example.com http://example.com:8080"
          allowSubdomains="true" supportedMethods="GET"
          supportedHeaders="Content-Type, X-Requested-With"
          exposedHeaders="X-Custom-1, X-Custom-2"
          supportsCredentials="false" maxAge="3600">
          <pattern>/fooly/site/.*</pattern>
        </corsConfig>
      </extension>

Making sure the contribution is taken into account

To debug your CORS configuration, you might use cURL and look at the response. If you haven't blocked OPTIONS method, you should test with the preflight request for an expected POST request:

Simulate preflight request

curl --verbose -H "Origin: http://www.nuxeo.com" -H "Access-Control-Request-Method: POST" -H "Access-Control-Request-Headers: X-Requested-With" -X OPTIONS http://localhost:8080/nuxeo/site/foobar/upload

With the default configuration, preflight's response must looks like:

Default response

< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< Access-Control-Allow-Origin: http://www.nuxeo.com
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Methods: HEAD, POST, GET, OPTIONS
< Access-Control-Allow-Headers: X-Requested-With
< Content-Length: 0 

With these "Access-Control-Allow-*" headers containing expected values.