Ravi
Ravi

Reputation: 1179

MarkLogic Custom Rest Endpoint set Access-Control-Allow-Origin for preflight request

I am setting in my custom rest endpoint the "Access-Control-Allow-Origin", but when I call this webservice from javascript, I get the following error

XMLHttpRequest cannot load http://10.239.12.22:8042/LATEST/resources/repoUIFacet?rs:q=TNF. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://gprulcd707873.abbvienet.com:8000' is therefore not allowed access. The response had HTTP status code 401.

Following is the code where I set the response header

(: Function responding to GET method - must use local name 'get':)
declare function repoUIFacet:get($context as map:map, $params  as map:map) as document-node()*
{
    let $output-types := map:put($context,"output-types","application/json")

    let $_ := xdmp:add-response-header("Access-Control-Allow-Origin", "*")
    ...
};

How do I set the response header for an OPTIONS request ?

Upvotes: 1

Views: 345

Answers (3)

Ravi
Ravi

Reputation: 1179

If anyone is interested, Following is what I did instead of writing a custom webservice layer in front of MarkLogic custom rest-api..
I basically have an Apache server that acts as proxy to custom Marklogic endpoints. Then I set the CORS header for it.. And also catch the OPTIONS request and send a 200.. Just letting you know, that when the request has Authorization. the '*' Access-Control-Allow-Origin *, will not work.. you need to specify the hosts.. I did a workaround of putting a regular expression, following is how I do it in my apache config or .htaccess file

 <IfModule mod_headers.c>
    SetEnvIf Origin "^http(s)?://(.+\.)?(YOUR_DOMAIN.com)(:[0-9]+)?$" origin_is=$0
    Header always set Access-Control-Allow-Origin %{origin_is}e env=origin_is
    Header always set Access-Control-Allow-Methods "POST, GET, PUT, DELETE, OPTIONS"
    Header always set Access-Control-Max-Age "1000"
    Header always set Access-Control-Allow-Headers "X-Requested-With, content-type, Access-Control-Allow-Origin, Authorization, X-User-Id"
  </IfModule>

  RewriteEngine on
  RewriteCond %{REQUEST_METHOD} OPTIONS
  RewriteRule ^(.*)$ $1 [R=200,L]

  ProxyPass /cr_dev http://10.239.12.22:8042/LATEST/resources
  ProxyPassReverse /cr_dev/ http://10.239.12.22:8042/LATEST/resources

Upvotes: 2

chriskelly
chriskelly

Reputation: 7736

I ran into a similar issue lately. On issuing a request from the browser, the browser sends an additional OPTIONS request to MarkLogic. However my router checked for an api_key and if it didn't exists I responded with a 40x code.

What worked was respsonding with a 200 code whenever the incoming method is OPTIONS before checking the api key. All other methods check the api and return the appropriate response code.

e.g. if you are using an xquery router, you could try something like this:

let $method := fn:lower-case(xdmp:get-request-method())

(: Intercept OPTIONS method and respond immediately :)
if ($methods = 'options') then 
    xdmp:set-response-code(200, 'OK')
else (:
    invoke the endpoint function "$method", e.g. repoUIFacet:get
:)

Good luck!

Upvotes: 2

grtjn
grtjn

Reputation: 20414

The error message ends with The response had HTTP status code 401. This is an issue with authentication, not with the access control header. You need to send credentials, or switch the app server to application-level authentication.

HTH!

Upvotes: 2

Related Questions