Java; HttpURLConnection; Query items duplicated as `paramName=value, value`. `paramName=value` expected - java

I'm having a very strange issue.
My company uses a centralized user registration web-service for our various properties. We generally send a request to the web service via HttpURLConnection with request-method GET, setting parameters via qs. This has worked fine in the past.
For another property with which we've recently acquired and plugged into our registration web service, HttpURLConnection seems to be duplicating parameters when sent along. The expected value of a parameter is paramName=value, but we're receiving paramName=value, value instead. Here's a representation of what it looks like in our logs:
Note: Removing information specific to my employer and our systems.
01-26 15:21:54 [TP-Processor17] INFO com].[/] - parameter=userName=nameValue65, nameValue65
01-26 15:21:54 [TP-Processor17] INFO com].[/] - parameter=policyAccepted=true, true
This, of course, caused the end-point validation to error and disable user-registration.
Here's a representation of the code used to create the connection:
URL url = new URL("http://account-ws.domain.tld/register.action?responseType=json&userName=nameValue65&age=24&country=US&password1=Passw3rt&emailAddress=name#domain.tld&tosAccepted=true&policyAccepted=true");
HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
urlc.setRequestMethod("GET");
urlc.setDoOutput(true);
urlc.setAllowUserInteraction(false);
PrintStream ps = new PrintStream(urlc.getOutputStream());
ps.print(restEndPoint);
ps.close();
Perhaps(?) useful info:
The registration form submits to itself using POST, at which point we validate using Struts forms, and send the request to the web service using the values returned by the Struts form validation class. (These values are checked for accuracy once more before sending.)
Wireshark and log4j debug messages indicate that the URL sent to the web service is correct / what we would expect, with single values for each parameter.
The initiating form's post fields are named identically to the query keys sent with the web service request.
Please ask for more info if you find what's here to be insufficient.
Thank you in advance! :)

When you use GET method, the query string is added to URL string. The GET method is a default Http request method for HttpURLConnection. You do not need to explicitly set the request method to GET.
A GET method is used to obtain the content of the requested URL. You should not write to output stream of the GET connection.
If you want to use POST method, you can set it via setRequestMethod("POST") but I am not sure if you need to have setDoOutput(true) as well. However, the setDoOutput(true) will, by default, set request method to POST so you might as well ignore the setRequestMethod("POST"). If you want to write to output stream using POST, here is my previous answer of how to do it using HttpURLConnection.
It should be noted that when you do a POST (or PUT), the URL should not contain query part. Since you have a mixture of GET and POST, this might be the cause of your problem but I am not certain.
One possible case where you have to use both setRequestMethod and setDoOutput(true) is when you want to do a Http PUT.

Related

Why does my POST to Sagepay returns an Error 400?

I am trying to integrate my application with Sagepay, using the Server Integration Protocol. I have written my code in JAVA and currently I am at the point where I'm sending a POST to Sagepay to be redirected to their payment page. However, I get a blank screen which is a result of an Error 400 (Bad Request).
In their documentation, they specifically state that:
The data should be sent as URL Encoded Name=Value pairs separated with & characters and sent to the Sage Pay Server URL with a Service name set to the message
type in question.
The URL that I have constructed is this:
https://test.sagepay.com/gateway/service/vspserver-register.vsp&VPSProtocol=3.00&TxType=PAYMENT&Vendor=foovendor&VendorTxCode=foovendor-1459865650735-78597&Amount=10&Currency=GBP&Description=This+is+the+description&NotificationURL=http%3A%2F%2Fwww.google.com&BillingSurname=foosurname&BillingFirstnames=fooname&BillingAddress1=fooaddress&BillingCity=foocity&BillingPostCode=foopc&BillingCountry=UK&DeliverySurname=fooname&DeliveryFirstnames=foosurname&DeliveryAddress1=fooaddr&DeliveryCity=foocity&DeliveryPostCode=foopc&DeliveryCountry=UK&CustomerEMail=foo%40foo.com
What am I missing?
Thanks for your help!
Your url doesn't setup the query string properly.
Ithink that
register.vsp&VPSProtocol
should be
register.vsp?VPSProtocol
I.E. Question mark instead of ampersand.
Also, you said a post was required, but pasting that url in a browser will send a GET request, won't it ?

URL not changing on page redirection in Jersey and MongoDB

My scenario is like this:
I'm building a website where I'm posting an ad regarding a topic. So, after the form filling of ad, the request goes to a REST service class as:
http://localhost:8080/cloudproject/postadvaction?title=tution&tag=tution&description=tution+%401000+%2F+month&category=TUTOR&location=indore
Here, the details of ad go in the database which is MongoDB. After all of this is done I'm redirecting to the profile page of user using Viewable model of jersey, where he can see all the ads posted by him. It is done as:
return new Viewable("/profile.jsp");
After this the response is redirected to profile page of the user.
But the problem is that, on redirecting the response to simply profile.jsp, the URL in the address bar has not changed to http://localhost:8080/profile.jsp, instead, it has remained the same as mentioned above. So, when user refreshes the page, the request of same ad post triggers and the whole process is followed again. Since, database is MongoDB, same ad is stored twice in it and same is displayed on the profile page of user with 2 identical ads.
So, how can I redirect to profile page without having the address of servlet in address bar?
Update: The question is related to PRG technique & Duplicate Form Submissions and not to just redirection.
See Post/Redirect/Get
When a web form is submitted to a server through an HTTP POST request, a web user that attempts to refresh the server response in certain user agents can cause the contents of the original HTTP POST request to be resubmitted, possibly causing undesired results, such as a duplicate web purchase.
To avoid this problem, many web developers use the PRG pattern[1] — instead of returning a web page directly, the POST operation returns a redirection command. The HTTP 1.1 specification introduced the HTTP 303 ("See other") response code to ensure that in this situation, the web user's browser can safely refresh the server response without causing the initial HTTP POST request to be resubmitted. However most common commercial applications in use today (new and old alike) still continue to issue HTTP 302 ("Found") responses in these situations.
With Jersey you can use
Response.seeOther(URI) - Create a new ResponseBuilder for a redirection. Used in the redirect-after-POST (aka POST/redirect/GET) pattern.
You just need to change your method signature to return a Response and return the built Response
return Response.seeOther(URI.create(...)).build();
Also stated about the URI parameter
the redirection URI. If a relative URI is supplied it will be converted into an absolute URI by resolving it relative to the base URI of the application (see UriInfo.getBaseUri()).

How does cookies work, when calling cookie-setting REST services from java VM?

I'm in the process of learning how to use HP Quality Center's REST api to query and manipulate data. Unlike REST standard, this API is not completely stateless. It uses cookies to store authentication sessions.
I've tried to implement a very simple test, using the Jersey Client library. I can successfully authenticate my user, by sending my credentials. The API reference claims that this will set a cookie, and I am good to go with further calling the REST api. However, a simple "is-authenticated" call returns a 401, Authentication failed.
I have a feeling that the cookie writing or reading is not working properly, as everything else seems to work as it should. But I haven't been able to find out if or how cookies are set and read, when no browser is involved. So How does cookies work, when calling cookie-setting REST services from java VM? Does it work at all? Where are they stored?
I am using Eclipse Kepler as my IDE, if that matters at all, and a 32-bit java 1.6 JDK and JRE.
Code, and response strings below:
1. Logging in:
Client client = ClientBuilder.newClient();
Response response = client
.target("http://[host]:[port]").path("qcbin/authentication-
point/alm-authenticate")
.request().post(Entity.entity("<alm-authentication>
<user>username</user>
<password>secret</password></alm-authentication>",
MediaType.TEXT_XML_TYPE));
System.out.println(response.toString());
Output:
InboundJaxrsResponse{ClientResponse{method=POST,
uri=http://[host]:[port]/qcbin/authentication-point/alm-authenticate,
status=200, reason=OK}}
API Return description:
One of:
HTTP code 200 and sets the LWSSO cookie (LWSSO_COOKIE_KEY).
HTTP code 401 for non-authenticated request. Sends header
WWW-Authenticate: ALMAUTH
2. Verifying Logged in:
response = client.target("http://[host]:[port]")
.path("qcbin/rest/is-authenticated")
.request().get();
System.out.println(response.toString());
Output:
InboundJaxrsResponse{ClientResponse{method=GET,
uri=http://[host]:[port]/rest/is-authenticated, status=401,
reason=Authentication failed. Browser based integrations - to login append
'?login-form-required=y to the url you tried to access.}}
PS: adding the ?login-form-required=y to the URL, will bring up a log-in window when called in a browser, but not here. Appending the line to the URL actually still gives the same error message, and suggestion to append it again. Also, when called in a browser, the is-authenticated returns a 200, success, even without the login-form.
When you log in, you're getting a cookie which is a name plus a value.
The REST server expects you to pass this in the request header with every request you make.
Look into the object which you get for client.request(); there should be a way to specify additional headers to send to the server. The header name must be Cookie and the header value must be name=value.
So if the server responds with a cookie called sessionID with the value 1234, then you need something like:
client.request().header("Cookie", "sessionID=1234")
Related:
http://en.wikipedia.org/wiki/HTTP_cookie

How to get HTTP request string from HttpURLConnection instance

I have HttpURLConnection instance created from URL and also I set query parameters and called some setters on this HttpURLConnection instance. I use this instance to get response from web service.
Is there some way to get the HTTP request string that will be sent over the network when using the given HttpURLConnection instance ? (just for debugging purposes). Can we do this programatically using HttpURLConnection or if it's not possible how can I monitor the outgoing HTTP traffic ?
The reason I need this that in some cases it can be easier to detect what is wrong with your configuration of HttpURLConnection by looking directly at the request that is defined by this instance than trying to figure out what is wrong with particular configuration of HttpURLConnection by checking what setters was called.
Thank you for any suggestion.
You can monitor your http Traffic by using Fiddler
Here is the download link

cookie tutorial problem

http://www.hccp.org/java-net-cookie-how-to.html
According to this link I was trying to create cookie and send cookie to enter in a cookie site. But it is not working. Is there is any problem in that. I have some confusion on the method setRequestProperty of URLConnection. I don't understand what are they trying to send by passing "Cookie"? Is it only a string or name or value??
urlConn.setRequestProperty("Cookie", myCookie);
"Cookie" in this case is a way to tell the setRequestProperty method that the argument (which is really just a String) should be treated as a cookie.
setRequestProperty may be more useful for many kinds of properties, but addRequestProperty would be more useful for cookies, because you can have multiple cookies per request. The properties are specified in RFC 2068 -- read especially section 14.

Categories

Resources