I am trying to perform an AJAX request to a Play application on Heroku from my local machine. Currently, the 'complete' and 'error' handlers are being invoke but not the 'success'. In Opera and Firefox, my response headers are:
HTTP/1.1 200 OK
Cache-Control: no-cache
Content-Type: application/json; charset=utf-8
Server: Play! Framework;1.2.4;prod
Set-Cookie: PLAY_FLASH=;Expires=Fri, 5-Oct-12 08:22:46 GMT;Path=/
Set-Cookie: PLAY_ERRORS=;Expires=Fri, 5-Oct-12 08:22:46 GMT;Path=/
Set-Cookie: PLAY_SESSION=;Expires=Fri, 5-Oct-12 08:22:46 GMT;Path=/
Content-Length: 2295
Connection: keep-alive
Opera also shows the returned JSON object
Here is my code:
var url = "http://myurl.com"
$.ajax({
'complete': function (jqXHR, status) {
console.log('Complete!');
console.log(status);
console.log(jqXHR.getAllResponseHeaders());
},
'dataType': "application/json",
'error': function (jqXHR, status, error) {
console.log('Error!');
console.log(status);
console.log(error);
},
'success': function (data, status, jqXHR) {
console.log('Success!');
console.log(status);
console.log(data);
},
'type': 'GET',
'url': url
});
Other similar questions suggested changing the datatype to text or removing it altogether: neither work. I have successfully validated the returned JSON object at JSONLint.
The console log is:
Error!
error
Complete!
error
I'm not sure if it is linked, but the getAllResponseHeaders() function is returning an empty string.
Is this a cross domain error?
Any help is welcome!
Thanks
Here they suggest that it is indeed a cross domain error.
Related
I am using the serverless framework to deploy my lambda to AWS and have been able to successfully run POST requests via Postman to the API Gateway associated with my lambda function, but when I try run a POST request from a form submission (AJAX request) on a local server I am receiving the 502 error message,
Access to XMLHttpRequest at 'https://*id*.execute-api.us-east-1.amazonaws.com/prod/message' from origin 'http://localhost:2368' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
which I didn't expect since I have the cors property in my serverless.yml set to true, which sets CORS configurations for the HTTP endpoint. Here is the function yaml setup:
functions:
email:
handler: handler.sendEmail
events:
- http:
path: message
method: post
cors: true
Here is the jQuery AJAX request:
$.ajax({
type: 'POST',
url: 'https://*id*.execute-api.us-east-1.amazonaws.com/prod/message',
crossDomain: true,
data: JSON.stringify(formData),
contentType: 'application/json',
dataType: 'json',
success: function(data) {
console.log(data)
},
error: function(xhr, ajaxOptions, thrownError) {
console.log(xhr);
console.log(ajaxOptions);
console.log(thrownError);
}
});
Is there something that I need to adjust with the API Gateway configuration or within my Lambda application?
Here is my response function:
const generateResponse = (body, statusCode) => {
console.log("generateResponse")
console.log(body)
return Promise.resolve({
headers: {
"access-control-allow-methods": "POST",
"access-control-allow-origin": "*",
"content-type": "application/json",
},
statusCode: statusCode,
body: `{\"result\": ${body.message}}`
});
};
Also provided is the ajax request:
$.ajax({
type: 'POST',
url: 'https://*my-lambda-id*.execute-api.us-east-1.amazonaws.com/prod/message',
crossDomain: true,
data: JSON.stringify(formData),
contentType: 'application/json',
dataType: 'json',
success: function(data) {
console.log(data)
},
error: function(xhr, ajaxOptions, thrownError) {
console.log(xhr);
console.log(ajaxOptions);
console.log(thrownError);
}
})
And the resulting OPTION and POST Request and Response Headers triggered by the AJAX:
OPTIONS:
Request URL: https://*my-lambda-id*.execute-api.us-east-1.amazonaws.com/prod/message
Request Method: OPTIONS
Status Code: 200
Response Headers
access-control-allow-credentials: false
access-control-allow-headers: Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent
access-control-allow-methods: OPTIONS,POST
access-control-allow-origin: http://localhost:2368
content-length: 1
content-type: application/json
date: Tue, 08 Oct 2019 11:11:36 GMT
status: 200
via: 1.1 *id*.cloudfront.net (CloudFront)
x-amz-apigw-id: *id*
x-amz-cf-id: *id*
x-amz-cf-pop: *id*
x-amzn-requestid: *id*
x-cache: Miss from cloudfront
Request Headers
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: POST
Origin: http://localhost:2368
Referer: http://localhost:2368/
Sec-Fetch-Mode: no-cors
POST
Request URL: https://*my-lambda-id*.execute-api.us-east-1.amazonaws.com/prod/message
Request Method: POST
Status Code: 502
Request Headers
Accept: application/json, text/javascript, */*; q=0.01
Content-Type: application/json
Origin: http://localhost:2368
Referer: http://localhost:2368/
Sec-Fetch-Mode: cors
Wherever you return a response from your Lambda function you need to include the specific header CORS requests. The cors: true option you add to serverless.yml only helps make sure that the OPTIONS pre-flight requests work. Don't forget that this includes non-success responses as well.
For example:
return {
statusCode: 200,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': true,
'Access-Control-Allow-Headers': 'Authorization'
}
}
Laravel Version: 5.3.31
Description:
I have the exact same ajax call on two diferente pages of my project but im getting an "methodNotAllowed" error in one of them.
My web.php:
Route::post('/seccion', 'FiltrosController#getSecciones')->name("filtro.secciones");
My AJAX call:
$.ajax({
type: "post",
url: "{{ route("filtro.secciones") }}",
data: $("#form").serialize(),
dataType: "json",
success: function (datos) {
//mycode
},
error: function (request, status, error) {
console.log(error);
}
});
Here is the header of the call that works:
Request URL:http://192.168.99.100:3001/seccion
Request Method:POST
Status Code:200 OK
Remote Address:192.168.99.100:3001
Referrer Policy:no-referrer-when-downgrade
And the response header that i get:
Cache-Control:no-cache
Connection:Keep-Alive
Content-Length:457
Content-Type:application/json
Date:Mon, 07 Aug 2017 19:26:43 GMT
Keep-Alive:timeout=5, max=97
Server:Apache/2.4.10 (Debian)
Ok in this case all works. But then in the other page, i make the same ajax call and im getting this:
Request URL:http://192.168.99.100:3001/seccion
Request Method:POST
Status Code:405 Method Not Allowed
Remote Address:192.168.99.100:3001
Referrer Policy:no-referrer-when-downgrade
And the response header of the call that fails:
allow:POST
Cache-Control:no-cache, private
Connection:close
Content-Type:text/html; charset=UTF-8
Date:Mon, 07 Aug 2017 19:26:57 GMT
Server:Apache/2.4.10 (Debian)
X-Powered-By:PHP/7.1.7
We can see POST is allowed in the response header but im getting this "Code:405 Method Not Allowed"
I dont know what is happing, any clue?
Thanks.
The problem was that i put "{{ method_field('PATCH') }}" in the form that wraps the select dropdown that fires the ajax call, so a _method parameter with "PATCH" value is passed in the data of the ajax call and throws the "methodNotAllowed" error.
I fixed it just passing the data i need and not all the form serialized:
$.ajax({
type: "post",
url: "{{ route("filtro.secciones") }}",
data: $("#form").find('#zonas').serialize(),//<-- solution
dataType: "json",
success: function (datos) {
//my code
},
error: function (request, status, error) {
console.log(error);
}
});
We're using web api cors requests in our application and many api calls are cacheable by the clients, i.e. browsers.
Chrome and Firefox honours the cache control headers and caches the responses as they are supposed to but Internet Explorer and Safari always performs new requests.
Controller:
[EnableCors("*", "*", "*")]
public HttpResponseMessage Get()
{
var response = Request.CreateResponse(HttpStatusCode.OK, "test");
response.Headers.CacheControl = new CacheControlHeaderValue
{
Public = true,
MaxAge = DateTime.UtcNow.AddDays(7) - DateTime.UtcNow
};
response.Headers.ETag = new EntityTagHeaderValue("\"" + Guid.NewGuid().ToString() + "\"");
return response;
}
JQuery ajax request (issued from another domain):
$.ajax({
type: 'GET',
url: 'http://next.b.se/api/tests'
}).done(function (data) {
$("#v").text("Done!");
}).error(function (jqXHR, textStatus, errorThrown) {
$("#v").text("Error");
});
Request (from fiddler):
GET http://next.b.se/api/tests HTTP/1.1
Referer: http://hitta.a.se/local.html
Accept: */*
Accept-Language: en,sv-SE;q=0.5
Origin: http://hitta.a.se
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Host: next.b.se
DNT: 1
Connection: Keep-Alive
Response (from fiddler):
HTTP/1.1 200 OK
Cache-Control: public, max-age=604800
Content-Type: application/json; charset=utf-8
Content-Encoding: gzip
ETag: "4bfa551b-61db-42cb-8877-25f20a0ec94d"
Vary: Accept-Encoding
Server: Microsoft-IIS/7.5
Access-Control-Allow-Origin: *
Date: Mon, 09 Jun 2014 10:58:12 GMT
Content-Length: 192
When loading the page hitta.a.se/local.html, from which the cross domain request is done, the first time after cleaning the browser cache all browsers (IE, CHrome, FF and Safari) makes a request to the api endpoint as expected.
When loading the page hitta.a.se/local.html the second time in a new tab and hitting return Chrome and FF gets the cached version, i.e. no request is issued to the api (as expected due to the cache-control headers) according to Fiddler and dev tools. The problem is that IE issues a new request, it does not use the cached version and it doesn't issue a conditional get using the etag and if-none-match header. I know that the api doesn't handle if-none-match requests but the problem is that the browser doesn't perform a conditional request at all.
Which is the appropriate approach if we would like IE and Safari to use the cached responses?
Notice! This question is posted on codeplex, https://aspnetwebstack.codeplex.com/discussions/548035, as well. I don't know where the web api gurus are most active!
UPDATE 2014-06-10
If we change the api call to use JSONP instead of Ajax Internet Explorer caches the response according to the cache headers.
JQuery JSONP request:
$.ajax({
type: 'GET',
url: 'http://next.b.se/api/tests',
dataType: 'jsonp',
contentType: 'text/javascript',
jsonpCallback: 'p',
cache: true
}).done(function (data) {
$("#v").text(data.v);
}).error(function (jqXHR, textStatus, errorThrown) {
$("#v").text("Error");
});
Safari still performs a new request. Any known workarounds for Safari? I.e. force Safari to honour the cache headers either on a cross domain XHR request or a JSONP request?
BR,
Max
I'm trying to activate jQuery.ajax() request using jsonp and I'm getting the following error:
Resource interpreted as Script but transferred with MIME type text/xml
My request is:
return $.ajax({
type: 'GET',
url: this.AgentServiceUrl + "/" + methodName,
async: false,
jsonpCallback: 'jsonCallback',
contentType: "text/xml",
dataType: 'jsonp',
success: function (json) {
console.dir(json.sites);
},
error: function (e) {
console.log(e.message);
}
});
and the response I'm getting from the server is:
HTTP/1.1 200 OK
Cache-Control: private, max-age=0
Content-Length: 114
Content-Type: text/xml; charset=utf-8
Server: Microsoft-IIS/7.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Wed, 19 Jun 2013 08:43:13 GMT
<?xml version="1.0" encoding="utf-8"?>
<string xmlns="http://CosmoCom.com/WebServices/TCWS/Agent">010001</string>
What can I do?
As the error message rightly says, when you mark your datatype as jsonp. it means the data you will be receiving will be script. so you cant have your contenttype as "text/xml".
Try changing it to "application/json" .
Also make sure that your service is jsonp enabled, meaning it returns data wrappped in a callback function.
I have a page locations.aspx that has a method behind it in locations.aspx/getData. when I use the code
$http.jsonp($scope.url)
.success(function (data, status, headers, config) {
alert(data);
}).error(function (data, status, headers, config) {
$scope.status = status;
});
with the $scope.url being locations.aspx/getData it loads the html page of the aspx page but doesn't access the method. I can access the method using
$.ajax({
type: "POST",
url: $scope.url,
data: {},
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (p) {
var temp = $.parseJSON(p.d);
$scope.allItems.push(temp);
},
error: function () {
alert('error');
}
});
but the data never updates or binds on the view side. An example on the html is
<select ng-model="selectLocation" id="selectLocation" ng-change="onLocationChange()">
<option></option>
<option ng-repeat="l in allItems">{{l.location}}</option>
</select>
After the ajax call allItems array does have an item in it but the view never updates.
My ajax call headers are
Request URL:localhost:41796/locations.aspx/getData
Request Method:POST
Status Code:200 OK
Request Headersview source
Accept:application/json, text/javascript, /; q=0.01
Content-Type:application/json; charset=utf-8
Response Headersview source
Cache-Control:private, max-age=0
Connection:Close
Content-Length:270
Content-Type:application/json; charset=utf-8
and my $http headers are
Request URL:localhost:41796/locations.aspx/getData
Request Method:GET
Status Code:200 OK
Request Headersview parsed
GET /locations.aspx/getData HTTP/1.1
Host: localhost:41796
Connection: keep-alive
Response Headersview parsed
HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 7177
Connection: Close
Based on the discussion above, it seems you're using ASP.NET and running into specific issues with it.
ASP.NET can be pretty picky sometimes about what it will parse and what it won't -- especially when it comes to MVC (which it doesn't appear that you're using here, but perhaps [WebMethod] (what I assume you're using) has the same kinds of issues).
Instead of messing with jQuery's $.ajax, you can use Angular's $http in the same way:
$http({
method: 'POST',
url: $scope.url,
contentType: 'application/json; charset=utf-8'
})
.success(function (data, status, headers, config) {
alert(data);
})
.error(function (data, status, headers, config) {
$scope.status = status;
});
Check this: http://docs.angularjs.org/api/ng.$http#Parameters for more information.