1

I'm doing a script to update several queries that we use in our project everytime we deploy a sprint.

I'm trying to replicate the same request that I'm testing on Fiddler, that it is working, in the following way:

System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
String host = 'redmine.our-domain.com';
String url = 'http://redmine.our-domain.com/queries/4088';
String REDMINE_SESSION_COOKIE = "_redmine_session=BAh7DkkiDHVzZXJfaWQGOgZFRmkvSSIKY3RpbWUGOwBGbCsHmouFWkkiCmF0aW1lBjsARmwrByk211tJIg9zZXNzaW9uX2lkBjsARkkiJTMzZWJkNmI1MzA4MzZkNmMxNGYwNjY1OWQxMDZjZmU3BjsAVEkiEF9jc3JmX3Rva2VuBjsARkkiMVB3bDlCb0F5NFFCbTd3dmdGWGx0VjdEL05WYjhVRGExdFluQmNMbnFZTHM9BjsARkkiCnF1ZXJ5BjsARnsHOgdpZGkC%2BA86D3Byb2plY3RfaWRpAssBSSIWaXNzdWVzX2luZGV4X3NvcnQGOwBGSSIMaWQ6ZGVzYwY7AEZJIg1wZXJfcGFnZQY7AEZpaUkiFWZqbGVzX2luWGV4X3NvcnQGOwBGSSINZm2sZW5hbWUGOwBG--5c961485290b3c98f38de934b939d25cc01e092f"
String data = "_method=put&authenticity_token=Pwl9BoAy4QBm7wvgFXlsV7D%2FNVb8UDa2tYnBcLnqYLs%3D&query%5Bname%5D=Current+sprint+1.75-test+API+0+0+1&query%5Bvisibility%5D=2query%5Bgroup_by%5D=category&f%5B%5D=status_id&op%5Bstatus_id%5D=o&f%5B%5D6=fixed_version_id&v%5Bfixed_version_id%5D%5B%5D=6030&c%5B%5D=tracker&c%5B%5D=status&c%5B%5D=priority&c%5B%5D=subject&c%5B%5D=assigned_to&c%5B%5D=fixed_version&c%5B%5D=start_date&c%5B%5D=due_date&c%5B%5D=estimated_hours&c%5B%5D=done_ratio&c%5B%5D=parent";
byte[] body = data.getBytes("UTF-8");

HttpURLConnection http = (HttpURLConnection) new URL(url).openConnection();
http.setRequestMethod('POST');
http.setRequestProperty('Cookie', REDMINE_SESSION_COOKIE);
http.setRequestProperty('Content-Type', 'application/x-www-form-urlencoded');
http.setRequestProperty('Host', host);
http.setRequestProperty('Content-Length', "${body.length}");
http.setDoOutput(true);
http.getOutputStream().write(body);

Both, data's authenticity_token and session cookie are fakes, but I'm copy-pasting the Fiddler one. I'm adding the Host and Content-Length because Fiddler always add them.

Fiddler returns a 302 status that it is right, because Redmine redirects the page. With the code above I receive a 422 status (Unprocessable Entity) with this message in the body: Invalid form authenticity token

I've spent 3 days trying to figure out what I'm doing wrong to clone the request. Any clue?

Agorreca
  • 684
  • 16
  • 31

1 Answers1

1

You should rather try to use Redmine's API to acheive your goal, instead of trying to send html form data to controller.

Redmine login form creates also invisible form data fields, which you can see while inspecting with your browser (F12 usually).

One such, hidden field is authenticity token, and it's generated new, every time form is rendered.

enter image description here

Fiddler probably works, because it's performing basic authentication, as described here: http://www.redmine.org/projects/redmine/wiki/Rest_api#Authentication

So in your code, you must remove part of code trying to mimic form data, and use basic authentication instead, like this:

System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
String host = 'redmine.our-domain.com';
String url = 'http://redmine.our-domain.com/queries/4088';
String auth = Base64.getEncoder().encodeToString((username+":"+password).getBytes(StandardCharsets.UTF_8));  //Java 8 - not sure for 7

HttpURLConnection http = (HttpURLConnection) new URL(url).openConnection();
http.setRequestProperty("Authorization", "Basic "+auth);    
http.setRequestMethod('POST');
http.setRequestProperty('Cookie', REDMINE_SESSION_COOKIE);
http.setRequestProperty('Content-Type', 'application/x-www-form-urlencoded');
http.setRequestProperty('Host', host);
http.setRequestProperty('Content-Length', "${body.length}");
http.setDoOutput(true);
http.getOutputStream().write(body);
Aleksandar Pavić
  • 3,143
  • 1
  • 34
  • 36
  • Great! I'm going try that way. I'm using the Redmine API for all the other things that I need to do, but there is no CRUD for Redmine Queries (or other things that I need such as add a version wiki page) – Agorreca Nov 05 '18 at 12:59