I'm writing a vue app to post data using axios to an API powered by laravel. The APIhas a POST route which is to create a resource. I have CORS set up which allows successful GET'ing of the data. However when I try to POST the data, the network tab shows an OPTIONS request being made with nothing being returned and no POST request follows.
Using axios: a POST request is made with: axios.post(url);
but no POST request is actually made, only the OPTIONS request with: axios.post(url,data).
I made a simple api with slim and didn't have similar problems, so I'm assuming this is something laravel specific?
There are no server log errors, the laravel log shows no errors neither. The error in the browser console is: Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://api/api/zones/save. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
UPDATE
These are the headers that are sent as the request:
Host: apiurl
User-Agent: ....
Accept: text/html,application/xhtml+xm…plication/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
Origin:null
DNT: 1
Connection: keep-alive
I understand about the pre-flight but the API I made with slim passed the pre-flight using the same axios code and the post request was made. I'm not sure why the laravel API isn't doing so.
UPDATE 2
These are the headers for the OPTIONS response
Server nginx/1.10.3 (Ubuntu)
Content-Type text/html; charset=UTF-8
Transfer-Encoding chunked
Connection keep-alive
Allow GET,HEAD,POST
Cache-Control no-cache, private
Date Fri, 03 Nov 2017 20:46:47 GMT
Content-Encoding gzip
and this is the code I'm using for the laravel middleware:
public function handle($request, Closure $next)
{
return $next($request)
->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
->header('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization')
;
}
}
I'm including this code in the Kernel under the 'api' key
Related
I posted earlier this post right here
The problem is that when i send my requests after login on my ionic app a have the token stored and I use it to send other request that needs authentication these request has the header like this:
Accept: application/json
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI.....
Content-Type: application/json
Origin: http://localhost:8100
Referer: http://localhost:8100/
An after 3 days of search I figured out the request headers are being ignored by Apache and all requests arrives without token so i get this message error as response from all API routes:
{"message": "Unauthenticated"}
I send a POST Ajax request to a Laravel Controller but I get a 302 Found response code.
The controller is the ForgotPasswordController provided by Laravel's Auth package, so nothing special about it.
It has the guest middleware in its constructor and I found that if I remove this middleware from the constructor, the Ajax request works correctly (it returns a 200 response code).
The Ajax request has the X-CSRF-TOKEN and X-XSRF-TOKEN headers, so I don't think there is something missing.
I'm sending this Ajax request from a VueJS password reset form with the Axios library.
Why my POST request does not work if the controller has the guest middleware ?
Here are the headers sent with the request :
POST /password/email HTTP/1.1
Host: myapp.dev
Connection: keep-alive
Content-Length: 37
Pragma: no-cache
Cache-Control: no-cache
Origin: http://myapp.dev
X-XSRF-TOKEN: eyJpdiI6IjRqTk1yTXFsXC9FVlRzckF0dUM4azdRPT0iLCJ2YWx1ZSI6IjY0MUZzaEpCTXJDcUhzUGhcL2dzYVJmalQrR3pwV3IzYWxiTSt4dVwvN2VVKzJ4b2t3XC9GcVhJcllmK3pQYVV4VGFIZG4wZ0s3NlNCTG01WEl6YzBCY2NRPT0iLCJtYWMiOiIwYmNjOTRiZGJjZTM2YjYyMWJiMzRhNTlkOTkwOWU4Y2M4NmYzYzI5NjhiMTU4MDdiMGJkMmJhYmMwODEzMDhjIn0=
X-CSRF-TOKEN: nejsetydvFWgeqppZc5XQtX04b5AdXlsTKSgaydj
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36
Content-Type: application/json;charset=UTF-8
Accept: application/json, text/plain, */*
X-Requested-With: XMLHttpRequest
Referer: http://myapp.dev/password
Accept-Encoding: gzip, deflate
Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: XSRF-TOKEN=eyJpdiI6IjRqTk1yTXFsXC9FVlRzckF0dUM4azdRPT0iLCJ2YWx1ZSI6IjY0MUZzaEpCTXJDcUhzUGhcL2dzYVJmalQrR3pwV3IzYWxiTSt4dVwvN2VVKzJ4b2t3XC9GcVhJcllmK3pQYVV4VGFIZG4wZ0s3NlNCTG01WEl6YzBCY2NRPT0iLCJtYWMiOiIwYmNjOTRiZGJjZTM2YjYyMWJiMzRhNTlkOTkwOWU4Y2M4NmYzYzI5NjhiMTU4MDdiMGJkMmJhYmMwODEzMDhjIn0%3D; laravel_session=eyJpdiI6IkJnczRHV3NcLzhLbzZWaUlvTTI2cFlBPT0iLCJ2YWx1ZSI6IkpQYytLXC9pQ1R3MTZlaEx2QWJ4bGpSd21BV25jelJKVDJkQVdcL25GSG4rQkpQc1duZHIrTjErOGt3bk5BVVVcL3FTK1c2XC83Y1NqTmxBaVZ1bkQ2TWV5Zz09IiwibWFjIjoiNzg4Y2UyNWQ0ODcxMWNkNWE3MmU4ZDY1MmIyNTE0NDgwMzFmM2ZjYzkxMzM5ZGM5ZTk5MDI4NjE4OGRkNmJjYyJ9
Ok i found... it's just that I was authenticated when doing these requests. So the guest middleware was redirecting me... shame on me !
302 response usually because your request is redirected by laravel. if you expect json response don't forget to add Accept: 'application/json' on your header request then you will see what actually wrong
You have to look closer into your controller. You have to return json. Also take a look in the network console in the browser. If response code is 302 there is a location. So if a location is the login page - validation not passed in the middleware
I'm developing some site aaa.com with django, which sends cross-domain ajax "GET" requests to receive json data from bbb.com which is also running on django and is using REST framework. At this point everything works pretty fine with adding crossDomain: true; withCredentials:true. And of course its configurated on server-side of aaa.com.
...-Allow-Credentials: true;
...-Allow-Origin: bbb.com
The main issue comes when aaa.com is trying to make PUT POST DELETE ajax requests.
According to CORS documentation:
[https://www.w3.org/TR/cors/#cross-origin-request-with-preflight-0], client side ajax request is correct, and
...-Allow-Headers, ...-Allow-Methods
is matched with
...-Request-Headers, ...-Request-Methods
so this request is not 'simple' and first of all browser sends preflight request from aaa.com to bbb.com to ask if some custom headers and methods are allowed.
Everything is OK But I'm still getting 403 Error. Here is the request/response:
General:
Request URL:http://bbb.com/api/someapipage/
Request Method:OPTIONS
Status Code:403 Forbidden
Remote Address:some ip:80
Response Headers:
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:accept, content-type, x-csrftoken, x-requested-with
Access-Control-Allow-Methods:GET, POST, OPTIONS, HEAD, PUT, DELETE
Access-Control-Allow-Origin:http://aaa.com
Allow:GET, POST, HEAD, OPTIONS
Connection:Keep-Alive
Content-Language:en
Content-Type:application/json
Date:Mon, 04 Jul 2016 14:20:38 GMT
Keep-Alive:timeout=5, max=100
Server:gunicorn/19.6.0
Transfer-Encoding:chunked
Vary:Accept,Accept-Language,Cookie
X-Frame-Options:SAMEORIGIN
Request Headers:
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8,ru;q=0.6
Access-Control-Request-Headers:accept, content-type, x-csrftoken
Access-Control-Request-Method:POST
Connection:keep-alive
Host:aaa.com
Origin:http://aaa.com
Referer:http://aaa.com/
User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36
After week of tries to fix this issue I realised that server wants to Vary: Cookie on pre-flighted request which is impossible because cross-domain pre-flight request cannot contain cookie in its header.
I started finding some solution to this issue and found:
https://code.djangoproject.com/ticket/13217
"Enabling django.middleware.locale.LocaleMiddleware causes that django adds a 'Vary: Cookie' header to every reponse."
So localMiddleware adds header Vary: Cookie even in pre-flight OPTIONS response
There are lots of reccomendations to use djang-cors-header to fix some of this problems. But using this package function are equal to my settings on server-side.
I have also found pretty package: django-dont-vary-on which if installed can set decorators to turn off Vary:cookie, but in my case i need to turn off Vary:cookie only in OPTIONS response.
Im bit new to django and actually cannot even imagine what to do in this situation. Every my step is just like walking on a mine field.
Is there any solution or some alternatives?
You have to CORS whitelist your client to access the server.
In case their is a Cross-domain request, the request becomes preflighted if you use methods other than GET, HEAD or POST.
Also, if POST is used to send request data with a Content-Type other
than application/x-www-form-urlencoded, multipart/form-data, or
text/plain, it becomes preflighted.
Its the server that allows the cross-domain client request to be processed or deny it (default).
So if you have access to the server-side application, you could do the following to get the response.
On server-side
Install django-cors-headers on your server side and white list your client domain or IP (it is also port specific)
pip install django-cors-headers
In settings.py, add it in your INSTALLED_APPS
INSTALLED_APPS = (
...
'corsheaders',
...
)
Add the corsheaders.middleware.CorsMiddleware in MIDDLEWARE_CLASSES
MIDDLEWARE_CLASSES = (
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'**corsheaders.middleware.CorsMiddleware**',
'django.middleware.common.CommonMiddleware',
....
)
and define a CORS whitelist
CORS_ORIGIN_WHITELIST = (
'aaa.com',
)
Now as you have added your client in the CORS whitelist, you will now be able to make a successful ajax request.
As I know that if cors request comes with some extra headers set, first server needs to process it.
With CORS, the server must send the Access-Control-Allow-Headers header to allow uncommon request headers from the client.
Access-Control-Allow-Headers ... - Comma-delimited list of the supported request headers.
e.g suppose my pre-flight request is
OPTIONS /cors HTTP/1.1
Origin: http://api.bob.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
Then from server-side I will send response
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Content-Type: text/html; charset=utf-8
My question is -
should I close the connection on server side while we send pre-flight response to client?
One more thing how can I cached pre-flight request for all other distinct subsequent requests?
Thanks
You could cache the OPTIONS request using the
Access-Control-Max-Age
header.
Attach it to the headers collection of the OPTIONS response.
But nevertheless an initial OPTIONS request by the user agent (browser) has to be made, you cannot avoid this.
But all further OPTIONS requests are cached and not issued to the server.
No need to close the connection.
Access-Control-Allow-Origin: http://hello-world.example
Access-Control-Max-Age: 3628800
Access-Control-Allow-Methods: PUT
as explained here, search for
could have the following headers specified
to get to the designated text section.
I have been encountering error in storing a file to Object Storage using HTTP POST method sent using Async XMLHttpRequest. The request is a CORS HTTP request sent to the Object storage public URL with required headers set. The error message says: Reason: CORS header Access-Control-Allow-Origin missing.
The error seems to happen with multipart form data send request using POST. If PUT is used to create the file, the required file (resource) gets created. The response to the PUT request contains the required Access-Control-Allow-Origin header, whereas the response to POST does not contain despite the meta data attributes being set on the container.
I have even tried using X_AUTH_TOKEN header instead of X_STORAGE_TOKEN, but the failure continues to happen.
Raised the ticket with Softlayer support, but have not received a solution. Any ideas to resolve the above would be helpful.
The details are below:
The container prod_file has following meta data attributes set:
access-control-expose-headers: Access-Control-Allow-Origin
access-control-allow-origin : *
The Firefox browser version is: Mozilla Firefox 46.0
Client OS is: Linux 3.16.0-71-generic #91~14.04.1-Ubuntu SMP Mon Apr 18 1K9:43:36 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
Request URL: https://*****.objectstorage.softlayer.net/v1/AUTH_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/prod_file/6ffb51fc-e40f-4cf5-982c-44cb5c342851.fl.file.orig.txt
Request HTTP Method: POST
Mechanism used: Async XMLHttpRequest
Request Headers:
Host: *****.objectstorage.softlayer.net
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:46.0) Gecko/20100101 Firefox/46.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
X-Storage-Token: AUTH_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Referer: http://*****myorg******.com/organization/572680760cf26af856c7432c/resources
Content-Length: 4500
Content-Type: multipart/form-data; boundary=---------------------------2139255891192408661525197545
Origin: http://*****myorg******.com
Connection: keep-alive
Response Headers:
Connection: keep-alive
Content-Length: 50
Content-Type: text/plain
Date: Sat, 14 May 2016 14:57:02 GMT
X-Trans-Id: *****Some Transaction Id********
The error response has the following message:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://*****.objectstorage.softlayer.net/v1/AUTH_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/prod_file/6ffb51fc-e40f-4cf5-982c-44cb5c342851.fl.file.orig.txt. (Reason: CORS header 'Access-Control-Allow-Origin' missing)
Thanks for the help in advance.
It looks like you set wrong the headers for your container, please take a look this documentation and try it:
http://docs.openstack.org/developer/swift/cors.html
https://swiftstack.com/blog/2013/04/02/using-cors-with-swift/
Renember that softlayer object storage is based in Open Stack.
Let me know if you are still having troubles
Regards