REST request fails with URI encoded path parameter - angularjs

I use AngularJS (client) and a REST interface in my project (server, javax.ws.rs.*). I'm passing data in a path parameter. It may contain special characters, so I call encodeURIComponent() to encode the arguments prior to sending a request.
Client-side:
$http.put('/foo/data/' + encodeURIComponent(data) + '/bar');
The controller will process the request and send a response.
Server-side:
#PUT
#Path("/data/{data}/bar")
public ResultObject handleFooRequest(#PathParam("data") String data) throws Exception {
return handleRequest(data);
}
This works fine on localhost, however, the request fails when I do a request on our production server (Error 400: Bad request). What am I doing wrong and why is it working on one server and fails on the other? In general, is my approach correct? Do I need to tell RESTEasy to decode the arguments? To my understanding (I read the documentation), it does that on default.

Related

React Fetch POST removes characters with header Content-type = application/x-www-form-urlencoded

I am using react with fetch for sending an image to the server.
I have tried using Content-type = application/x-www-form-urlencoded to pass my data to the server but it replaces special characters with spaces (i.e. + becomes a space).
I have switched the header to be Content-type: multipart/form-data but that throws the error
Failed to load resource: the server responded with a status of 500
(Internal Server Error).
I have added a boundary to the Content-type as boundary=abcdefg.
That did not change anything and I am not sure what my boundary would be.
Finding a clear answer with straight forward examples about boundaries have been impossible to get.
The data that I am sending is a large string.
If needed I can post that as well.
Here is a sample of the code that is causing the problem:
SaveTest4(data: string) {
const options = {
method: 'post',
headers: {
"Content-type": "multipart/form-data; boundary=abcdefg"
},
body: 'data=' + data
}
fetch('api/DataPoint/AddTest4', options);
}
Based on part of your analysis, it sounds like you're trying to send base64-encoded data. A content type of application/x-www-form-urlencoded will result in the server performing URL decoding, which will replace each instance of + in the content body with a space character.
When you used a content type of multipart/form-data, the server fails with status 500 because the data you provided wasn't a properly constructed MIME document.
My psychic debugging powers tell me that you're trying to post a base64-encoded file to a ASP.NET MVC WebAPI endpoint that's expecting a JSON document. You might have a controller method that looks like this:
[HttpPost("api/DataPoint/AddTest4")]
public void AddTest4([FromBody] string data) { ... }
If you send with a content type of application/json, this endpoint will expect a document that looks like this:
"{base64-encoded-data}"
Note that there are quotes around the data, because a quoted string is a proper JSON document. You'd just use JSON.stringify() to create the quoted string in this case, which would escape any quotes within the string correctly.
If you send with application/x-www-form-urlencoded, you'd need to send a document that looks like this:
data={base64-encoded-data}
But, as you note, you'd have to make sure you escape all of the special characters in the payload; you can do this using window.encodeURIComponent(), which would translate each "+" to "%2B", among other things.
If the files that you're uploading to this endpoint are large, it would be significantly better to use an instance of FormData. This would allow the browser to stream the file to the server in chunks instead of reading it into memory and base64-encoding it in JavaScript.

How to use / in parameter during rest webservice call from angularjs?

I need to send a value like app/role as parameter through rest webservice url from angularjs
In controller.js
var roleName = 'app/role';
checkRole.check({'roleName': roleName}, function(data){}
In model.js
popModel.factory('checkRole', function ($resource) {
return $resource('./rest/checkRole/:roleName',{roleName:'#roleName'},{
check: {'method':'GET'},
});
});
The rest webservice call in java
#GET
#Path("/checkRole/{roleName}")
#Produces(MediaType.APPLICATION_JSON)
public Response checkRole(#Context HttpServletRequest request, #PathParam("roleName") String roleName);
When i pass it i am getting browser console error as
Bad request response from the server.
For normal parameter values like 'Test', 'Solution', 'Application' etc. If i use with / as a parameter no process is done and i am getting error.
/ is reserved character for GET request. So, you can't use them directly. If you use them, you would get Bad Request Error.
One of the solution can be to encode the URL on client side and decode it on server.
Reference:
Characters allowed in GET parameter
How to handle special characters in url as parameter values?

Web api is giving error on passing * as the input value to the api method parameter

I am using asp.net mvc web api and i have this method
[HttpGet]
public LoginResult AuthenticateOnlineBookingUser(String userName,String password)
{
//My Code
}
The problem is that when i pass (*) as input value to the parameter (password)
i receieve this error but on other inputs it is working perfectly
A potentialy dangerous Request.Path.value was detected from client(*)
Thanks in advance
Note:My client side is written in angular js
i tried this solution as well Getting "A potentially dangerous Request.Path value was detected from the client (&)" but it is not working for me
You need to set the options for invalid characters. You can do this in your web.config as shown here.
Use url encoder to encode the request before sending it to server.
Finally solved my problem by changing my GET request to POST request The problem was with query string in Order to solve it with GET Request i have to make some changes to my query string in order to make it work but

CXF wsdl2java, GZip compression, and stub reutilization

I´m using CXF to consume a WebService and, as the responses are quite large, I´m requesting with a gzip "Accept-Encoding" and using GZIPInInterceptor to handle the gziped response. Also my WSDL is very large (360kb) and it takes a long time(+10 seconds) to create the stub, because it has to read and parse the WSDL, so I´m creating the stub once and reusing it.
The problem is, whenever I try to use two different methods the second request gives me an error saying it is expecting the previous request.
To illustrate my problem I created a simple example with this public WebService:
http://www.webservicex.net/BibleWebservice.asmx?WSDL
Without the GZip compression it works fine:
BibleWebserviceSoap bibleService = new BibleWebservice().getBibleWebserviceSoap();
String title = bibleService.getBookTitles();
response.getWriter().write(title);
String johnResponse = bibleService.getBibleWordsbyKeyWord("John");
response.getWriter().write(johnResponse);
I´m able to receive both responses.
Enabling Gzip compression:
BibleWebserviceSoap bibleService = new BibleWebservice().getBibleWebserviceSoap();
//GZIP compression on bibleService
Client client = ClientProxy.getClient(bibleService);
client.getInInterceptors().add(new GZIPInInterceptor());
client.getInFaultInterceptors().add(new GZIPInInterceptor());
// Creating HTTP headers
Map<String, List<String>> headers = new HashMap<String, List<String>>();
headers.put("Accept-Encoding", Arrays.asList("gzip"));
// Add HTTP headers to the web service request
client.getRequestContext().put(Message.PROTOCOL_HEADERS, headers);
String title = bibleService.getBookTitles();
response.getWriter().write(title);
String johnResponse = bibleService.getBibleWordsbyKeyWord("John");
response.getWriter().write(johnResponse);
When I try to receive the second response I´m getting this exception:
org.apache.cxf.interceptor.Fault: Unexpected wrapper element {http://www.webserviceX.NET}GetBookTitlesResponse found. Expected {http://www.webserviceX.NET}GetBibleWordsbyKeyWordResponse.
On my real application I´m getting an exception with the request:
org.apache.cxf.binding.soap.SoapFault: OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name 'GetAvailabilityRequest' and namespace 'http://schemas.navitaire.com/WebServices/ServiceContracts/BookingService'. Found node type 'Element' with name 'ns4:PriceItineraryRequest' and namespace 'http://schemas.navitaire.com/WebServices/ServiceContracts/BookingService'
My sample project can be downloaded here:
http://www.sendspace.com/file/plt0m4
Thank you
Instead of setting the protocol headers directly like that, use CXF's GZIPOutInterceptor to handle that.
Either that or reset the PROTOCOL headers for each request. When set like that, the headers map gets updated as the request goes through the chain. In this case, the soapaction gets set. This then gets resent on the second request.

Why does GAE BlobstoreService#createUploadUrl(String) include the request query parameter

I am using the GAE Blobstore with Jersey REST on ther server side. I send a GET request to the server via Android and include a query parameter called logindx. My server side code snippet looks like this:
#Path("/getuploadurl")
#GET
#Produces(MediaType.TEXT_PLAIN)
public Response getUploadUrl(#QueryParam("logindx") Long logIndx ) {
BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
String uurl = blobstoreService.createUploadUrl("/logblobkey");
logger.severe("urltest: " + uurl);
return Response.ok(uurl).build();
}
The problem is that the result String I get back at Android (and which is also logged) is:
urltest: http://bardroid123.appspot.com/_ah/upload/?logindx=-43803902306520/AMmfu6b2Ubvf17gD_5uheZeDhTIsr8nm582oaNi0_SDPWfuxqHmYgtkWqVVP52QbBwnnNbWyJf_lDdf9GDmFKtdHU_eUn5gjjtrOSAB32HSu3HiVgLovO5pYeYDkapBPfu7uuo460Ez0/ALBNUaYAAAAAUeuzYniVLlTqyYCjIkfK7-n0ARv5yoo1/
The part ?logindx=-43803902306520/ in the above upload URL should surely not be there? Ho does the createUploadUrl function even know how to get hold of the HttpRequest object to extract the query parameter?
The problem is when I try to use the above uri in my android app like so:
HttpPost postRequest = new HttpPost(uri);
I get the following error:
java.lang.IllegalArgumentException: Illegal character in query at index 253: http://bardroid123.appspot.com/_ah/upload/?logindx=-43803902306520/AMmfu6ZDQr7WenGd0N3ZkbI3zfSl0xPcY56XS5p_VQiS_MWxtTwtc1xm8NbhdrhK-PxopCIolsWci_06DQ3EsUJXSlbiavtJKX9JXT7RU3vTnwj-H0yY5DZKv9hbYR0brfOezaVwob1k/ALBNUaYAAAAAUevBZWOmVC0m1tipSR7Lk9WcwePsXBzf/
Even more confusing is that I don't get the ?logindx=-43803902306520/ part when I do the get request on my local server (from Eclipse provided by App Engine):
http://localhost:8888/res/logs/getuploadurl?logindx=1234567.
In that case the browser returns something like:
http://localhost:8888/_ah/upload/agtiYXJkcm9pZDEyM3IbCxIVX19CbG9iVXBsb2FkU2Vzc2lvbl9fGDIM
Clearly it has got nothing to do with Android and I can't see how this can be Jersey specific either.
Any help would be greatly appreciated.
Thanks - from Africa.
EDIT:
I got it right now by simply dropping the last slash (/) in the uri and the Illegal character in query error went away. The uri was working perfectly with the Blobstore with the ?logindx=-43803902306520/ part included. Don't matter now, but still wondering why it is included in the upload uri?

Resources