BaseX REST API: Set custom HTTP response header - rest

I want to include the following HTTP header to all responses by the BaseX REST API:
Access-Control-Allow-Origin: *
Is this possible?

BaseX uses Jetty below the hood. You can modify the web.xml file to make Jetty send CORS headers, but either
use at least BaseX 8.6.3 which added the jetty-servlets library or
have to add the jetty-servlets jar to your $CLASSPATH (BaseX already ships jetty-servlet, which is a different class; and be sure to fetch the appropriate version matching what's included in BaseX).
Include following directives to the web.xml file:
<web-app>
<!-- add those before the closing web-app tag: -->
<filter>
<filter-name>cross-origin</filter-name>
<filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>cross-origin</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
Be aware that Jetty does not seem to support posting a wildcard header Access-Control-Allow-Origin: *: while the default is already
<init-param>
<param-name>allowedOrigins</param-name>
<param-value>*</param-value>
</init-param>
(put that into the <filter/> element), Jetty uses this to construct a regular expression and always returns the value of the Origin: request header if matching, but that should also serve you well.
An example request:
$ curl -v -H "Origin: http://foo.example" http://admin:admin#localhost:8984/rest
* Trying ::1...
* Connected to localhost (::1) port 8984 (#0)
* Server auth using Basic with user 'admin'
> GET /rest HTTP/1.1
> Host: localhost:8984
> Authorization: Basic YWRtaW46YWRtaW4=
> User-Agent: curl/7.50.1
> Accept: */*
> Origin: http://foo.example
>
< HTTP/1.1 200 OK
< Content-Type: application/xml; charset=UTF-8
< Content-Length: 152
< Server: Jetty(8.1.18.v20150929)
<
<rest:databases xmlns:rest="http://basex.org/rest" resources="1">
<rest:database resources="1" size="96234589">test</rest:database>
</rest:databases>
* Connection #0 to host localhost left intact
Given this seems a rather reasonable request and thing to do, you might be successful opening an issue to include the library by default, and maybe even enabling CORS by default. (the library is now included by default)

Related

JasperReport Server REST 2 api - Creating a new report

I was not able to find any api that can actually create a report on the JasperReports Server.
There is one to create resource.
http://community.jaspersoft.com/documentation/jasperreports-server-web-services-guide/v550/creating-resource
To an extend it tells about how to create a folder etc. but talks nothing about creating a report in all.
Any idea on how a report (jrxml) can be done in a programmatic way?
Thanks.
To post your reports manually to the JasperServer repository, use the same method as in the link you posted, but you aren't posting a resourceDescriptor. You should be posting a reportUnit instead.
Here is an example of the PUT command where I'm sending a (gzipped) jrxml file I named TestJrxmlFile to the repository creating a new report:
PUT http://localhost:8080/jasperserver-pro/rest_v2/resources/public/TestJrxmlFile?createFolders=true&overwrite=true HTTP/1.1
Content-Type: application/repository.reportUnit+xml
User-Agent: Jersey/2.13 (Apache HttpClient 4.3.4)
Transfer-Encoding: chunked
Host: localhost:8080
Connection: Keep-Alive
Cookie: JSESSIONID=45F47838C567120CF4DB1068AE0473C4; userLocale=en_US
Cookie2: $Version=1
Accept-Encoding: gzip,deflate
82d
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><reportUnit><description>ds</description><label>TestJrxmlFile</label><permissionMask>1</permissionMask><uri>/public/TestJrxmlFile</uri><version>-1</version><alwaysPromptControls>true</alwaysPromptControls><controlsLayout>popupScreen</controlsLayout><resources/><inputControls/><jrxmlFile><label>Main jrxml</label><permissionMask>1</permissionMask><uri>/public/TestJrxmlFile_files/main_jrxml</uri><version>-1</version><content>PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCEtLSBDcmVhdGVkIHdpdGggSmFzcGVyc29mdCBTdHVkaW8gdmVyc2lvbiA2LjEuMC5maW5hbCB1c2luZyBKYXNwZXJSZXBvcnRzIExpYnJhcnkgdmVyc2lvbiA2LjEuMCAgLS0+CjwhLS0gMjAxNS0xMS0xM1QwOTo1OTo1MiAtLT4KPGphc3BlclJlcG9ydCB4bWxucz0iaHR0cDovL2phc3BlcnJlcG9ydHMuc291cmNlZm9yZ2UubmV0L2phc3BlcnJlcG9ydHMiIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL2phc3BlcnJlcG9ydHMuc291cmNlZm9yZ2UubmV0L2phc3BlcnJlcG9ydHMgaHR0cDovL2phc3BlcnJlcG9ydHMuc291cmNlZm9yZ2UubmV0L3hzZC9qYXNwZXJyZXBvcnQueHNkIiBuYW1lPSJCbGFua19BNCIgcGFnZVdpZHRoPSI1OTUiIHBhZ2VIZWlnaHQ9Ijg0MiIgY29sdW1uV2lkdGg9IjU1NSIgbGVmdE1hcmdpbj0iMjAiIHJpZ2h0TWFyZ2luPSIyMCIgdG9wTWFyZ2luPSIyMCIgYm90dG9tTWFyZ2luPSIyMCIgdXVpZD0iOTlmNDQzNzAtY2FjNi00YWVkLTgyMDUtMDdkMThmZDUwNmJmIj4KCTxxdWVyeVN0cmluZz4KCQk8IVtDREFUQVtdXT4KCTwvcXVlcnlTdHJpbmc+Cgk8YmFja2dyb3VuZD4KCQk8YmFuZCBzcGxpdFR5cGU9IlN0cmV0Y2giLz4KCTwvYmFja2dyb3VuZD4KCTx0aXRsZT4KCQk8YmFuZCBoZWlnaHQ9Ijc5IiBzcGxpdFR5cGU9IlN0cmV0Y2giLz4KCTwvdGl0bGU+Cgk8cGFnZUhlYWRlcj4KCQk8YmFuZCBoZWlnaHQ9IjM1IiBzcGxpdFR5cGU9IlN0cmV0Y2giLz4KCTwvcGFnZUhlYWRlcj4KCTxjb2x1bW5IZWFkZXI+CgkJPGJhbmQgaGVpZ2h0PSI2MSIgc3BsaXRUeXBlPSJTdHJldGNoIi8+Cgk8L2NvbHVtbkhlYWRlcj4KCTxkZXRhaWw+CgkJPGJhbmQgaGVpZ2h0PSIxMjUiIHNwbGl0VHlwZT0iU3RyZXRjaCIvPgoJPC9kZXRhaWw+Cgk8Y29sdW1uRm9vdGVyPgoJCTxiYW5kIGhlaWdodD0iNDUiIHNwbGl0VHlwZT0iU3RyZXRjaCIvPgoJPC9jb2x1bW5Gb290ZXI+Cgk8cGFnZUZvb3Rlcj4KCQk8YmFuZCBoZWlnaHQ9IjU0IiBzcGxpdFR5cGU9IlN0cmV0 Y2giLz4KCTwvcGFnZUZvb3Rlcj4KCTxzdW1tYXJ5PgoJCTxiYW5kIGhlaWdodD0iNDIiIHNwbGl0VHlwZT0iU3RyZXRjaCIvPgoJPC9zdW1tYXJ5Pgo8L2phc3BlclJlcG9ydD4K
35
</content><type>jrxml</type></jrxmlFile></reportUnit>
0
Updating a single jrxml file would require posting a file a la
PUT http://localhost:8080/jasperserver-pro/rest_v2/resources/public/TestJrxmlFile_files/main_jrxml?createFolders=true&overwrite=true HTTP/1.1
Content-Type: application/repository.file+xml
User-Agent: Jersey/2.13 (Apache HttpClient 4.3.4)
Transfer-Encoding: chunked
Host: localhost:8080
Connection: Keep-Alive
Cookie: JSESSIONID=CBE64F76548FC2D4CB73281A6FEB9319; userLocale=en_US
Cookie2: $Version=1
Accept-Encoding: gzip,deflate
93a
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><file><creationDate>2015-11-13T09:59:55</creationDate><label>Main jrxml</label><permissionMask>1</permissionMask><updateDate>2015-11-13T09:59:55</updateDate><uri>/public/TestJrxmlFile_files/main_jrxml</uri><version>0</version><content>PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCEtLSBDcmVhdGVkIHdpdGggSmFzcGVyc29mdCBTdHVkaW8gdmVyc2lvbiA2LjEuMC5maW5hbCB1c2luZyBKYXNwZXJSZXBvcnRzIExpYnJhcnkgdmVyc2lvbiA2LjEuMCAgLS0+CjwhLS0gMjAxNS0xMS0xM1QxMDoxMjowNiAtLT4KPGphc3BlclJlcG9ydCB4bWxucz0iaHR0cDovL2phc3BlcnJlcG9ydHMuc291cmNlZm9yZ2UubmV0L2phc3BlcnJlcG9ydHMiIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL2phc3BlcnJlcG9ydHMuc291cmNlZm9yZ2UubmV0L2phc3BlcnJlcG9ydHMgaHR0cDovL2phc3BlcnJlcG9ydHMuc291cmNlZm9yZ2UubmV0L3hzZC9qYXNwZXJyZXBvcnQueHNkIiBuYW1lPSJCbGFua19BNCIgcGFnZVdpZHRoPSI1OTUiIHBhZ2VIZWlnaHQ9Ijg0MiIgY29sdW1uV2lkdGg9IjU1NSIgbGVmdE1hcmdpbj0iMjAiIHJpZ2h0TWFyZ2luPSIyMCIgdG9wTWFyZ2luPSIyMCIgYm90dG9tTWFyZ2luPSIyMCIgdXVpZD0iOTlmNDQzNzAtY2FjNi00YWVkLTgyMDUtMDdkMThmZDUwNmJmIj4KCTxwcm9wZXJ0eSBuYW1lPSJpcmVwb3J0Lmphc3BlcnNlcnZlci51cmwiIHZhbHVlPSJodHRwOi8vbG9jYWxob3N0OjgwODAvamFzcGVyc2VydmVyLXByby8iLz4KCTxwcm9wZXJ0eSBuYW1lPSJpcmVwb3J0Lmphc3BlcnNlcnZlci51c2VyIiB2YWx1ZT0iamFzcGVyYWRtaW4iLz4KCTxwcm9wZXJ0eSBuYW1lPSJpcmVwb3J0Lmphc3BlcnNlcnZlci5yZXBvcnQucmVzb3VyY2UiIHZhbHVlPSIvcHVibGljL1Rlc3RKcnhtbEZpbGVfZmlsZXMvbWFpbl9qcnhtbCIvPgoJPHByb3BlcnR5IG5hbWU9ImlyZXBvcnQuamFzcGVyc2VydmVyLnJlcG9ydFVuaXQiIHZhbHVlPSIvcHVibGljL1Rlc3RKcnhtbEZpbGUiLz4KCTxxdWVyeVN0cmluZz4KCQk8IVtDREFUQVtdXT4KCTwvcXVlcnlTdHJpbmc+Cgk8YmFja2dyb3VuZD4KCQk8YmFuZCBzcGxpdFR5cGU9IlN0cmV0Y2giLz4KCTwvYmFja2dyb3VuZD4KCTx0aXRsZT4KCQk8YmFuZCBoZWlnaHQ9Ijc5IiBzcGxpdFR5cGU9IlN0cmV0Y2giLz4KCTwvdGl0bGU+Cgk8cGFnZUhlYWRlcj4KCQk8YmFuZCBoZWlnaHQ9IjM1IiBzcGxpdFR5cGU9IlN0cmV0Y2giLz4KCTwvcGFnZUhlYWRlcj4KCTxjb2x1bW5IZWFkZXI+CgkJPGJhbmQgaGVpZ2h0PSI2MSIgc3BsaXRUeXBlPSJTdHJldGNoIi8+Cgk8L2NvbHVtbkhlYWRlcj4KCTxkZXRhaWw+CgkJPGJhbmQgaGVpZ2h0PSIxMjUiIHNwbGl0VHlwZT0iU3RyZXRjaCIvPgoJPC9kZXRhaWw+Cgk8Y29sdW1uRm9vdGVyPgoJCTxiYW5kIGhlaWdodD0iNDUiIHNwbGl0VHlwZT0iU3RyZXRjaCIvPgoJPC9jb2x1bW5Gb290ZXI+Cgk8cGFnZUZvb3Rlcj4KCQk8YmFuZCBoZWlnaHQ9IjU0IiBzcGxpdFR5cGU9IlN0cmV0Y2giLz4KCTwvcGFnZUZvb3Rlcj4KCTxzdW1tYXJ5PgoJCTxiYW5kIGhlaW dodD0iNDIiIHNwbGl0VHlwZT0iU3RyZXRjaCIvPgoJPC9zdW1tYXJ5Pgo8L2phc3BlclJlcG9ydD4K
23
</content><type>jrxml</type></file>
0

Questions on proper REST api design specifically on the PUT action when updating a resource

I'm creating a REST interface (aren't we all), and I want to UPDATE a resource.
So, I think to use a PUT.
So, i read this.
My take away is that i PUT to a URL like this
/hc/api/v1/organizer/event/762d36c2-afc5-4c51-84eb-9b5b0ef2990c
with a payload, then a permanent redirect to the URL that it can GET an updated version of the resource.
In this case it happens to be the same URL, different action.
So my questions are:
Is my understanding of updating a resource correct in using a PUT, and is my understanding of the use of the PUT correct.
When a client gets a redirect does it do the same action on the redirected URL as it did on the original URL? If its "depends" is there a standard most clients follow?
I ask the 2nd question, because POSTMAN and my JQuery AJAX calls are choking. JQuery because of net::ERR_TOO_MANY_REDIRECTS. So is it redirecting and trying the PUT again, which it will get another REDIRECT?
curl blows up too but even though it says if it gets a 301 it will switch to a GET, it doesn't really seem to do that when i look at the output (below).
When curl follows a redirect and the request is not a plain GET (for example POST or PUT), it will do the following request with a GET if the HTTP response was 301, 302, or 303. If the response code was any other 3xx code, curl will re-send the following request using the same unmodified method.
CURL OUTPUT (edited for brevity) (also note how it says its going to switch to a GET [incorrectly from a POST], but then it seems to do a PUT anyway):
curl -X PUT -H "Authorization: Basic AUTHZ==" -H "Content-Type: application/json" -H "Cache-Control: no-cache" -H "Postman-Token: e80657f0-a8f5-af77-1d9d-d7bc22ed0b30" -d '{ JSONDATA"}' http://localhost:8080/hc/api/v1/organizer/event/762d36c2-afc5-4c51-84eb-9b5b0ef2990c -v -L
* Hostname was NOT found in DNS cache
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> PUT /hc/api/v1/organizer/event/762d36c2-afc5-4c51-84eb-9b5b0ef2990c HTTP/1.1
> User-Agent: curl/7.37.1
> Host: localhost:8080
> Accept: */*
> Authorization: Basic AUTHZ==
> Content-Type: application/json
> Cache-Control: no-cache
> Postman-Token: e80657f0-a8f5-af77-1d9d-d7bc22ed0b30
> Content-Length: 203
>
* upload completely sent off: 203 out of 203 bytes
< HTTP/1.1 301 Moved Permanently
< Connection: keep-alive
< X-Powered-By: Undertow/1
< Set-Cookie: rememberMe=deleteMe; Path=/hc; Max-Age=0; Expires=Fri, 20-Feb-2015 03:53:28 GMT
< Set-Cookie: JSESSIONID=uwI3_41LAa7vlvapTsrZdw10.macbook-air; path=/hc
* Server WildFly/8 is not blacklisted
< Server: WildFly/8
< Location: /hc/api/v1/organizer/event/762d36c2-afc5-4c51-84eb-9b5b0ef2990c
< Content-Length: 0
< Date: Sat, 21 Feb 2015 03:53:28 GMT
<
* Connection #0 to host localhost left intact
* Issue another request to this URL: 'http://localhost:8080/hc/api/v1/organizer/event/762d36c2-afc5-4c51-84eb-9b5b0ef2990c'
* Switch from POST to GET
* Found bundle for host localhost: 0x7f9e4b415430
* Re-using existing connection! (#0) with host localhost
* Connected to localhost (127.0.0.1) port 8080 (#0)
> PUT /hc/api/v1/organizer/event/762d36c2-afc5-4c51-84eb-9b5b0ef2990c HTTP/1.1
> User-Agent: curl/7.37.1
> Host: localhost:8080
> Accept: */*
> Authorization: Basic dGVzdHVzZXIxOlBhc3N3b3JkMQ==
> Content-Type: application/json
> Cache-Control: no-cache
> Postman-Token: e80657f0-a8f5-af77-1d9d-d7bc22ed0b30
>
< HTTP/1.1 500 Internal Server Error
< Connection: keep-alive
< Set-Cookie: JSESSIONID=fDXxlH2xI-0-DEaC6Dj5EhD9.macbook-air; path=/hc
< Content-Type: text/html; charset=UTF-8
< Content-Length: 8593
< Date: Sat, 21 Feb 2015 03:53:28 GMT
<
...failure ensues... It actually does a PUT
thanks in advance.
I think you're reading too much into the 301 redirect section.
If you want to update a resource using PUT, return:
201: if the resource was created
200: with the updated resource
The 301 in question only applies if there actually is a redirect in question - like, if something can be identified by name, and you need to redirect it to a url that has the id or something. (Maybe you refactor and people are still consuming the old endpoint).
So, do you really need to redirect your PUT requests? Because you should be sending back the updated resource within the same loop using 200, like stated above, instead of "redirecting to GET".
EDIT: Fix some spelling.

Setting up a REST request in to http request window

I want to load test a REST communication and I capture the request using membrane-monitor tool. It is a Mix of some parameters and a Jason String.(Below screen.)
*
> POST /TourStartRequest/ HTTP/1.1 Accept: application/json
> Content-Type: application/json ClientId: 2c8e2becce68f697
> ProtocolVersion: 2 PlatformType: Android UserSessionId:
> 18e2b3cb-1d35-4912-a01d-8f88ceb5bce9 SessionGuid:
> 05fab126-ef81-4365-a541-15b88c0b1df7 SecurityLevel: 3 Content-Length:
> 83 Host: 62.188.35.849:81002 Connection: Keep-Alive User-Agent: PreCom
> Android Framework X-Forwarded-For: 188.888.1.175
> {"TourId":"1884","Position":"0,0","Time":"/Date(1417019685605)/","IsStarted":false}
*
I want to map this in to a http request in Jmeter Name and Value field (image)
http://images.cnitblog.com/blog/489469/201305/23102249-7016f2808bb346fb954b4e8a04625754.png
1) Can some one advice me which parts I have to put as Parameters ?
2) How to setup the Jason part in to this window ?
Thanks
Add a HTTP Header Manager to your request and add the following Header there
Name: Content-Type Value: application/json
Switch to "Body Data" in HTTP Request sampler tab and put your JSON payload there
You might also need to perform some correlation to build proper UserSessionId and SessionGuid
For end-to-end guide for testing web services via JMeter check out Testing SOAP/REST Web Services Using JMeter post.

Creating Sonatype Nexus repository using REST API causes HTTP/1.1 400 Bad Request

In my attempt to create a new Sonatype Nexus hosted repository, using the REST API, I get an "HTTP/1.1 400 Bad Request". I am using a Sonatype Nexus™ 2.10.0-02, running locally.
According to the REST API documentation, available at
http://localhost:8081/nexus/nexus-restlet1x-plugin/default/docs/path__repositories.html
to create a new repository a POST request must look like this:
<?xml version="1.0" encoding="UTF-8"?>
<repository>
<data>
<format>...</format>
<providerRole>...</providerRole>
<exposed>...</exposed>
<id>...</id>
<name>...</name>
<contentResourceURI>...</contentResourceURI>
<repoType>...</repoType>
<provider>...</provider>
</data>
</repository>
So, my XML payload looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<repository>
<data>
<format>maven2</format>
<providerRole>org.sonatype.nexus.proxy.repository.Repository</providerRole>
<exposed>true</exposed>
<id>my-releases</id>
<name>MyReleases</name>
<contentResourceURI>http://localhost:8081/nexus/content/repositories/my-releases</contentResourceURI>
<repoType>hosted</repoType>
<provider>maven2</provider>
</data>
</repository>
and up to here (I hope) is OK.
I use cURL to POST this XML content:
curl -i -H "Accept: application/xml" -H "Content-Type: application/xml" -f -X POST -v -d "#$(pwd)/insert_oss_repository.xml" -u admin:admin123 http://localhost:8081/service/local/repositories
The complete log of this command is this:
* Hostname was NOT found in DNS cache
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8081 (#0)
* Server auth using Basic with user 'admin'
> POST /nexus/service/local/repositories HTTP/1.1
> Authorization: Basic YWRtaW46YWRtaW4xMjM=
> User-Agent: curl/7.35.0
> Host: localhost:8081
> Accept: */*
> Content-Type:application/xml
> Content-Length: 327
>
* upload completely sent off: 327 out of 327 bytes
< HTTP/1.1 400 Bad Request
< Date: Mon, 20 Oct 2014 19:19:21 GMT
* Server Nexus/2.10.0-02 is not blacklisted
< Server: Nexus/2.10.0-02
< X-Frame-Options: SAMEORIGIN
< X-Content-Type-Options: nosniff
< Set-Cookie: rememberMe=deleteMe; Path=/nexus; Max-Age=0; Expires=Sun, 19-Oct-2014 19:19:21 GMT
< Content-Type: application/xml; charset=UTF-8
< Date: Mon, 20 Oct 2014 19:19:21 GMT
* Server Noelios-Restlet-Engine/1.1.6-SONATYPE-5348-V8 is not blacklisted
< Server: Noelios-Restlet-Engine/1.1.6-SONATYPE-5348-V8
< Content-Length: 183
<
<nexus-error>
<errors>
<error>
<id>*</id>
<msg>No enum const class org.sonatype.nexus.proxy.maven.RepositoryPolicy.null</msg>
</error>
</errors>
* Connection #0 to host localhost left intact
</nexus-error>
First of all, I would read your comment regarding the XML payload of my POST request. Second, if they took the time to create a sort of documentation, why don't they provide also a working example? Third, if they made this REST API available why don't they respond with a human readable answer?
It looks like there may be a bug in the documentation, you also need to provide the "repoPolicy" element. Here's an example payload:
<repository>
<data>
<id>my-releases-xml</id>
<name>MyReleasesXml</name>
<exposed>true</exposed>
<repoType>hosted</repoType>
<repoPolicy>RELEASE</repoPolicy>
<providerRole>org.sonatype.nexus.proxy.repository.Repository</providerRole>
<provider>maven2</provider>
<format>maven2</format>
</data>
</repository>
In general the best approach to use with Nexus and REST is to use the JSON payloads, these are easily discoverable because the UI calls through the REST layer and sends JSON. See here for more information:
http://blog.sonatype.com/2012/07/learning-the-nexus-rest-api-read-the-docs-or-fire-up-a-browser/

GWT with XS. No POST, Just OPTIONS. Load cancelled

I have a problem with a GWT Application which is rather simple but using the Cross-Site-Scripting mechanism of gwt in conjunction with the GWT-RPC (Async-Interface).
The Problem is, that the Browser is sending only the OPTIONS command to the RPC-Backend but not POST. Therefore the data never reach the server. This is the capture of the client-server-communication:
From the GWT-Client
OPTIONS /contact/contact/dispatchService HTTP/1.1
Host: svr3.dmz.mycompany.com:8380
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://www.mycompany.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.43 Safari/537.31
Access-Control-Request-Headers: x-gwt-module-base, x-gwt-permutation, origin, content-type
Accept: */*
Referer: http://www.mycompany.com/contact.html
Accept-Encoding: gzip,deflate,sdch
Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
From the Server
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Allow: POST, TRACE, OPTIONS
Content-Length: 0
Date: Tue, 23 Apr 2013 07:13:06 GMT
But no data are beeing sent via POST.
In my module.gwt.xml I have the following line for using the xs-Linker:
<inherits name="com.google.gwt.core.Core" />
<add-linker name="xs" />
I have also tried xsiframe unfortunately with the same result.
When I directly invoke GWT-Application from the same server without cross-site-scripting everything works fine:
POST /contact/contact/dispatchService HTTP/1.1
Host: svr3.dmz.mycompany.com:8380
Connection: keep-alive
Content-Length: 273
X-GWT-Module-Base: http://svr3.dmz.mycompany.com:8380/contact/contact/
X-GWT-Permutation: 5BE2BF501B916E292DCA5282B8B896AE
Origin: http://svr3.dmz.mycompany.com:8380
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.43 Safari/537.31
Content-Type: text/x-gwt-rpc; charset=UTF-8
Accept: */*
Referer: http://svr3.dmz.mycompany.com:8380/contact/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: __utma=179080955.1318578617.1360141977.1366109245.1366612633.29; __utmc=179080955; __utmz=179080955.1366104741.27.5.utmcsr=www.mycompany.com|utmccn=(referral)|utmcmd=referral|utmcct=/index.html
From the Server
7|0|9|http://svr3.dmz.mycompany.com:8380/contact/contact/|C4C9C36F0F0B498822C3C822496B3301|com.mycompany.contact.client.DispatchService|dispatch|com.mycompany.contact.client.DispatchService$Message/2078545930||lastname#mycompany.com|Direct via
svr3.|givenname|1|2|3|4|1|5|5|6|7|8|9|6|HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Disposition: attachment
Content-Type: application/json;charset=utf-8
Content-Length: 12
Date: Tue, 23 Apr 2013 07:15:44 GMT
//OK[[],0,7]
The Webapplication is running on a Tomcat6 behind an Apache2 connected via mod_jk.
Any idea how I can solve this issue?
This is known as a preflight request and is made by the browser when you do a cross-origin request (with a few exceptions for legacy reasons) to first check with the server whether the webapp is allowed to POST.
You have to handle the OPTIONS request on the server-side and respond with the appropriate Access-Control-Allow-Origin header (and possibly Access-Control-Max-Age, Access-Control-Allow-Headers, etc.)
See http://www.w3.org/TR/cors/#cross-origin-request-with-preflight-0
Note that this will (obviously) only work in browsers that support CORS, which rules out a lot of people (IE only supports CORS starting with IE10, unfortunately not yet mainstream): http://caniuse.com/cors
See also https://developers.google.com/web-toolkit/doc/latest/FAQ_Server#SOP,_GWT,_and_XMLHTTPRequest_Calls
Using the xs linker (BTW, you should prefer the xsiframe linker nowadays, the doc is a little bit out-of-date) only fixes the loading of the script, it doesn't cover the requests to a server. You can use a proxy (servlet, script, server configuration, whatever) on the same origin as the HTML host page that routes the requests to the server where the RPC services are actually deployed; see https://developers.google.com/web-toolkit/doc/latest/DevGuideServerCommunication#DevGuideRPCDeployment
Based on the Information from Thomas Broyer I managed to resolve the issue by adding a CORS-Support-Filter:
First I added this to my pom.xml:
<dependency>
<groupId>com.thetransactioncompany</groupId>
<artifactId>cors-filter</artifactId>
<version>1.3.2</version>
</dependency>
Then added this to my web.xml:
<filter>
<!-- The CORS filter with parameters -->
<filter-name>CORS</filter-name>
<filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
<!-- Note: All parameters are options, if ommitted CORS Filter
will fall back to the respective default values.
-->
<init-param>
<param-name>cors.allowGenericHttpRequests</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>cors.allowOrigin</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>cors.allowSubdomains</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>cors.supportedMethods</param-name>
<param-value>GET, HEAD, POST, OPTIONS</param-value>
</init-param>
<init-param>
<param-name>cors.supportedHeaders</param-name>
<param-value>Content-Type, X-Requested-With, x-gwt-module-base, x-gwt-permutation, origin</param-value>
</init-param>
<init-param>
<param-name>cors.exposedHeaders</param-name>
<param-value>X-Test-1, X-Test-2</param-value>
</init-param>
<init-param>
<param-name>cors.supportsCredentials</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>cors.maxAge</param-name>
<param-value>3600</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CORS</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Please see here for more information about the filter.
CAUTION: Further more I have tested this solution with IE 8 and unfortunately it is, as expected, NOT working with IE 8. I haven't tested it with more recent versions but since IE 8 is still in the wild I have to include the rpc-servlet into the same origin website via mod_jk.