0

Hi all i have an istance of xwiki on my localhost, for a test purpose i wanted to test the RESTful api by writing some simple jquery script:

<script type="text/javascript">

var username = "Admin";
var password ="admin";  

function make_base_auth(user, password) 
  {

    var tok = user + ':' + password;
    var hash = btoa(tok);
    alert(hash);
    return "Basic " + hash;

  }

var url = "http://localhost:8080/xwiki/rest/wikis/query?q=object:XWiki.XWikiUsers";
var returnData = "";
$.ajax({
    type: "GET",
    dataType: "xml",
    crossDomain: true,
    async: true,
    url: url,
     headers: {"authorization":  make_base_auth(username, password), "Access-Control-Allow-Origin": "*" },

    error: function(request, status, error) 
    {   
        alert(error) 
    },
    success: function(data) 
    {
       alert("success");

    }

       });    
</script>

the error i get is:

XMLHttpRequest cannot load http://localhost:8080/xwiki/rest/wikis/query?q=object:XWiki.XWikiUsers. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.

but trying with postman i get the correct result...i'm missing something? thanks

Lorenzo
  • 673
  • 1
  • 11
  • 25
  • if you send authentication information it is no longer a "simple" request and you need to configure XWiki (in the `web.xml`) to allow these requests ... do you really need the auth info? (Probably yes, if the wiki is not public) – Clemens Klein-Robbenhaar Feb 17 '16 at 16:48

2 Answers2

1

In the default configuration XWiki does not allow CORS; you need to enable it in the web.xml

To allow sending authentication data with the authentication header, edit the file web.xml and add a new filter among the section with the filters:

<filter>
  <filter-name>Set CORS headers very lenitent</filter-name>
  <filter-class>org.xwiki.container.servlet.filters.internal.SetHTTPHeaderFilter</filter-class>
  <init-param>
    <param-name>name</param-name>
    <param-value>Access-Control-Allow-Headers</param-value>
  </init-param>
  <init-param>
    <param-name>value</param-name>
    <param-value>authorization</param-value>
  </init-param>
</filter>

Now you need to activate the filter; further down among the filter-mappings add your own:

<filter-mapping>
  <filter-name>Set CORS headers very lenitent</filter-name>
  <servlet-name>RestletServlet</servlet-name>
</filter-mapping>

(and yes, if you do not like the filter name, use a different name, just use the same name in both places.)

As you figured out in the comments, allowing several HTTP headers works like:

<filter>
  <filter-name>Set CORS headers very lenitent</filter-name>
  <filter-class>org.xwiki.container.servlet.filters.internal.SetHTTPHeaderFilter</filter-class>
  <init-param>
    <param-name>name</param-name>
    <param-value>Access-Control-Allow-Headers</param-value>
  </init-param>
  <init-param>
    <param-name>value</param-name>
    <param-value>authorization, content-type</param-value>
  </init-param>
</filter>

(in this case allowing both the authorization header and a "non-standard" Content-Type header) (side note: headers are case-nsensitive: Are HTTP headers case-sensitive?)

Also you need to allow CORS in general for REST-request; for this search for:

<!-- We set the CORS policy globally for webjars.
   ... longer comment ....
  -->
<filter-mapping>
  <filter-name>Set CORS policy for fonts</filter-name>
  <servlet-name>resourceReferenceHandler</servlet-name>
  <url-pattern>/webjars/*</url-pattern>
  <url-pattern>*.woff</url-pattern>
  <url-pattern>*.eot</url-pattern>
  <url-pattern>*.ttf</url-pattern>
  <dispatcher>REQUEST</dispatcher>
  <dispatcher>FORWARD</dispatcher>
</filter-mapping>

edit the filter-mapping and add a line <servlet-name>RestletServlet</servlet-name> to activate this filter for the rest servlet, too:

<filter-mapping>
  <filter-name>Set CORS policy for fonts</filter-name>
  <servlet-name>resourceReferenceHandler</servlet-name>
  <servlet-name>RestletServlet</servlet-name>
  <url-pattern>/webjars/*</url-pattern>
  [...]

After a restart of the servlet container the AJAX request should now work.

Community
  • 1
  • 1
Clemens Klein-Robbenhaar
  • 3,457
  • 1
  • 18
  • 27
  • Great but how can i modify the xml to allow also: Access-Control-Allow-Methods? This because trying a put method it raised that error – Lorenzo Feb 22 '16 at 16:32
  • 1
    Probably the same way, i.e. add yet another `` with `org.xwiki.container.servlet.filters.internal.SetHTTPHeaderFilter` and where `name` is `Access-Control-Allow-Methods`. not sure about the `value` however ... – Clemens Klein-Robbenhaar Feb 22 '16 at 17:31
  • 1
    ... probably `GET, POST, PUT, DELETE` - more CORS stuff e.g. https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS (but sure there is a better ref?) – Clemens Klein-Robbenhaar Feb 22 '16 at 17:38
  • my doubt was about the filter class, thanks i'll try – Lorenzo Feb 23 '16 at 07:59
  • now i get: Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed. Origin 'null' is therefore not allowed access. when i perform a POST method – Lorenzo Feb 23 '16 at 09:11
  • ok now it seems to do the authorization and the put (without specifying the contentType)...but...because i should specify the type of data i pass i set : contentType:"application/xml", and i get Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response. – Lorenzo Feb 23 '16 at 10:52
  • i'm lucky that xwiki accept the default application/x-www-form-urlencoded, so i can send it..but i'm curious to know how to add this contentType option to web.xml – Lorenzo Feb 23 '16 at 11:14
  • 1
    web.xml documentation e,g, at: http://docs.oracle.com/cd/E13222_01/wls/docs81/webapp/web_xml.html and CORS tutorial: see my last comment – Clemens Klein-Robbenhaar Feb 24 '16 at 09:07
  • mmm adding value2 contentType to Set CORS headers very lenitent still give me errors regarding contenType... – Lorenzo Feb 24 '16 at 15:57
  • solved this way authorization, Content-Type thank you! – Lorenzo Feb 25 '16 at 08:39
0

You can modify web.xml file for enabling cors (I am using jetty server). I added the below mentioned filter.

<filter>
      <filter-name>cross-origin</filter-name>
      <filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class>
       <init-param>
         <param-name>allowedOrigins</param-name>
         <param-value>*</param-value>
       </init-param>
       <init-param>
         <param-name>allowedMethods</param-name>
         <param-value>GET,POST,DELETE,PUT,HEAD</param-value>
       </init-param>
       <init-param>
         <param-name>allowedHeaders</param-name>
         <param-value>origin, content-type, accept, authorization</param-value>
       </init-param>
  </filter>
  <filter-mapping>
     <filter-name>cross-origin</filter-name>
     <url-pattern>/*</url-pattern>
  </filter-mapping>

Then you need to Download and add jetty servlet jar from here

Put this jar inside the lib folder, then restart your server and the cors is enabled for jetty server.

totten
  • 2,769
  • 3
  • 27
  • 41