Get OkHttp PUT request parameters in Servlets - java

I'm making a PUT request using OkHttp 4.9.1 from my Android app as below,
RequestBody reqBody = new FormBody.Builder()
.add("name", name)
.add("phone", phone)
.build();
Request request = new Request.Builder()
.url(API_URL)
.put(reqBody)
.build();
new OkHttpClient().newCall(request).enqueue(new Callback() {
...
});
The request comes to the server but the problem is I cannot access the parameters from the Servlet,
#Override
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("NAME: " + req.getParameter("name"));
System.out.println("PARAMS: " + new HashMap(req.getParameterMap()).toString());
System.out.println("CT: " + req.getContentType());
}
below is the output log from the server,
NAME: null
PARAMS: {}
CT: application/x-www-form-urlencoded
As you can see the parameter map is empty. What am I missing?

request.getParameter() is not working in Servlets when it comes to PUT requests. So this was not a problem with OkHttp. As to why request.getParameter() is not working in doPut(...) refer the post below,
Servlet request.getParameter() returns null in PUT but not in POST

Related

Adding Headers to Zuul when re-directing

I am trying to use Zuul to redirect calls to a downstream system somewhere else.
In the re-direct, I need to add in a Header with necessary data for the api receiving the redirection to process. I can't seem to get the downstream system to detect this data. Attached is my code.
I am using Zuul from Edgware.SR3, Spring Boot 1.5.12
Zuul Filter
#Component
public class RouteFilter extends ZuulFilter{
#Override
public Object run() {
//Testing to add header
context.getRequest().getParameterMap().put("api", new String[]{"api"});
context.getResponse().setHeader("api", api);
context.addZuulResponseHeader("api", "api");
context.addZuulRequestHeader("api", "api");
context.setSendZuulResponse(false);
context.put(FORWARD_TO_KEY, redirect_urls.get(key));
context.setResponseStatusCode(HttpStatus.SC_TEMPORARY_REDIRECT);
context.getResponse().sendRedirect(redirect_urls.get(key));
return null;
}
}
Redirected Service Code
#RequestMapping(value = "/forward")
public ResponseEntity<String> forwardToMe(#RequestHeader(required = true, name = "api")String api){
return new ResponseEntity<String>("Hi",HttpStatus.OK);
}
Error Received in Postman
{
"timestamp": 1524737817729,
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.web.bind.ServletRequestBindingException",
"message": "Missing request header 'api' for method parameter of type String",
"path": "/forward" }
I guess you use a Route Filter, maybe you can try with a Pre Filter.
Adding a custom header can be done with something like this : context.addZuulRequestHeader("Authorization", "Basic " + credentials);.
For the redirection part, you can check this thread
A little late my response but works fine
As referred in the official documentation Cookies and Sensitive Headers
The sensitiveHeaders are a blacklist, and the default is not empty. Consequently, to make Zuul send all headers (except the ignored ones), you must explicitly set it to the empty list. Doing so is necessary if you want to pass cookie or authorization headers to your back end. The following example shows how to use sensitiveHeaders:
zuul:
routes:
entry:
path: /users/**
strip-prefix: false
service-id: users-service
sensitive-headers:
- Cookie,Set-Cookie
This implemented example can also help you
In case if anyone still facing this issue,
In Zuul Proxy add the header to RequestContext as below:
RequestContext ctx = RequestContext.getCurrentContext();
ctx.addZuulRequestHeader("param", "value");
And then in the respective microservices write a custom filter and extract the value as below
#Component
public class MyFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain)
throws ServletException, IOException {
String headerParam = request.getHeaders("param").nextElement();
logger.info("headerParam: "+headerParam);
filterChain.doFilter(request, response);
}
}
I update my comment here just in case if anyone is still facing this problem.
I found this problem recently and resolved by adding the following configuration in my application.yml
application.yml
...
zuul:
sensitive-headers:
- Cookie,Set-Cookie
...
Reference Link below:
https://cloud.spring.io/spring-cloud-static/Dalston.SR5/multi/multi__router_and_filter_zuul.html
RequestContext ctx = RequestContext.getCurrentContext();
String auth = "useeerrr" + ":" + "passsss";
ctx.addZuulRequestHeader("Authorization", "Basic " +
Base64Variants.MIME_NO_LINEFEEDS.encode(auth.getBytes(StandardCharsets.US_ASCII)));
ctx.addZuulRequestHeader("X-USERNAME-HEADER","xxx");
Map<String, List<String>> newParameterMap = new HashMap<>();
Map<String, String[]> parameterMap = ctx.getRequest().getParameterMap();
for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
String key = entry.getKey();
String[] values = entry.getValue();
newParameterMap.put(key, Arrays.asList(values));
}
String authenticatedKey = "authenticated";
String authenticatedValue = "true";
newParameterMap.put(authenticatedKey,Arrays.asList(authenticatedValue));
ctx.setRequestQueryParams(newParameterMap);
HttpServletRequest request = ctx.getRequest();
logger.info(String.format("%s request to %s", request.getMethod(), request.getRequestURL().toString()));
return null;

Does a HttpServlet have to respond to a request?

I have several servlets that do things server side. On a few I just encode some unnecessary data and send it back, which seems pointless. Do you have to respond ? What happens when you just say return ? I've done that before and nothing seems to go wrong but I am relatively new to servlets. Are there consequences for simply returning that go above my head ? And what exactly happens when you return;
if(request.getParameter("name").equals("saveusedcards")) {
String sessId = request.getSession().getId();
//encode request with confirmation that cards were successfully updated
if(usersUpdatedCards.get(sessId).isEmpty()){
//no cards were seen
}
boolean success = DataDAO.updateCards(usersUpdatedCards.get(sessId));
if(success){
System.out.println("Data base update successfull!");
String responseMessage = new Gson().toJson("card successfully udpated");
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
System.out.println("updated cards response message: "+responseMessage);
response.getWriter().write(responseMessage);
return;
} else {
System.out.println("Data base update failed...");
String responseMessage = new Gson().toJson("card was not successfully updated");
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
System.out.println("updated cards response message: "+responseMessage);
response.getWriter().write(responseMessage);
return;
}
}
The servlet must produce an HTTP response for the client, however it is perfectly acceptable to return no content in the response body. When doing so your servlet should make this clear to the client by sending a response code of 204 (no content). Reference: https://httpstatuses.com/204
Here is an example of how you would set the response code from the doGet method. You could do the same from doPost or service methods.
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
// Do whatever work you need to do here...
res.setStatus(HttpServletResponse. SC_NO_CONTENT); // This returns a 204
}

angular send post request but servlet keep showing nul value

i have angular controller which triggered with ng-click:
app.controller('showAllWorkersContoller', function($scope, $http){
$http.get("/SafetyManager/workers").success(function(response){
$scope.workers = response;
$scope.workerInfo = function(id){
$http({
url: '/SafetyManager/workers',
method: "POST",
data: { 'ID' : id },
}).success(function(response){
$scope.info = response;
});
};
});
});
and when i check on chrome debug it sends in form data: {'ID':"1"} (or any other id num according to the worker i click on)
but when the Servlet get the request:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("post request to Workers (get worker by id )");
String id = request.getParameter("ID");
System.out.println("this id is: " + id);
}
its print :
post request to Workers (get worker by id )
this id is: null
how can i get the ID value in the servlet?
The data that you post will not be available as a request parameter, it is in the request body.
You can use a reader to read content from body.
Refer: Getting request payload from POST request in Java servlet
You have to use req.getAttribute(name) to get body content.
Refer this blog:
Difference between getAttribute() and getParameter()

GWT HTTP request response code 0 with CORS working

I am using GWT 2.4 to build an application that runs entirely client-side and uses a web service that I control but is hosted on a different server. On this Java Servlet web service, I have implemented doOptions like so:
protected void doOptions(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods", "POST, GET");
}
And client-side in GWT I submit a request the standard way, e.g.
public static void makeHttpGetRequest(String query, RequestCallback callback) {
String url = "http://example.webservice.com/endpoint" + "?q=" + query;
RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, URL.encode(url));
try {
builder.sendRequest(query, callback);
} catch (RequestException e) {
Window.alert("Server encountered an error: \n" + e.getMessage());
e.printStackTrace();
}
}
And then my callback implements onResponseReceived like this:
#Override
public void onResponseReceived(Request request, Response response) {
if (response.getStatusCode() == 200) {
System.out.println("HTTP request successful, received "
+ response.getText());
processResponse(response.getText());
} else {
System.out.println("HTTP error code " +
response.getStatusCode() + ":" +
response.getStatusText());
}
}
Whenever I run the application in late versions of Chrome or Firefox and send a request, onResponseReceived is called but the response code is 0 and there is no error message. Research indicates that most other instances of this problem arise from SOP restrictions. However, when looking at the HTTP traffic in Fiddler I see that when this is executed, the browser is indeed sending the expected HTTP request, and the web service is indeed returning the expected response, with a 200 response code. Somehow, the browser just isn't handling it properly.
Update: when I look at the traffic in Fiddler, it indicates that the request is sent and a response is received, but when I look at the same request in Chrome's developer console it shows that the request is 'canceled'. If the request is actually happening, what does that mean in this context?
Has anyone run across this problem? Any suggestions on what may be going on?
Error code 0 means that the CORS has been aborted, check that your servlet implementation is all right, I think you have to send Allow instead of Access-Control-Allow-Methods, and also you have to add the Access-Control-Allow-Headers since GWT adds extra headers to ajax requests.
Try this implementation from the gwt-query example which works fine:
private static final String ALLOWED_DOMAINS_REGEXP = ".*";
HttpServletRequest req = (HttpServletRequest) servletRequest;
HttpServletResponse resp = (HttpServletResponse) servletResponse;
String origin = req.getHeader("Origin");
if (origin != null && origin.matches(ALLOWED_DOMAINS_REGEXP)) {
resp.addHeader("Access-Control-Allow-Origin", origin);
resp.setHeader("Allow", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS");
if (origin != null) {
String headers = req.getHeader("Access-Control-Request-Headers");
String method = req.getHeader("Access-Control-Request-Method");
resp.addHeader("Access-Control-Allow-Methods", method);
resp.addHeader("Access-Control-Allow-Headers", headers);
resp.setContentType("text/plain");
}
}
I would rather a filter instead a servlet, like in the link above is explained, though.

Making AJAX POST request to Servlet fails

From my client side code, I am making an AJAX call to my servlet. If I use GET as request method. Everything works and I get response back. But when I send request as POST, servlet fails to send the response. From log I found out that in servlet "request" object is null when made ajax call with POST. According to this post:
Servlet response to AJAX request is empty , I'm setting headers for same-origin policy.
Below is my code for reference:
function aimslc_ajaxCall(url,callback, postParams){
var xmlhttp = null
if (window.XMLHttpRequest){
xmlhttp=new XMLHttpRequest();
}
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){
eval( callback+"("+xmlhttp.responseText+")" );
}
}
if(postParams!=null && typeof postParams!="undefined" ){
xmlhttp.open("POST",url,true);
xmlhttp.send(postParams);
}else{
xmlhttp.open("GET",url,true);
xmlhttp.send();
}
}
Servlet Code:
public void doProcess (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
logger.info("doProcess::start..."+request.getQueryString());
response.setHeader("P3P","CP='NOI ADM DEV PSAi COM NAV OUR OTR STP IND DEM'");
response.setHeader("Access-Control-Allow-Origin","*");
response.setHeader("Access-Control-Allow-Credentials","true");
response.setHeader("Access-Control-Allow-Methods","POST, GET");
}
Throws a null exception on request.getQueryString()
if you do a post all the data is in the request body, not on the url. From here you see that getQueryString only gets the stuff on the url.
See here for how to get the request body.
Also, if your data is name/value pairs, you might want to use getParameter and associated methods.
If the request is null, I ask do you implement doPost on your servlet?

Categories

Resources