OSDE
The OpenLink Structured Data Editor
When a browser loads a page from a server, which perform an Ajax call via javascript to a second server, the browser will setup an HTTP connection to the second server, add an —
Origin: host
— header, perform the OPTIONS
/GET
/HEAD
/PUT
request,
and retrieve the result-headers as well as any data passed back from the second server.
The browser then checks if the result-headers contain a —
Access-Control-Allow-Origin: host
— or —
Access-Control-Allow-Origin: *
If this header is available, the browser will set the correct HTTP status code, as well the
responseText
, which is needed to make a proper error dialog if the status is an error state
like 404
.
If this header is not available, the browser will simply return a HTTP status code 0
and a status text "error
", no matter whether the request succeeded or failed to
begin with.
The console log will contain get a more informative CORS related error, but this is NOT available for normal javascript to retrieve.
It is also impossible, as far as we have been able to determine, to get the response headers from the server (which is the only place from which the real HTTP status codes and other texts can be retrieved).
So when an Ajax call gets 'error
' with HTTP status 0
, the ONLY dialog
we can give is that it possibly is a CORS related problem.
The only reason we can think of why browser developers would have coded it like this, would be to hide
URL probing, so when a server is NOT CORS enabled, no-one can try out different URLs to see whether
they are there (which would be indicated by the state 0
) or not (which would result in
a proper 404
status). However, since it would be just as easy to test this directly
with curl
, it is rather a far-fetched reason.
We cannot find an official answer for this strange behavior, but it does makes web app development and error reporting very hard.
Most web server installations do not return CORS headers on HTTP 40x
error states, which means
that any error from these servers is simply NOT retrievable.
It took us a long time to actually get both apache
and nginx
to add these headers
to 40x
states, which is something of course NOT fully documented correctly by the CORS proponents.
There are a number of different scenarios that have different effects when a page with javascript tries to make an Ajax call to retrieve some data.
We have a server that is not CORS enabled, but the app is running on the same server.
In this case the app works without any problems, as the browser sees the call is to the same host that the
page was loaded from, so it will not use Origin
and will return the proper HTTP status codes
and error messages.
We have a server that is not CORS enabled, and the app is running from a different host.
In this case all Ajax requests will check for Access-Control-Allow-Origin
in the response-headers,
and because it is not there, all requests get HTTP code 0
and should report something like
'Request failed possibly due to missing CORS setup of the server'.
We have a server that is CORS enabled for normal pages (where the header is returned by the page), and the app is running from a different host.
In this case any page request that succeeds with status 200
will work, but any redirect
(30x
) or error (40x
, 50x
) will NOT return a proper error, since
these pages will not have an Access-Control-Allow-Origin
, so the error state is completely
hidden from the web application and can therefore only report something like 'Request failed possibly
due to missing CORS setup of the server'.
We have a server that is CORS enabled, and an app running on the SAME system. However the app calls a short URL on the same server, so this does not require any special headers.
Unfortunately that short URL is automatically expanded by the Ajax call which will do an internal retry
to the new Location which may be on another server. In this case if that new server conforms to scenario
1, 2, or 3 you still won't get any error information other than an HTTP status 0
. What
is even worse is that you cannot even get the info to the redirected URL so you cannot even check yourself
if the url.location.host
matches windows.location.host
which is the way the rdf
-editor tries to distinguish CORS errors from non-CORS errors when HTTP state = 0
.
We have a server that is CORS enabled for ALL pages, including redirect (30x
) and error
(40x
, 50x
) pages, and an app is running from a different host.
In this case there will always be an Access-Control-Allow-Origin
in the response-headers and
error information IS passed on to the web application to show to the user.
Currently, http://dbpedia.org
is the ONLY
system that has this complete setup enabled.
$ curl -I -H 'Origin: pipo' "http://dbpedia-live.openlinksw.com/resource/OpenLink" HTTP/1.1 303 See Other Date: Thu, 07 Apr 2016 19:17:07 GMT Content-Type: text/html; charset=UTF-8 Content-Length: 0 Connection: keep-alive Server: Virtuoso/07.20.3216 (Linux) i686-generic-linux-glibc212-64 VDB Location: http://dbpedia-live.openlinksw.com/page/OpenLink Expires: Thu, 07 Apr 2016 19:18:07 GMT Cache-Control: max-age=60
As we see the redirect page does not have the correct CORS headers, so this next link will give a generic CORS error:
$ curl -I -H 'Origin: pipo' "http://dbpedia.org/resource/OpenLink" HTTP/1.1 303 See Other Date: Thu, 07 Apr 2016 19:17:27 GMT Content-Type: text/html; charset=UTF-8 Content-Length: 0 Connection: keep-alive Server: Virtuoso/07.20.3216 (Linux) i686-generic-linux-glibc212-64 VDB Location: http://dbpedia.org/page/OpenLink Expires: Thu, 14 Apr 2016 19:17:27 GMT Cache-Control: max-age=604800 Access-Control-Allow-Origin: pipo Access-Control-Allow-Credentials: true Access-Control-Allow-Methods: HEAD, GET, POST, OPTIONS Access-Control-Allow-Headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type
Since the 303
page does have the right CORS headers, the Ajax call will subsequently load
the correct .n3
page and display the results:
http://ods-qa.openlinksw.com/rdf-editor/#/editor?uri=http:%2F%2Fdbpedia.org%2Fresource%2FOpenLink