My problem look like this: When i send POST request to REST Service I get Access-Control-Allow-Origin error, but request GET it's working.
This is my Rest Service:
#Path("/createUser")
#RequestScoped
public class ClientRestService {
#Inject
private ClientManager clientManager;
#POST
#Path("{name}/{surname}/{adress}")
#Produces(MediaType.APPLICATION_JSON)
public Response createUser(#PathParam("name")String name, #PathParam("surname")String surname, #PathParam("adress")String adress) {
Client client = new Client(name,surname,adress);
Response.ResponseBuilder builder = Response.ok("POST It's working.!!!");
builder.header("Access-Control-Allow-Origin", "*");
builder.header("Access-Control-Allow-Methods", "POST");
return builder.build();
}
#GET
public Response getMetod() {
Response.ResponseBuilder builder = Response.ok("GET It's working.");
builder.header("Access-Control-Allow-Origin", "*");
return builder.build();
}
}
This is client:
$(document).ready(function() {
$.ajax({
url: 'http://localhost:8080/Bank_Project_Test/MyApp/createUser',
type: 'POST',
data: 'name=SomeName'+
'&surname=SomeSurname'+
'&adress=SomeAdress',
success: function(success) {
alert(success);
}
});
});
Might fail because of cors preflight requests?
If you see OPTIONS-method requests in the browser when things fail, then you need to handle those in your server implementation as well.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests
Related
In my ionic 5.0.0 application I'm using cordova's native HTTP to make the rest calls. Below is the code snippet of my logout function.
But when i execute this function i'm getting following error.
"advanced-http: \"data\" argument supports only following data types: String"
logout() {
this.setData("url", "/web/oauth/revoke-token");
let apiUrl = this.getBaseUrl() + this.getData("url");
const headers = {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
'Authorization': 'Basic Y2hyR3liUnBxQUR3X2VDemw5dzc0cHU4dXNnYTpKdmZ1azgyYnBUQlVnNDJ6NU1hZFhXOWJPeElh'
};
const params = {
'companyId': this.getData("COMPANY_ID"),
'token': this.getData("ACCESS_TOKEN"),
'client_id': this.getData("CLIENT_ID"),
'token_type_hint': 'access_token'
};
this.nativeHttp.post(apiUrl, params, headers).then(response => {
console.log("success response: "+response);
})
.catch(error => {
console.log("error response: "+error);
});
console.log("finished");
}
Here is my Spring controller which receives the params.
#RequestMapping(value = "/oauth/revoke-token", method = RequestMethod.POST)
#ResponseBody
public ResponseEntity<Object> logout(HttpServletRequest request) {
String clientId = request.getParameter(OAuth2Constants.CLIENT_ID);
String token = request.getParameter(OAuth2Constants.TOKEN);
String tokenTypeHint = request.getParameter(OAuth2Constants.TOKEN_TYPE_HINT);
String companyId = request.getParameter(WebConstants.COMPANY_ID_PARAMETER);
}
But unfortunately all params receives in the controller as null.
Can someone help me?
Finally I found a solution for the issue. Simply set the data serializer for http request as follows before doing the post call.
this.nativeHttp.setDataSerializer( "urlencoded" );
I try to post a dictionary with data for a reservation. But chrome logs this error:Access to XMLHttpRequest at 'http://localhost:8080/reservations' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
This is strange since I can post images, videos, html content because I put a #CrossOrigin annotation above my controllers. But with this particular post request it doesn’t seem to work.
rest controller:
#CrossOrigin(origins="http://localhost:4200",
maxAge=2000,allowedHeaders="header1,header2",
exposedHeaders="header1",allowCredentials= "false")
#RestController
public class ReservationsController {
private ReservationDao dao;
#Autowired
public ReservationsController(ReservationDao dao) {
this.dao = dao;
}
#PostMapping("/reservations")
public Map<String, String> bookReservation(#RequestBody Map<String, String> reservation) {
System.out.println(reservation);
return null;
}
}
angular api bookReservation method:
bookReservation(data) {
console.log(data);
const result = this.http.post(this.apiUrl + 'reservations', data).subscribe(
(val) => {
console.log('POST call succesful value returned in body',
val);
},
response => {
console.log('POST call in error', response);
},
() => {
console.log('The POST observable is now completed');
});
console.log(result);
}
If you set allowedHeaders only you will allow this params and if it receive other params it never send cross origing headers and chrome will throw error.
You should remove allowedHeaders, exposedHeaders and allowCredentials if you don't need them.
I have a rest API implemented in Java (MSF4J codegen from swagger) and a swagger 2 definition that describes it.
A swagger UI is hosted on a web server. The API is deployed on a VM somewhere on the internet.
My Problem is that the "try it out" function of the swagger UI doesn't work. I always get a "401 Unauthorized". When I take the curl command from the UI and paste it into my terminal it works.
Last week I didn't have HTTPS or Basic Authentication - just HTTP - and it worked fine. Now I don't know why it doesn't work.
Since I changed the swagger definition to https the UI makes an OPTIONS request. I implemented that, but I get 401 responses.
The certificate comes from Lets Encrypt and is used by an apache web server. The apache is a proxy to the rest api on the same machine.
Here is my authentication interceptor:
public class BasicAuthSecurityInterceptor extends AbstractBasicAuthSecurityInterceptor {
#Override
protected boolean authenticate(String username, String password) {
if (checkCredentials(username, password))
return true;
return false;
}
private boolean checkCredentials(String username, String password) {
if (username.equals("testuser"))
return BCrypt.checkpw(password, "$2a$10$iXRsLgkJg3ZZGy4utrdNyunHcamiL2RmrKHKyJAoV4kHVGhFv.d6G");
return false;
}
}
Here is a part of the api:
public abstract class DeviceApiService {
private static final Logger LOGGER = LogManager.getLogger();
public abstract Response deviceGet() throws NotFoundException;
public abstract Response deviceIdAvailableLoadGet(Integer id, Long from, Long to, String resolution)
throws NotFoundException;
public abstract Response deviceIdGet(Integer id) throws NotFoundException;
protected Response getOptionsResponse() {
String allowedOrigin = "";
try {
allowedOrigin = PropertyFileHandler.getInstance().getPropertyValueFromKey("api.cors.allowed");
} catch (IllegalArgumentException | PropertyException | IOException e) {
LOGGER.error("Could not get allowed origin.", e);
}
Response response = Response.ok().header("Allow", "GET").header("Access-Control-Allow-Origin", allowedOrigin)
.header("Access-Control-Allow-Headers", "authorization, content-type").build();
return response;
}
}
public class DeviceApi {
private final DeviceApiService delegate = DeviceApiServiceFactory.getDeviceApi();
// #formatter:off
#GET
#Produces({ "application/json" })
#io.swagger.annotations.ApiOperation(
value = "Get devices",
notes = "",
response = Device.class,
responseContainer = "List",
authorizations = { #io.swagger.annotations.Authorization(value = "basicAuth") },
tags = { "Device", }
)
#io.swagger.annotations.ApiResponses(
value = { #io.swagger.annotations.ApiResponse(
code = 200,
message = "200 OK",
response = Device.class,
responseContainer = "List")
})
public Response deviceGet() throws NotFoundException {
return delegate.deviceGet();
}
#OPTIONS
#Consumes({ "application/json" })
#Produces({ "application/json" })
#io.swagger.annotations.ApiOperation(value = "CORS support", notes = "", response = Void.class, authorizations = {
#io.swagger.annotations.Authorization(value = "basicAuth") }, tags = { "Device", })
#io.swagger.annotations.ApiResponses(value = {
#io.swagger.annotations.ApiResponse(code = 200, message = "Default response for CORS method", response = Void.class) })
public Response deviceOptions() throws NotFoundException {
return delegate.getOptionsResponse();
}
}
EDIT:
This are the headers of the request the swagger ui creates:
Accept: text/html,application/xhtml+xm…plication/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: de,en-US;q=0.7,en;q=0.3
Access-Control-Request-Headers: authorization
Access-Control-Request-Method: GET
Connection: keep-alive
DNT: 1
Host: api.myfancyurl.com
Origin: http://apidoc.myfancyurl.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; …) Gecko/20100101 Firefox/61.0
It seems that the authorization header is missing. When I edit the request and resend it with the authorization header and encoded credentials it works.
But I don't know why swagger doesn't add this header. Should one accept all options requests without authorization?
For my application I am writing a POST request to send array of parameters from a checkbox list. Its working for get request but not working for post request. What is the error in my code.
My code on the client side for sending ajax request to the server.
$(".add").click(function(){
monitoring.length=0;
nonMonitoring.length=0;
$('.modal-body input:checked').each(function() {
monitoring.push($(this).val());
});
$('.addkeywords input:checked').each(function() {
nonMonitoring.push($(this).val());
});
// alert(monitoring[2]+ " " + nonMonitoring[2]);
var monitoringLength=monitoring.length;
var nonMonitoringLength=nonMonitoring.length;
$.ajax({
type : "POST",
url : '/rest/channelstats/my/rest/controller',
data : {
// monitoring : monitoring,
// nonMonitoring: nonMonitoring,
monitoringLength: monitoringLength,
nonMonitoringLength: nonMonitoringLength,
},
success : function(data) {
// var keywordsList=data
//console.log(keywordsList);
// htm = "" ;
}
});
})
My java code on the server side.
#RequestMapping(value="/rest/channelstats/my/rest/controller",method = RequestMethod.POST)
public void monitorKeywords(#RequestParam(value="monitoringLength",required=true)int monitoringLength,#RequestParam(value="nonMonitoringLength",required=true)int nonMonitoringLength){
System.out.println("MonitoringLength =>" +monitoringLength);
System.out.println("NonMonitoringLength=>" +nonMonitoringLength);
}
}
Its working for HTTP GET requests but not working for POST requests.How should I solve this problem?
According to your jquery post request, you should use DAO(Data Access Object) to parse the request data. So you should add class Request
public class Request {
private int monitoringLength;
private int nonMonitoringLength;
//getters and setters
}
And change controller to
#RequestMapping(value="/rest/channelstats/my/rest/controller",method = RequestMethod.POST)
public void monitorKeywords(#RequestBody Request request){
System.out.println("MonitoringLength =>"+request.getMonitoringLength());
System.out.println("NonMonitoringLength=>"+request.getNonMonitoringLength());
}
I have an AJAX call that should return JSON document
function getData() {
$.ajax({
url: '/x',
type: 'GET',
data: "json",
success: function (data) {
// code omitted
}
});
}
My server side is very simple.
#RequestMapping(value = "/x", method = GET, produces = "application/json")
public #ResponseBody List<Employee> get() {
return employeeService.getEmployees();
}
But my request can't even get to the controller. The error is:
HTTP Status 415 - The server refused this request because the request entity is in a format not supported by the requested resource for the requested method.
How can I fix it?
add #Consumes("text/html") before your code in server side,
#Consumes("text/html")
#RequestMapping(value = "/x", method = GET, produces = "application/json")
public #ResponseBody List<Employee> get() {
return employeeService.getEmployees();
}