I get null when I send a POST. Please someone know how to pass value with Angular using #HeaderParam in Jersey?
I have this in backend:
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Users loginUser(#HeaderParam("username")String username,#HeaderParam("password") String password){
System.out.println("What happen"+userService.loginService(username, password));
return userService.loginService(username, password);
}
and this in front-end, using Angular:
$scope.getUserFunction = function () {
$http({
method : 'POST',
url : 'http://localhost:8080/JersyBackEnd/resources/login'+data,
contentType:'application/json',
data : {username: "akram",password:"yes"},
})
.then(function(data) {
console.log(data);
});
};
I get 204 because of the null data.
Can anyone help me, either using HeaderParam, PathParam or FormParm annotations in Jersey?
data is sent as the request body. What you really want is headers.
From the docs:
data – {string|Object} – Data to be sent as the request message data.
headers – {Object} – Map of strings or functions which return strings representing HTTP headers to send to the server. If the return value of a function is null, the header will not be sent. Functions accept a config object as an argument.
Example:
$http({
...
headers: {
username: "akram",
password: "yes"
}
})
When you use #HeaderParam, you have to pass the values from .JS using headers: { 'something': 'anything' }. As i can see currently you are using data : {username: "akram",password:"yes"}. try to use headers: { 'something': 'anything' } instead of this.
Please try header, hope it will solve your null issue.
Related
I am using Vue.js, axios and Spring.
On the page I have the following axios code
axios({
method: 'post',
url: '/user/info',
params: {
'_csrf' : document.getElementById('csrf_id').value,
'name' : 'job',
'age' : '25',
},
headers: {'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'application/json'}
});
And on the server I have a receiving method like this
#Controller
#RequestMapping("/user")
public class UserInfo {
#ResponseBody
#PostMapping(value = "/info", consumes = "application/x-www-form-urlencoded", produces = "application/json" + ";charset=utf8")
public String info(#RequestParam(value = "name") String name, #RequestParam(value = "age") String age) {
System.out.println(name);
System.out.println(age);
return "ok";
}
}
Axios makes a request to the server, but the server returns a 415 response.
The request headers are missing the application/x-www-form-urlencoded content type. I suspect the problem lies precisely in this.
Tell me, what am I doing wrong?
HttpMethod Post is a method of writing and transmitting data in the request body.
In your case, you put data through params. If you execute code as you write, data will be sent such as /user/info?_csrf=value&name=job&age=25 and there will be no data in the request body.
To get the response you want, you can modify it as below.
axios({
method: 'post',
url: '/user/info',
data: '_csrf=csrf&name=job&age=25',
headers: {'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'application/json'}
});
change params keyword to data and write data like querystring.
#CrossOrigin(origins = "http://localhost:3000")
#GetMapping("")
public ResponseEntity<List<ToDoItemViewModel>> loadCategoriesByName(#RequestParam(required = false) String name)
{
List<ToDoItemViewModel> allItemsByCategoryName = toDoItemService.getAllItemsByCategoryName(name);
return new ResponseEntity<>(allItemsByCategoryName, HttpStatus.OK);
}
How can i pass just a primitive type to the controller, here is how my $.ajax looks like
$.ajax({
method: 'GET',
url: "http://localhost:8080/todItems",
contentType: 'application/json',
crossDomain: true,
data: 'Work',
success: (resp) => {
console.log(resp)
},
error: (resp) => {
console.log(resp);
}
})
Now when i debug it, it indeed sends the request to this controller, but the String name is always null for some reason, can you just show me what i have to adjust in my ajax request, it's probably something in the data field.
You are using GET Request with request params(#RequestParam annotation).
#RequestParam means that param in request pass across url, like this;
http://localhost:8080/todItems?name=Work
So, you just need to move data to url params.
If you prefer send data across request body, please do not use GET method, use POST instead. Many web servers are not supporting request body in GET Requests
I am trying to create a RESTful service and encounter a type conflict within the application. Right now, I deal with this problem by using two different URLs, but this leads to other problems and doesn't feel right.
// Controller to get a JSON
#RequestMapping(value = "/stuff/{stuffId}",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public stuffDto getStuff(#PathVariable String stuffId) {
return //JSON DTO//
}
// Controller to get an HTML Form
#RequestMapping(value = "/stuff/{stuffId}/form", // <- nasty '/form' here
method = RequestMethod.GET)
public String getStuffForm(#PathVariable String stuffId, ModelMap model) {
// Prepares the model
return "JSP_Form";
}
And on the JavaScript side:
function loadStuffForm(url) {
$.ajax({
type : 'GET',
url : url,
success : function(response) {
showStuffForm(response);
}
});
}
How can I merge both controllers so it will return the right type of data based on what the client accepts? By default it would return a JSON. I want to add 'text/html' somewhere in the ajax query to get the Form instead. Any idea?
You can use Content Negotiation to communicate to the server and tell it what kind of a response you're expecting form it. In your particular scenario, you as a client using an Accept header tell the server to serve a text/html or application/json. In order to implement this, use two different produces with that same URL:
// Controller to get a JSON
#ResponseBody
#RequestMapping(value = "/stuff/{stuffId}", method = GET, produces = "application/json")
public stuffDto getStuff( ... ) { ... }
// Controller to get an HTML Form
#RequestMapping(value = "/stuff/{stuffId}", method = GET, produces = "text/html")
public String getStuffForm( ... ) { ... }
In your requests to /stuff/{id} endpoint, if you send Accept: text/html in headers, the HTML form would return. Likewise, you would get the JSON response by sending Accept: application/json header.
I'm not a JQuery expert but you can check this answer out on how to send an Accept header in $.ajax requests.
I'm doing an ajax call to my server, and need to get the values from it. How is this done?
This is the ajax:
$.ajax({
type: "POST",
url: "http://localhost:8080/myapp/etc",
contentType: "application/json; charset=utf-8",
data: {"id": "1", "somekey": "somevalue"},
dataType: "json",
async: "true",
success: function(msg) {
alert("success " + msg);
},
error: function(msg) {
alert("error " + msg.toString());
}
});
I'm working with Restlets so I'm assuming the values would be in the Representation entity. This is the method:
#Post
public Representation doPost(Representation entity) {
String et = java.net.URLDecoder.decode(entity.getText(), "UTF-8");
System.out.println("the entity text " + et);
}
This prints out "id": "1", "somekey": "somevalue". But how do I get the other values? The async, the url, etc?
Restlet will give you access about the elements sent within the request (URL, headers, payload) but not to client-side configuration properties to build the request.
You can have a look at what is sent in the request for your AJAX call using tool like Chome console or Firebug.
The property async isn't sent within the request, so you can't get it from server side. For the URL, you can use this code within a server resource:
Reference reference = getRequest().getResourceRef();
String url = reference.toString();
For more details, have a look at javadocs for the class Reference: http://restlet.com/technical-resources/restlet-framework/javadocs/2.1/jee/api/org/restlet/data/Reference.html. This class allows you to have access to each element within it (host domain, port, path, ...).
Hope it helps you,
Thierry
The async is a client-side directive telling the client not to block while the ajax call is processed. The server doesn't know or care about this.
Getting the URL is possible server side using something like String url = ((HttpServletRequest)request).getRequestURL().toString();
you can do something like this, using the org.restlet.ext.json extension:
#Post
public Representation handle(JsonObject jo) {
System.out.println(jo.getString("id"));
System.out.println(jo.getString("somekey"));
return ...;
}
I have a problem in my spring boot app with the csrf token.
I have a form where I can edit a Person. A Person can have
Let us now imagine that the person has a car and enter this and store it. The next time he wants to delete this car and enter another one. I have created that so that there is a list of all of his cars -- he has the option to remove this from the list. Now I'm starting from these pills and want to send with the corresponding ID to the server a POST. When I try I get a 403 forbidden and I have no idea why.
If I change from POST to GET, then it works.
My JavaScript (taken from this site: http://docs.spring.io/autorepo/docs/spring-security/4.0.0.CI-SNAPSHOT/reference/htmlsingle/#the-csrfmetatags-tag)
var csrfParameter = $("meta[name='_csrf_parameter']").attr("content");
var csrfHeader = $("meta[name='_csrf_header']").attr("content");
var csrfToken = $("meta[name='_csrf']").attr("content");
// using JQuery to send a non-x-www-form-urlencoded request
var headers = {};
headers[csrfHeader] = csrfToken;
$.ajax({
url: "./delete/car",
type: "GET",
headers: headers,
});
$.ajax({
url: "./delete/car",
type: "POST",
headers: headers,
});
My controller methods:
#RequestMapping(value = "/{login}/delete/car", method = RequestMethod.GET)
public ModelAndView delete(#PathVariable("login") final String login) {
System.out.println("Stop");
return new ModelAndView("redirect:" + WebSecurityConfig.URL_PERSONS_OVERVIEW);
}
#RequestMapping(value = "/{login}/delete/car", method = RequestMethod.POST)
public ModelAndView deleteInstEmp(#PathVariable("login") final String login) {
System.out.println("Stop");
return new ModelAndView("redirect:" + WebSecurityConfig.URL_PERSONS_OVERVIEW);
}
Any suggestions?
Thanks in advance.
OK, after strugglin with all that, I get the following result.
I added the fail method to the Ajax construct and get the following message:
"Failed to execute 'setRequestHeader' on 'XMLHttpRequest': '${_csrf.headerName}' is not a valid HTTP header field name."
the official spring site advises that you have to put this: <sec:csrfMetaTags /> or from other sources, this: <meta name="_csrf" th:content="${_csrf.token}"/> in your html file.
After this, you should be able to access these attributes in your JavaScript, but in my case I get undefined and ${_csrf.headerName}.
A last try was to take the value from the hidden value (chapter 24.5: http://docs.spring.io/autorepo/docs/spring-security/4.0.0.CI-SNAPSHOT/reference/htmlsingle/#the-csrfmetatags-tag).
Now, I have the following:
$(function () {
var token = $("input[name='_csrf']").val();
var header = "X-CSRF-TOKEN";
$(document).ajaxSend(function(e, xhr, options) {
xhr.setRequestHeader(header, token);
});
});
$.ajax({
url: "./delete/car",
type: "POST",
success:function(response) {
alert(response);
}
});
With this it works like a charm.
Another way, you can use the following code:
$.ajax({
url : './delete/car',
headers: {"X-CSRF-TOKEN": $("input[name='_csrf']").val()},
type : 'POST',
success : function(result) {
alert(result.msgDetail);
}
})
I suggest you first check if a valid csrf token and the header have been generated using chrome debugger. If not, then have you added the <sec:csrfMetaTags /> in the <head>?(you will need to import the spring security taglibs). If using Apache tiles, you will have to add this at the <head> section of the template file being used for the view.
If the token is not empty, then in your security-context/configuration file, check if you have disabled csrf security by any chance. By default it is enabled and needs to be for this process to work.