I've been stuck on this for a few hours with no luck, so I figured that I would ask here.
I have a service with a bunch of endpoints, most of which accept GET and POST http methods. In that case, my service simply specifies Access-Control-Allow-Origin to be * in the response headers, in the event that one of my apps is on a different domain/port and wants to use the service.
I have one endpoint that uses the DELETE http method, and I can't seem to get it to work. When I call this endpoint from my client app, I get this message in my console:
Response to preflight request doesn't pass access control check:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
I've been reading up on CORS for the past couple hours and have tried a few different things, all of which have not worked. I (think I) at least understand that when I'm using http methods other than GET and POST, the browser sends a pre-flighted request with OPTIONS as the http method.
What is the best way to handle this? Is there a way to disable this pre-flighted request? I specify in my client app that the http method to call this endpoint is DELETE. Should I be putting something specifying headers in my AJAX function that calls this endpoint (I'm using straight JavaScript)?
If I can't figure out a way around this, I'm just going to change my endpoint to use a GET or POST method, but I wanted to find a way to handle this issue before I took the easy way out.
I (think I) at least understand that when I'm using http methods other than GET and POST, the browser sends a pre-flighted request with OPTIONS as the http method.
Yes
Is there a way to disable this pre-flighted request?
No there isn’t. It’s initiated by browsers automatically, with no way to disable it from your JS. As long as you’re sending that DELETE request cross-origin in your JS, browsers will do that preflight.
Should I be putting something specifying headers in my AJAX function that calls this endpoint?
Given the “No 'Access-Control-Allow-Origin' header is present on the requested resource” message you’re getting, no changes you make in your client code will make any difference.
The place where more headers need to be sent to deal with this is instead on the server side.
If I can't figure out a way around this, I'm just going to change my endpoint to use a GET or POST method
You might want to experiment with trying that first. It seems even if you make that change you’re still gonna get that “No 'Access-Control-Allow-Origin' header is present on the requested resource”.
The SO question "No 'Access-Control-Allow-Origin' header is present on the requested resource" is a good place to read up on this to get a better idea of what’s happening.
Related
I'd like to accept and respond to JSON requests in Odoo from sources that may be out of my control. The reason this is not straightforward is because Odoo is forcing me to use JSON-RPC, which is not suitable for the source I'm interacting with.
For example, if I set the route type to http in the #http.route decorator, Odoo rejects the request if the mimetype is application/json but the body has no content. This isn't going to work in my case because I may not be able to choose what the other source sends to me. Additionally, I am unable to send back a custom JSON response unless the incoming request doesn't have the application/json mimetype, which again is not in my control.
I have done a lot of searching on the internet and read much of Odoo's HTTP source code. The "solution" I keep seeing everywhere is to monkey patch the JsonRequest class one way or another. This allows me to indeed respond with whatever I want, however it doesn't allow me to accept whatever the service may send me.
One specific case I need to be able to handle is incoming application/json GET requests with no body. How can I achieve this despite Odoo's heavy handed JSON-RPC handing?
There is no correct way to accomplish this, I'd call the described method acceptable. It applies to versions of Odoo 10 through 15.
In my opinion, it would be better to leave JsonRequest class alone and let it do its JSON-RPC related job. There is odoo.http.Root.get_request method which constructs the json-rpc or http request object, depending on the content type:
class Root(object):
"""Root WSGI application for the OpenERP Web Client.
"""
# ...
def get_request(self, httprequest):
# deduce type of request
if httprequest.mimetype in ("application/json", "application/json-rpc"):
return JsonRequest(httprequest)
else:
return HttpRequest(httprequest)
This point seems to be the most relevant one to be patched, with returning the custom request class object from this method. There is an issue, though - this method is called prior to any route detection. You have to invent a suitable method to tell, which request class object to return.
To have an idea about a possible implementation, please, see OCA base_rest module.
I'm having a following problem with camel http requests. I would want to preserve a value of url query string parameter without passing it to another http request that needs to be done on the route. The value is needed after the http request to external api to process the data. Below is a clarification of the problem:
rest("/api")//We get requests as /camel/api?param1=xyz...
.get()
.route()
.setHeader(Exchange.HTTP_METHOD, constant("GET"))
.setHeader("Accept-Encoding", constant("gzip"))
.setHeader("Accept", constant("*/*"))
.removeHeader(Exchange.HTTP_URI)//Remove this
//How do I prevent the {header.param1} from being passed to the following http request but still be able to use it after the request on the route?
.to("https://someapi.org/api/...")
//To process the result, we need the original {header.param1} value from the request to this /camel/api endpoint
.endRest();
What is the correct way to achieve this?
If you receive parameters that are only needed in the current route and should not be passed on to any other endpoints, you can also copy them over to Exchange properties and delete the headers.
In contrast to message headers, the Camel Exchange properties are not propagated to routings and they are removed together with the Exchange when the message reaches an end of the current route.
.setProperty("param1", header("param1")) // create property from header
.removeHeader("param1") // remove the header
This is a very explicit and transparent way to do this, but you have to do it everywhere you need it. So it is good for exceptional cases that you want to make explicit.
On the other hand a HeaderFilterStrategy prevents sending specific headers (based on patterns) to the endpoints you configure it. So it is very good for general header rules you want to apply to all endpoints of a specific type (for example to all HTTP endpoints).
Due to some decisions in the past, our custom proxy is unable to accept HEAD requests. Changing it to accept HEAD will be quite a lot of work. One approach was to use the code path used by GET when a HEAD request comes. But this would mean the response gets sent back as well. Is it ok to send back a response for a HEAD request? Or does it really depend on the upstream HTTP client? I feel the request body will anyway be ignored so shouldn't be a problem
I've been under the impression that Post in Rest means "Create".
But after reading up on the spec http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5
It seems like it can be more than just Create?
That was also stated by Stormpath in their screencasts on rest api design.
According to Stormpath, Post means "Process" , which can be pretty much anything.
Is that the correct way to see it?
I can trigger custom actions for my resources using Post?
In theory, a POST request should attempt to create or modify some resource on the server. As #Tichodroma pointed out, an idempotent request will affect this change only the first time it is sent, but otherwise what's important is that some state on the server will be changed by the request.
More practically. POST requests are often used when the request payload is too large to fit into a GET URI (e.g. a large file upload). This is usually an intentional breach of HTTP standards to avoid a 414 Request-URI Too Long response.
In terms of verbiage, I don't know if I like "process", because even a GET request will usually be "processed" to determine the resource to return. The main difference in my mind is the change of some state on the server.
I want to use cross-domain ajax, thus I had to use either JSONP, or use CORS. Due to technical problems I had, I chose to use CORS. Thus, I created a generic handler in the target website (say http://www.target.com/handler.ashx) and I sent ajax requests to that handler from http://www.source.com/.
However, browser didn't show anything and when I saw the HTTP Headers of the response, I didn't see any Access-Control-Allow-Origin header there.
What's wrong?