I am trying to retrieve data from 3rd party xml api through jquery ajax call. But it is showing Access Control Allow Origin CORS error. After some twiking I a getting ERR_CONNECTION_RESET error on Chrome.
This is the the Api link from where I am trying to retrieve data
http://202.61.117.90/GRIPS/ChallanDetails/query.do?GRN_NO=192021225551499528
This is my own server url to access the api
http://103.240.91.230:8080/CRM/checkApi.do?method=checkApi
Below is the html/jquery code i am using
<script>
$(document).ready(function(){
$.ajax({
type: "GET" ,
url: "http://202.61.117.90/GRIPS/ChallanDetails/query.do?GRN_NO=192021225551499528" ,
headers: { 'Access-Control-Allow-Origin': 'http://202.61.117.90/*' },
dataType: "xml" ,
success: function(xml) {
$(xml).find('GRIPS_EPAYMENT').each(function(){
var grnNo = $(this).find('GRN_NO').text();
var grnDate = $(this).find('GRN_DATE').text();
var brnNo = $(this).find('BRN_NO').text();
$("#grndate").append(grnDate);
$("#brnno").append(brnNo);
});
}
});
});
</script>
I am using tomcat 8.5 and added following filter in web.xml
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Note: when I am calling same api from my local server - it works fine
Related
When calling my REST Service in Angular, there are no response headers.
Login method in Angular
login(username: string, password: string) {
const credentials = { "username": username, "password": password };
return this.http.post(this.url, credentials)
.subscribe(
data => console.log(data), // JSON.stringify(data.headers) also is empty
error => console.log(error)
);
}
Output in the Chrome dev tools console
Response {_body: "", status: 200, ok: true, statusText: "OK", headers:
Headers…}headers: Headers_headers: Map(0)_normalizedNames:
Map(0)proto: Objectok: truestatus: 200statusText: "OK"type: 2url:
"http://localhost:8080/backend/rest/login"_body: ""proto: Body
But when I send the same post request with postman, I get the expected result:
Access-Control-Allow-Credentials →true
Access-Control-Allow-Origin →chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop
Authorization →Bearer eyJ[...]
Connection →keep-alive
Content-Length →0
Date →Mon, 12 Jun 2017 13:19:54 GMT
Server →WildFly/10
Vary →Origin
X-Powered-By →Undertow/1
The REST Service
#POST
#Consumes(MediaType.APPLICATION_JSON)
public Response authenticateUser(CredentialsDTO credentialsDTO) {
try {
authService.login(credentialsDTO.getUsername(), credentialsDTO.getPassword());
} catch (WrongCredentialsException e) {
return Response.status(Status.FORBIDDEN).entity("WrongCredentialsException").build();
}
// Issue token
String token = issueToken(credentialsDTO.getUsername());
// Return the token on the response
return Response.ok().header(AUTHORIZATION, "Bearer " + token).build();
}
Why can't I see the headers in chrome ?
UPDATE
I am also using a CORSFilter that allowed Javascript to contact my backend in the first place. This is how it is configured in my web.xml
<filter>
<filter-name>CORS</filter-name>
<filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
<init-param>
<param-name>cors.allowGenericHttpRequests</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>cors.allowOrigin</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>cors.allowSubdomains</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>cors.supportedMethods</param-name>
<param-value>GET, HEAD, POST, DELETE, OPTIONS</param-value>
</init-param>
<init-param>
<param-name>cors.supportedHeaders</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>cors.supportsCredentials</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>cors.maxAge</param-name>
<param-value>3600</param-value>
</init-param>
</filter>
<filter-mapping>
<!-- CORS Filter mapping -->
<filter-name>CORS</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>
Although I thought it was configured to allow everything, I am not sure if this is related to my problem.
By default CORS responses only exposes these 6 headers to scripts:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
To allow scripts to access other headers sent by the sever, the server needs to send the Access-Control-Expose-Headers Header.
The Access-Control-Expose-Headers response header indicates which headers can be exposed to scripts as part of the response by listing their names.
eg: Access-Control-Expose-Headers: Authorization, X-Foobar
You can tweak your web.xml file including this to allow the Authorization header to be accessed from the script that made the XHR:
<init-param>
<param-name>cors.exposedHeaders</param-name>
<param-value>Authorization</param-value>
<init-param>
I used the following solution to allow my custom header in Owin self-hosted web api
using Owin;
using Microsoft.Owin.Cors;
using System.Threading.Tasks;
using System.Web.Cors;
namespace App.Web.App_Start
{
public static class CorsConfig
{
public static void Configure(IAppBuilder app)
{
var allowedOrigins = "comma,separated,list,of,origins";
var corsPolicy = new CorsPolicy
{
AllowAnyHeader = true,
AllowAnyMethod = true,
AllowAnyOrigin = false,
SupportsCredentials = true
};
corsPolicy.ExposedHeaders.Add("Custom-Header");
foreach (string origin in allowedOrigins.Split(','))
corsPolicy.Origins.Add(origin);
app.UseCors(new CorsOptions
{
PolicyProvider = new CorsPolicyProvider
{
PolicyResolver = context => Task.FromResult(corsPolicy)
}
});
}
}
}
I call the method like this CorsConfig.Configure(app); // app is Owin.IAppBuilder
The headers in an HttpResponse object are lazy-loaded, so headers will appear to be empty until you force the values to be loaded. Try calling response.headers.keys() to see all available header names. By the way, this also forces all values to be loaded into the map response.headers.headers.
Be sure to use headers.get('my-header-name') if you only need to access one particular header value.
I'm using Spring Data Neo4j Rest backend served on Tomcat (8.0.27) with Angular frontend, all served locally at http://localhost:8080/. When I try to delete a record with either $http.delete() or with $resource().delete(), tomcat returns a 405 not supported error.
However, using $http({method: 'DELETE', url: '/competitors/13'}) works fine. Unfortunately, this does not allow me to use the angular $resource service instead of $http, which is my goal. (As an aside, PUT creates the same 405 response as DELETE)
I am also able to use DELETE from command line. This works fine:
curl -X DELETE http://localhost:8080/competitors/13
I have disable csrf in WebSecurityConfig in case that has anything to do with it.
I have also added readonly init-param to web.xml to try to force tomcat to accept DELETE, like so:
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Proto v2 Application</display-name>
<servlet>
<servlet-name>proto</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>readonly</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>proto</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Since I've verified that the server is able to perform the delete, I will omit all Java code. Here is my complete .js file with the angular module:
var magneticApp = angular.module('magneticApp', ['ngResource'])
.controller('defaultCtrl', function ($scope, $http, $resource, baseUrl) {
$scope.Competitor = $resource("/competitors/:id", {id: "#id"});
$scope.listItems = function () {
var query = $scope.Competitor.get(function () {
console.log('inside query');
});
query.$promise.then(
function successCallback(data) {
$scope.competitors = data._embedded.competitors;
},
function errorCallback(data) {
console.log('error:');
console.dir(data);
}
);
};
/*
* THIS DELETE FUNCTION RETURNS A 405 NOT SUPPORTED ERROR
*/
$scope.deleteItem = function (item) {
var query = $scope.Competitor.delete({}, item.itemId);
query.$promise.then(
function successCallback(data) {
console.log('success:');
$scope.competitors.splice($scope.competitors.indexOf(item), 1);
},
function errorCallback(data) {
console.log('error:');
console.dir(data);
}
);
};
/*
* THIS DELETE FUNCTION WORKS PROPERLY
*/
$scope.deleteItemWorksCorrectly = function (item) {
$http({method: 'DELETE', url: '/competitors/' + item.itemId})
.then(
function successCallback(data) {
$scope.competitors.splice($scope.competitors.indexOf(item), 1);
},
function errorCallback(data) {
console.log('delete error');
console.dir(data);
}
);
};
$scope.adjustActive = function (item) {
item.id = item.itemId;
console.log('adjustActive');
console.dir(item);
$http.post('/competitors', item)
.success(function (data) {
$http.get('/competitors').success(function (data) {
console.dir(data._embedded.competitors);
$scope.competitors = data._embedded.competitors;
});
});
};
$scope.addItem = function (itemName) {
var item = {name: itemName};
$http.post('/competitors', item)
.success(function (data) {
$http.get('/competitors').success(function (data) {
console.dir(data._embedded.competitors);
$scope.competitors = data._embedded.competitors;
//magneticApp.controller('defaultCtrl').$scope.competitors = data._embedded.competitors;
});
});
};
$scope.listItems();
});
Can anyone shed some light on this? Thanks.
I am working on ExtJS and need to access the REST services. I tried doing that with Spring's MVC REST supporting functionality and it worked well.
Now its kind of mandatory that I have to go with Jersey(JAX-RS). When tried with Jersey, I keep getting 404 error. I think the annotations, URL mapping, etc are fine (since the similar ones worked for Spring)
Below are the relevant code snippets.
Web.xml
<servlet>
<servlet-name>spring-jersey</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.myProducts.controller</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring-jersey</servlet-name>
<url-pattern>/jersey/*</url-pattern>
</servlet-mapping>
App.js
Ext.onReady(function() {
var store = Ext.create('Ext.data.Store', {
autoLoad: true,
autoSync: true,
model: 'Product',
proxy: {
type: 'rest',
url: 'products',
format: 'json',
headers: {
'Content-Type': 'application/json'
},
reader: {
type: 'json',
root: 'data'
},
writer: {
type: 'json'
},
api: {
create: 'products/createJ/',
read: 'products/readJ/',
update: 'products/editJ/',
destroy: 'products/deleteJ/'
}
}
});
Controller :
#Component
#Path("products/jersey/products")
public class JerseyProductsController {
#Autowired
private ProductService productService;
#POST
#Path("createJ/{id}")
#Consumes(MediaType.APPLICATION_JSON_VALUE)
#Produces(MediaType.APPLICATION_JSON_VALUE)
public Product createJ(#PathParam("id") int id, #RequestBody Product myProduct) {
myProduct.setId(id);
return productService.create(myProduct);
}
#PUT
#Path("editJ/{id}")
#Consumes(MediaType.APPLICATION_JSON_VALUE)
#Produces(MediaType.APPLICATION_JSON_VALUE)
public Product editJ(#PathParam("id") int id, #RequestBody Product myProduct) {
myProduct.setId(id);
return productService.update(myProduct);
}
#DELETE
#Path("deleteJ/{id}")
#Consumes(MediaType.APPLICATION_JSON_VALUE)
#Produces(MediaType.APPLICATION_JSON_VALUE)
public Product deleteJ(#PathParam("id") int id) {
return productService.delete(id);
}
#GET
#Path("readJ/")
#Consumes(MediaType.APPLICATION_JSON_VALUE)
#Produces(MediaType.APPLICATION_JSON_VALUE)
public List<Product> allProductsJ() {
return productService.getAll();
}
}
I get 404 for below URL:
Request URL:http://localhost:4080/MyProducts/products/jersey/products/readJ/.json?_dc=1407930853131&page=1&start=0&limit=25
Request Method:GET
Status Code:404 Not Found
Kindly let me know what is being missed.
You may need to use /jersey/products/jersey in your URL since you are having <url-pattern>/jersey/*</url-pattern>
Not sure what's the issue but you could try below one :
<url-pattern>*.do</url-pattern>
I believe its because it could capture requests ending with .do and it reduced the headache of having some pattern in between the URL.
I think your servlet mapping is incorrect. Your Url-Pattern is /jersey/* but in your url is /MyProducts/*
put this in your web.xml
<servlet-mapping>
<servlet-name>spring-jersey</servlet-name>
<url-pattern>/MyProducts/*</url-pattern>
Ajax to consume WCF service hosted at server. I already configured and allowed following flag of JQM to use Cross-Domain Requests.
$.support.cors = true;
$.mobile.allowCrossDomainPages = true;
The same code is working with Android emulator and Device. I also allowed the url in config.xml file of Phonegap for IOS app.
Also I can browse the same HTML page in Safari and IOS emulator. In both webservice is working fine. The issue occurs when I build and run the phonegap app in IOS emulator or device. The service will not called and success callback of $.ajax is called. I checked the response in success and I found that it is returning the HTML of web service url page (.svc).
I used following code to call SVC using $.ajax
var soapRequest = '<?xml version="1.0" encoding="utf-8"?>'
+ '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">'
+ '<soap:Body>'
+ '<SignIn xmlns="http://tempuri.org/">'
+ '<UserName>' + $.trim($('#txtEmail').val()) + '</UserName>'
+ '<Password>' + $.trim($('#txtPassword').val()) + '</Password>'
+ '<DeviceDetails>' + GetDeviceInfo() + '</DeviceDetails>'
+ '</SignIn>'
+ '</soap:Body>'
+ '</soap:Envelope>';
$.ajax({
beforeSend: function (xhr) {
ShowLoading('Please wait...');
xhr.setRequestHeader("SOAPAction", "http://tempuri.org/IService/SignIn");
}, //Show spinner
complete: function () {
HideLoading();
}, //Hide spinner
url: "http://somedomain/service.svc",
type: "POST",
dataType: "xml",
data: soapRequest,
contentType: "text/xml; charset=\"utf-8\"",
success: function (rcvdata, status) {
alert(rcvdata); // THIS IS GIVING HTML OF SERVICE PAGE
},
error: function (request, status, error) {
alert(request + "\n" + status + "\n" + error);
HideLoading();
}
});
I also tied to change the value of async and processdata option of AJAX but it is always returning the svc service page html. Ajax request status is always 200.
This issue is only occurring in Phonegap IOS app. When I directly open the HTML page in IOS emulator browser then the service is called successfully and I got the valid SOAP response.
I am using Phonegap 2.8.1 and also tried in 2.9.0
Thanks in advance.
Edit --------------
I host the WCF service local environment in IIS then it is working fine and I got the response from service. I also checked and compare the IIS settings in local and live server. Both are same
Everything seems to work fine until i want to submit the form and update the database.
Wildcard mapping works on requests like "/navigation/edit/1", but when i submit the form as:
var ajaxPost = function(Url, Params) {
Ext.Ajax.request({
url: Url,
params: Params,
method: 'POST',
async: false,
scope: this
});
};
it says "200 bad response: syntax error" and in firebug there is "Failed to load source for: http://.../Navigation/edit/1".
Any help?
Perhaps its a syntax error: try
params: {"sendparams": Params}
it turns out there was a urlrewrite rule for some other web site corrupting my requests.