can't send PUT to Philips Hue (same origin policy) - javascript

I'm trying to send a PUT-request to a Philips Hue bridge, so I can change the current state in which the lamp is. I do this from a webserver on my PC. With CORS I already managed to send GET and POST- request, but if I send a PUT I get an error that tells "method not found in Access-Control-Allow-Methods". I'm pretty sure that would make no sense to block just that method.
I'm using that code to do so, it is the same as the code for GET and POST, just the if clause is not needed.
var lightReq = new XMLHttpRequest();
if ("withCredentials" in lightReq) {
lightReq.open('PUT',stringChange,true);
if (value == false) {
lightReq.send("{\"on\":true}");
}
else {
lightReq.send("{\"on\":false}");
}
}
Maybe someone had a similar problem and got a solution, or there are steps I should check. I'm glad for every help.
EDIT:
Here is a screenshot of the header, it shows that the PUT-method should be accepted.
EDIT2:
For roryhewitt here is what you asked for, i think:
Best Regards,
Adrian

It looks from your screenshot as if that's the response to a POST request (I'm looing at the Anfragemethode field)?
Most of those CORS response headers (except ACAC) should only be returned in the response to a preflight OPTIONS request - they have no 'meaning' if they are returned in the response to any other request. That's the 'fault' of the bridge, though, not of anything you're doing in the browser code.
Anyway, when your JS code makes a PUT request via XMLHttpRequest, if you look at the network traffic from your browser, you should see an OPTIONS requests (CORS preflight) followed by your PUT request. If you only see the OPTIONS request, can you provide the response headers for that request?

Related

POST Request Not Recognizing Headers

I am trying to make a POST request to an AWS Lambda Python Script I have set up.
I have already heard about solving the issue of Access-Control-Allow-Origin by adding a header to the Response from AWS lambda, that looks like Access-Control-Allow-Origin:*, and I implemented this in the code I was working on for the get request. Then when I begun creating a POST request, I did the same thing, so that the new POST request originally looked like this:
def post(event, context):
try:
return dict(
statusCode=200,
headers= {'Access-Control-Allow-Origin': "*"},
body="test"
)
except Exception as ex:
return dict(
statusCode=500,
body=str(ex)
)
And this works, in Chrome's Network-Tab I see that we pass a post request and there is no issue, and the header is recognized properly, allowing Cross-Origin calls. But this is pretty much just the GET request I have which is already set up and working. So when I update it to be more similar to a POST METHOD and do what I want the problems begin.
So my code, that I want to be performed in the POST request is simple, I should be able to make the request like such,
def post(event, context):
try:
result=str(event.get("inputOne") + event.get("inputTwo"))
return dict(
statusCode=200,
headers= {'Access-Control-Allow-Origin': "*"},
body=result
)
except Exception as ex:
return dict(
statusCode=500,
body=str(ex)
)
When I test this in the AWS Lambda Management console, my code works, and I get the expected response back in the body.
But then when I try and call the POST endpoint from my React Site, I once again am getting the error:
Access to XMLHttpRequest at 'THE_POST_URL' from origin
'http://localhost:XXX' has been blocked by CORS policy: No 'Access-
Control-Allow-Origin' header is present on the requested resource.
So for some reason, when the body variable is not just a simple string in quotes like "this" <- it fails. I believe this has to do with the Content-Type in the request being of the form application/json;charset=UTF-8 while my request only accepts (as it says in dev-tools) application/json however even when trying to add the headers to accept this format for content-type, I am still getting the same issues.
I am not entirely sure why the header worked on the GET request, but not the POST request, and would appreciate anyone being able to help teach me, thank you!
EDIT: I have also tried adding 'Access-Control-Allow-Methods': "OPTIONS,GET,POST" to the headers of the post response, but this did not work either.
So after reading through the comments on my question, I decided it was worth going and taking a harder look at the way I had my API Gateway, and Lambda service set up on AWS.
I began using the curl utility in order to try and test my post-call from a terminal utility and found that there it was also failing, but I was able to use CloudWatch to debug, the issue and finally get it working.
The problem that I was facing with my curl Request was that I was not properly formatting the JSON input, but even when I was the Lambda was transforming the event improperly, not resulting in a Dict, as expected.
The curl call I was using can be seen:
curl -X POST https://myURL.execute-api.myREGION.amazonaws.com/stage/yourPOST \
-d '{"inputOne":80000,"inputTwo":85}'
But in order to read that input properly, and then work with it, I had to update my code in the Lambda to reflect parsing the input properly, this updated lambda code can be found here. The event object that you are passing to this lambda is a DICT object, so on the first line, we use JSON.loads to decode the "body" value of the event, into a dict that we store as body. Then to get the value of the two attributes, we use the command body.get("yourKey").
def yourPOST(event, context):
body=json.loads(event["body"])
a=body.get("inputOne")
c=body.get("inputTwo")
After making these changes the call from my React site works without error! If anyone has any questions feel free to comment, I hope this helped!

React to 303 status code in jquery ( Prevent from redirecting)

when I send requests to a certain server, a 303 response will come, followed by the requested response in combination with a 200 status code.
Funny thing is that I only see this on my developer console's network view. When checking the statuscode and response of my $.ajax() request, there will be the response of the second request, as well as a 200 http status code.
The problem is that it seems that the second request is being cached (though 200 status code), and I really need it to be non-cachable.
Therefore I'd really like to intervene into the forwarding process that occurs with a http 303 status code. I'd like my jquery function to check for the status code, then send the get request with explicit headers, that tell the server not to cache the response.
Well, I just don't know how to do this, since (as mentioned above) the jQuery.ajax method will respond with the forwarded request's response and status code (200).
Can you help me?
edit
10.3.4 303 See Other
The response to the request can be found under a different URI and
SHOULD be retrieved using a GET method on that resource. This method
exists primarily to allow the output of a POST-activated script to
redirect the user agent to a selected resource. The new URI is not a
substitute reference for the originally requested resource. The 303
response MUST NOT be cached, but the response to the second
(redirected) request might be cacheable.
maybe I need to somehow prevent the user agent from redirecting himself, so I can do the redirect?
Or is there a way to simply tell the server/browser not to cache the second request from client-side? or to prevent it from redirecting my request? or at least modify the second request before redirecting?
Responses in the 300 range are meant to be transparent. AFAIK, web browsers don't expose any of them to javascript. Thus, handling the 303 is not an option.
Have you tried setting the cache property to false in the ajaxSetup? It will append a timestamp to the request, preventing the browser from caching the response. You can also do that manually yourself. The browser should match the first request url to the 2nd response
You cannot stop the browser from following the 303 redirect. It sounds like that's not what you want, anyway. Whatever you would do in the browser to prevent the original request from being cached should work equally well for preventing the redirected 200 from being cached. That said, there is little you can do on the browser side other than using a unique URL for each request. This is done for you automatically by jQuery when you set cache: false.
$.ajax({
url: "example.html",
cache: false
}
}).done(function( html ) {
$("#results").append(html);
});
This is old post, but maybe someone will find this useful.
I have the same issue, and in my case the problem was in the method that was called out using the ajax. The problem was in the redirection that was set in the method. So, based on this, you can't use both ajax and redirect(server side), and i removed redirect() function from method, i everything works as expected.
Btw, i am using codeigniter.
See statusCode property of your .ajax() call
Example :
$.ajax({
statusCode: {
303: function() {
alert("page not found");
}
}
});

I can see a API response in browser but not with Ajax, why?

I have an api from the backend, if I visit the url in browser directly, I can see the response correctly, but if I load it with Ajax, I always get a 502 Bad Gateway error.
The page and the api are in the same domain: http://xx.com and http://xx.com/api.
This is really weird, how could it happen?
Update: I explored it a little further and found that even var img = new Image(); img.src = url; get a 502 error.
As this page helpfully explains, "the upstream server and the gateway/proxy do not agree on the protocol for exchanging data." This could happen, in this case, because your Ajax request specifies different headers (such as a different "Accept" header), leading to a different entity type (i.e., body) being exchanged between your proxy and your actual back-end. I would advise using a tool like Firebug or the Chrome debugger to examine the details of your regular request and your Ajax request, look for significant differences, and add headers to your Ajax request as needed to get the desired result.

How to get error details from xmlhttprequest?

I'm trying to get some more information about why my request failed. It goes through the standard phases (I can see receiving headers (state 2) for a while). Then it notifies about readyState=4, status=0 and no statusText set.
How can I get some more information about what happened and why?
If this is a simple website AJAX request you can use Firebug to look at all the parameters, it will not tell you what happens in code but can help you maybe figure out what is wrong with the post/get request to the server, this way maybe this is an issue with the back-end or a bug in the request uri or parameters
And in general it is a useful tool to have which is free

Submit cross domain ajax POST request

I swear I saw an article about this at one point but can not find it...
How can I perform a jQuery ajax request of type POST on another domain? Must be accomplished without a proxy. Is this possible?
Yes you can POST all you want, even $.post() works...but you won't get a response back.
This works, the other domain will get the POST:
$.post("http://othersite.com/somePage.php", { thing: "value" }, function(data) {
//data will always be null
});
But the response, data in the above example, will be null due to the same-origin policy.
All the options I've experimented with:
1) PORK: http://www.schizofreend.nl/Pork.Iframe/Examples/ Creates an iframe and submits the post there, then reads the response. Still requires same base domain per
request (i.e. www.foo.com can request
data from www2.foo.com, but not from
www.google.com) . Also requires you to
fiddle with the document.domain
property, which causes adverse side
effects. And there's a pervasive problem in all the major browsers where reloading the page basically shuffles the cached contents of all iframes on the page if any of them are dynamically written. Your response data will show up in the box where an ad is supposed to be.
2) flxhr: http://flxhr.flensed.com/ Can even be used to mask jQuery's built-in ajax so you don't even notice it. Requires flash though, so iPhone is out
3) jsonp: Doesn't work if you're posting a lot of data. boo.
4) chunked jsonp: When your jsonp request is too big, break the query string up into manageable chunks and send multiple get requests. Reconstruct them on the server. This is helpful but breaks down if you're load balancing users between servers.
5) CORS: http://www.w3.org/TR/cors/ doesn't work in older browsers (IE7, IE6, Firefox 2, etc)
So we currently do the following algorithm:
If request is small enough, use JSONP
If not small enough, but user has flash, use FlXHR
Else use chunked JSONP
Spend one afternoon writing that up and you'll be able to use it for good. Adding CORS to our algorithm might be good for faster iPhone support.
If you have control over the code running at the other domain, just let it return an appropriate Access-Control-Allow-Origin header in the response. See also HTTP Access-Control at MDC.
If you want a fire and forget POST where you don't care about the response then just submit a form to a hidden iframe. This requires a Transitional Doctype.
<form method="POST" action="http://example.com/" target="name_of_iframe">
If you want to parse the response, then using a proxy if the only real option.
If you are desperate, and control the remote site, then you can:
Submit a form as above
Set a cookie in the response (which might be blocked before the iframe could cause the cookie to be considered '3rd party' (i.e. likely to be advertising tracking).
Wait long enough for the response to come back
Dynamically generate a script element with the src pointing to the remote site
Use JSON-P in the response and take advantage of the data previously stored in the cookie
This approach is subject to race conditions and generally ugly. Proxing the data through the current domain is a much better approach.
If you need to know that the POST was successful, and don't have control over the remote server:
$.ajax({
type:"POST",
url:"http://www.somesite.com/submit",
data:'firstname=test&lastname=person&email=test#test.com',
complete: function(response){
if(response.status == 0 && response.statusText == "success")
{
/* CORS POST was successful */
}
else
{
/* Show error message */
}
}
});
If there was a problem with the submission then response.statusText should equal "error".
Note: some remote servers will send the HTTP header Access-Control-Allow-Origin: *, which will result in a 200 OK HTTP status code response. In that case, ajax will execute the success handler, and this method is not needed. To look at the response just do console.log(JSON.stringify(response)); or use FireBug's 'Net' panel.

Categories