Redirecting REST request using Servlets - java

Here is my issue. I want to be able to receive a REST request at an url like
localhost:8080/API to some other address like example.app/API, however I want to add some extra fields to the existing REST request like uuid and user_id which are generated by some Java class or extracted from another Rest service.
So for example I get following request:
GET /API/myfunc HTTP/1.1
Host: www.example.com
And resend a request
GET /example.app/API?uuid=1231231231231&user_id=3 HTTP/1.1
Host: www.example.com
Now this is simple if its a GET request, but what if it's a POST request?
Is there a already made solution to this problem?

UrlRewriteFilter [1] might help you here.
Such a filter allows you to define advanced redirecting rules and gives you access to the request and response objects (e.g. you can use request.addParameter(...))
Check the <run> element and <class-rule> element sections from [2].
[1] https://stackoverflow.com/questions/tagged/tuckey-urlrewrite-filter
[2] http://cdn.rawgit.com/paultuckey/urlrewritefilter/master/src/doc/manual/4.0/index.html

Related

Sending Query Parameters encoded in a URI on a Post which also has json

I have a server that handles a POST request with JSON. It also looks and decodes query parameters from the URI. My Java Client currently uses HTTPPost to send across the Json with ContentType application/json.
I wonder whehther URLEncodeUtil method format would be able to accomplish this. Except the documentation mentions
suitable for use as an application/x-www-form-urlencoded list of
parameters in an HTTP PUT or HTTP POST.
So my question is
1. Would this work with ContenType set to application/json.
2. Is there another way to accomplish what the Server requires, ie: have JSON as well as Query parameters encoded in the URI.
There are two official methods of posting form data via the (HTML spec). The pertinent value is application/x-www-form-urlencoded which adds a ? along with the name/value pairs encoded in the URL. If the form method is POST then it will be the first line after the HTTP POST statement.
Everything we do with HTTP in REST web services is valid HTTP, but not for HTML. So the application/json can have a combination of the application/x-www-form-urlencoded style parameters and the JSON payload.
The HTTP request will look something like this:
POST /blog/posts?myparam=Something%20Good&token=donotdothis
Accept: application/json
Content-Type: application/json
Content-Length: 57
{"title":"Hello World!","body":"This is my first post!"}
Also spelled out here: http://www.jsonrpc.org/historical/json-rpc-over-http.html
It's the ? that marks the beginning of extra parameters. So while that is technically legal, it does beg the question why everything you need to post can't be part of your JSON. The downside of this approach is that the query parameters are all part of your HTTP logs and is very visible. You definitely should not use this approach with passwords or any other personally identifiable information. Depending on privacy laws in your country, you want to minimize unnecessary records to make compliance much easier.

Postman multipart/form-data error: Missing start boundary

I'm trying to hit my server's endpoint with a multipart/form-data request sent from Postman. I'm getting a 400 Bad Request and the cause is:
org.jvnet.mimepull.MIMEParsingException: Missing start boundary.
How can I set the start boundary and how do I know what it should be?
https://github.com/postmanlabs/postman-app-support/issues/191 Following that thread here seems that setting the request header to Content-Type multipart/form-data I'm overriding the value set by Postman.
There is no need to add a content-type header manually. You are
overriding the value set by Postman. Just select form-data in POST
request and send your request to see if it works.
Removing the header allowed me to hit my endpoint.
Overriding POSTMAN header values is the issue as mentioned by Anton above. Here is how your headers and request body should look like for standalone POSTMAN client:
As a work around try this:
spring:
jersey:
application-path: /rest # Path that serves as the base URI for the application. Overrides the value of "#ApplicationPath" if specified.
filter.order: 0 # Jersey filter chain order.
type: servlet # Can be either "servlet" or "filter".
init.*:
type servlet worked fine, where as filter is throwing the Start Boundary error.

Cross Origin Resource sharing issue even when all the CORS headers are present

even though i have appended my service response with following provided CORS Headers :
resp.setContentType("application/json");
resp.addHeader("Access-Control-Allow-Origin", "*");
resp.addHeader("Access-Control-Allow-Credentials", "true");
resp.addHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS");
resp.addHeader("Access-Control-Allow-Headers", "Origin,accept,content-type");
resp.flushBuffer();
i am still getting below error in the console while trying to access some of the POST web methods in the service through my AngularJS frontend.
XMLHttpRequest cannot load http://192.***.*.***:8080/abc/def/search/vehicleManufacturer. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://192.***.*.***:8085' is therefore not allowed access.
However within the same class, some POST methods without any payloads are responding perfectly. Any suggestions ?
EDIT--------->
Below is my AngularJS client screen code for calling the web method:-
getVehicleModel : function(searchData,$scope){
$http({
method:'POST',
url:'http://192.169.*.***:8085/abc/def/search/vehicleModel',
dataType:'jsonp',
data:searchData
}).
success(function(data){
console.log("vehicle model")
$scope.vehicleModel = data.Response;
});
},
I think the problem here is Preflighted Requests in CORS.
From the Mozilla docs,
Unlike simple requests (discussed above), "preflighted" requests first
send an HTTP request by the OPTIONS method to the resource on the
other domain, in order to determine whether the actual request is safe
to send. Cross-site requests are preflighted like this since they may
have implications to user data. In particular, a request is
preflighted if:
It uses methods other than GET, HEAD or POST. Also, if POST is used to send request data with a Content-Type other than
application/x-www-form-urlencoded,
multipart/form-data
text/plain
e.g. if the POST request sends an XML payload to the server using application/xml or text/xml, then the request is preflighted.
It sets custom headers in the request (e.g. the request uses a header such as X-PINGOTHER)
As explained above, even though you're making a simple POST request, the Content-Type in your request is application/json which is different from the 3 types mentioned above, so it's considered as a Preflight request and an OPTIONS request is fired before your actual POST request.
You can solve this by implementing doOptions in your servlet, just add the headers there and it will work :)
The preflight (OPTIONS) is occurring due to the fact that you are sending a cross-origin ajax request AND specifying an Authorization header with this GET request.
Also (this is not causing an issue) I would suggest removing the contentType option. This doesn't make sense in the context of a GET request. A GET request should not have any content. All data should be included in the query string or, possibly, headers.
The Authorization header will not be sent with the OPTIONS. You must acknowledge it server-side, and then the browser will send the underlying GET. Read more about CORS at https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS .

Can I rewrite a URL, adding query params and preserve the form data?

I have a rule like:
RewriteCond %{HTTP_HOST}:%{QUERY_STRING} ^(\w+)\.t(.*)\.(\w+)?\.sprawk\.com:(.*)$
RewriteRule ^(.*) /api/translateHtmlPublic?tl=%1&su=%2&p=$1&q=%4 [B,PT,L]
which works great for GET requests.
However, for POST requests, the q parameter is null (which I expected) but inside my Java servlet, both the HttpServletRequest.getReader() and HttpServletRequest.getInputStream() give no data.
Using Firefox Live headers, I see that I am sending:
POST /uid/contactSend.cfm HTTP/1.1
Host: fr.t51940.local.sprawk.com
Connection: keep-alive
Referer: http://fr.t51940.local.sprawk.com/uid/contact.cfm?country=137
Cache-Control: max-age=0
Content-Type: application/x-www-form-urlencoded
Content-Length: 146
userName=Nic&queryCountry=Libya&queryCode=137&userEmail=n.cottrell%40idea.int&Comment=Just+testing&captcha=Quotas&Submit=--+Envoyer+Commentaire+--
I know that the servlet is receiving it as a POST since the doPost method is triggered. I understand that Apache 2.x should automatically preserve POST data during a simple rewrite, but maybe the addition of parameters is wiping the content data?
Update: I just realised (by dumping out all parameters) that the userName, queryCountry, queryCode parameters are getting correct values via the request.getParameter(String) method. The problem is that I need to be able to separate the original form parameter names from the ones I introduction in the RewriteRule.
The parameters of a POST are in the body, not the header. You can rewrite the URL as much as you like without affecting them.
The body of a POST request whose content type is application/x-www-form-urlencoded consists only of parameters that are retrieved via request.getParameter(). Reading the body via request.getInputStream() and request.getReader() will deliver nothing. (Servlet Specification 3, #3.1.1)
According to Servlet Specifcation #3, the parameters you add to the URL should be retrievable via getParameter().
There is no way to distinguish POST parameters in the body from URL parameters in the header. There is probably therefore something wrong with your solution, or your problem.

Setting up a Restful POST request using xml

I'm working on setting up a RESTful request for the application I'm working on and I wanted to use xml as the request in the uri instead of allowing the client to supply the parameters in the URI itself.
I'm looking to have the URI like so: someurl/service/request
instead of: someurl/service/request?id={id}&name={name}
I have been searching the web to see what the convention should be when creating the POST request. Can anyone kind of help point me in the right direction on how I should set up this POST request allowing the client to use xml?
Not sure if it is relevant but I'm setting up the server side code in JAVA using the SPRING 3.0 framework. Please let me know if I need to supply more details.
Thanks for your help!!
You can put parameters into the body of the request. They are the same format as appending them to the URL. Eg:
POST /path/script.cgi HTTP/1.0
User-Agent: HTTPTool/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 32
home=Cosby&favorite+flavor=flies
You can do that in prototype pretty easily with:
new Ajax.Request('someurl/service', {
method: 'post',
postBody: 'home=Cosby&favorite+flavor=flies',
encoding: 'UTF-8'});
To add your xml file, just append it to your postBody with some sort of delimiter so your cgi knows where parameters end and where xml begins.
I think that's what you were looking for, hope it helps.
You can pass whatever you want in your POST body. So if you want to use XML, you can use XML. Example:
POST /car
Content-Type: text/xml
<car>
<date>10-10-2007<date>
<type>Corvette</type>
</car>
HTTP/1.1 201 CREATED
I think all the REST API frameworks let you easily specify XML in the client request and server response. See Restlet's quick start for an example.

Categories

Resources