Apiato: Cors and Json request error

Created on 22 Sep 2016  Â·  7Comments  Â·  Source: apiato/apiato

When I try to request with an x-www-form-urlencoded content type, everything works fine

Request

Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate
Accept-Language:fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
Cache-Control:no-cache
Connection:keep-alive
Content-Length:49
Content-Type:application/x-www-form-urlencoded
Host:api.hello.local
Origin:http://hello.local
Pragma:no-cache
Referer:http://hello.local
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.92 Safari/537.36

Response

Access-Control-Allow-Origin:http://hello.local
Cache-Control:private, must-revalidate
Content-Language:en
Content-Type:application/json
Date:Thu, 22 Sep 2016 15:14:36 GMT
ETag:"e24a002b754612447c8be5660951f2296c685ca4"
Server:Apache
Set-Cookie:mediaplan=R3721135442; path=/; expires=Thu, 22-Sep-2016 16:28:31 GMT
Set-Cookie:mediaplanBAK=R129296274; path=/; expires=Thu, 22-Sep-2016 16:32:55 GMT
Set-Cookie:laravel_session=XXX---XXX; expires=Thu, 22-Sep-2016 17:14:36 GMT; Max-Age=7200; path=/; HttpOnly
Transfer-Encoding:chunked
Vary:Origin
X-Powered-By:PHP/7.0.8
X-RateLimit-Limit:100
X-RateLimit-Remaining:99
X-RateLimit-Reset:1474557576

But, when the same request uses an application/json content type, I have this response from server

Content-Encoding:gzip
Content-Length:185
Content-Type:text/html; charset=iso-8859-1
Date:Thu, 22 Sep 2016 15:15:40 GMT
Server:Apache
Set-Cookie:mediaplanBAK=R129294096; path=/; expires=Thu, 22-Sep-2016 16:26:16 GMT
Set-Cookie:mediaplan=R3721135442; path=/; expires=Thu, 22-Sep-2016 16:32:55 GMT
Vary:Accept-Encoding

There is no Access-Control-Allow-Origin header, so the js client doesn't handle the server response. Without CORS, everything is working fine (even with a JSON request). I can't figure why. Somebody has an idea ?

Bug Help

Most helpful comment

Hi, I have found a solution on this laravel-cros issue, adding the cors middleware globally fix the error. Now I have the CORS header even on error responses. I will send a pull request with the fix and adding some lines as suggested on laravel-cros docs to prevent future issues.

Looks related to "dingo/api", this package handles the errors responses without calling the render() method on the exception handler class, so we can't call laravel-cors to put the spected header when errors occurs.

All 7 comments

@nmrgt I have not tried Cors with this project yet. I advise you to check this repo. Probably you need to enable it in Hello API.

Can you show the request headers of the JSON encoded call ? How are you testing this?

Hi, I have a similar error, when I try to send a post request to login with invalid credentials, there is no Access-Control-Allow-Origin header:

$ curl -H "Origin: http://angular.dev" --verbose  http://api.hello.dev/user/login -k -d [email protected] -d password=wrong
*   Trying 192.168.10.10...
* Connected to api.hello.dev (192.168.10.10) port 80 (#0)
> POST /user/login HTTP/1.1
> Host: api.hello.dev
> User-Agent: Mozilla/5.0 Gecko
> Accept: */*
> Origin: http://angular.dev
> Content-Length: 35
> Content-Type: application/x-www-form-urlencoded
> 
* upload completely sent off: 35 out of 35 bytes
< HTTP/1.1 401 Unauthorized
< Server: nginx/1.11.5
< Content-Type: application/json
< Transfer-Encoding: chunked
< Connection: keep-alive
< Cache-Control: no-cache
< Date: Fri, 27 Jan 2017 03:28:57 GMT
< 
* Connection #0 to host api.hello.dev left intact
{"message":"Credentials Incorrect.","status_code":401}

If credentials are ok, the headers Access-Control-Allow-Origin is given:

$ curl -H "Origin: http://angular.dev" --verbose  http://api.hello.dev/user/login -k -d [email protected] -d password=admin
*   Trying 192.168.10.10...
* Connected to api.hello.dev (192.168.10.10) port 80 (#0)
> POST /user/login HTTP/1.1
> Host: api.hello.dev
> User-Agent: Mozilla/5.0 Gecko
> Accept: */*
> Origin: http://angular.dev
> Content-Length: 36
> Content-Type: application/x-www-form-urlencoded
> 
* upload completely sent off: 36 out of 36 bytes
< HTTP/1.1 200 OK
< Server: nginx/1.11.5
< Content-Type: application/json
< Transfer-Encoding: chunked
< Connection: keep-alive
< Cache-Control: private, must-revalidate
< X-RateLimit-Limit: 100
< X-RateLimit-Remaining: 98
< X-RateLimit-Reset: 1485488426
< Content-Language: en
< Access-Control-Allow-Origin: http://angular.dev
< Vary: Origin
< ETag: "07567eaa2149a92935097c33e091f88e75aebcb4"
< Date: Fri, 27 Jan 2017 03:35:36 GMT
< 
{"data":{...}}

This causes problems on javascript app handling the server errors, because we have no the response from server, we have this on browser console instead:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://api.hello.dev/user/login. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

Get and Post (with correctly data) request are ok, have no tested others methods. Sounds like the Access-Control-Allow-Origin header is no set serving errors, like validation errors in this case.

Hi, I am so frustrated with this bug... I have tried many things, but nothing works, except this:

In the Barryvdh\Cors\Stack\CorsService, line 92, write this:

return $response."";

And yes, we have the Access-Control-Allow-Origin again even when the server returns error messages, like validation, authentication, 500 status, etc...

Credentials Incorrect

$ curl -H "Origin: http://angular.dev" --verbose  http://api.hello.dev/user/login -k -d [email protected] -d password=
*   Trying 192.168.10.10...
* Connected to api.hello.dev (192.168.10.10) port 80 (#0)
> POST /user/login HTTP/1.1
> Host: api.hello.dev
> User-Agent: Mozilla/5.0 Gecko
> Accept: */*
> Origin: http://angular.dev
> Content-Length: 31
> Content-Type: application/x-www-form-urlencoded
> 
* upload completely sent off: 31 out of 31 bytes
< HTTP/1.1 200 OK
< Server: nginx/1.11.5
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Cache-Control: private, must-revalidate
< ETag: "2492947978b05524942766c9f6c7b934cb91ed86"
< Date: Fri, 27 Jan 2017 05:47:32 GMT
< 
HTTP/1.0 401 Unauthorized
Access-Control-Allow-Origin: http://angular.dev
Cache-Control:               no-cache
Content-Language:            en
Content-Type:                application/json
Vary:                        Origin
X-Ratelimit-Limit:           100
X-Ratelimit-Remaining:       99
X-Ratelimit-Reset:           1485496352

* Connection #0 to host api.hello.dev left intact
{"message":"Credentials Incorrect.","status_code":401}

No authorization headers

$ curl -H "Origin: http://angular.dev" --verbose  http://api.hello.dev/apps
*   Trying 192.168.10.10...
* Connected to api.hello.dev (192.168.10.10) port 80 (#0)
> GET /apps HTTP/1.1
> Host: api.hello.dev
> User-Agent: Mozilla/5.0 Gecko
> Accept: */*
> Origin: http://angular.dev
> 
< HTTP/1.1 200 OK
< Server: nginx/1.11.5
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Cache-Control: private, must-revalidate
< ETag: "b682ef6deea6fae72d713f5314e56610a0924d13"
< Date: Fri, 27 Jan 2017 05:48:57 GMT
< 
HTTP/1.0 401 Unauthorized
Access-Control-Allow-Origin: http://angular.dev
Cache-Control:               no-cache
Content-Language:            en
Content-Type:                application/json
Vary:                        Origin
X-Ratelimit-Limit:           100
X-Ratelimit-Remaining:       96
X-Ratelimit-Reset:           1485496180

* Connection #0 to host api.hello.dev left intact
{"message":"Failed to authenticate because of bad credentials or an invalid authorization header.","status_code":401}

Validation

$ curl -H "Origin: http://angular.dev" --verbose  http://api.hello.dev/user/login -k -d email=admin -d password=123
*   Trying 192.168.10.10...
* Connected to api.hello.dev (192.168.10.10) port 80 (#0)
> POST /user/login HTTP/1.1
> Host: api.hello.dev
> User-Agent: Mozilla/5.0 Gecko
> Accept: */*
> Origin: http://angular.dev
> Content-Length: 24
> Content-Type: application/x-www-form-urlencoded
> 
* upload completely sent off: 24 out of 24 bytes
< HTTP/1.1 200 OK
< Server: nginx/1.11.5
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Cache-Control: private, must-revalidate
< ETag: "69bf046130b61520871606276d3e616008909f17"
< Date: Fri, 27 Jan 2017 05:50:59 GMT
< 
HTTP/1.0 422 Unprocessable Entity
Access-Control-Allow-Origin: http://angular.dev
Cache-Control:               no-cache
Content-Language:            en
Content-Type:                application/json
Vary:                        Origin
X-Ratelimit-Limit:           100
X-Ratelimit-Remaining:       95
X-Ratelimit-Reset:           1485496352

* Connection #0 to host api.hello.dev left intact
{"message":"Invalid Input.","errors":{"email":["The email must be a valid email address."]},"status_code":422}

This way everything is ok on command line, but when testing this on the javascript app we have not the CORS header on GET or POST any more.

WTH!!

Hi, I have found a solution on this laravel-cros issue, adding the cors middleware globally fix the error. Now I have the CORS header even on error responses. I will send a pull request with the fix and adding some lines as suggested on laravel-cros docs to prevent future issues.

Looks related to "dingo/api", this package handles the errors responses without calling the render() method on the exception handler class, so we can't call laravel-cors to put the spected header when errors occurs.

@llstarscreamll thanks mate, glad you've solved it. I will merge your PR now. Have a good weekend :)

I followed your explanation for this issue and I continuo with this error:

Request Method:OPTIONS
Status Code:501 Not Implemented

But when I'm in the intranet works well...

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rogerapras picture rogerapras  Â·  5Comments

Mahmoudz picture Mahmoudz  Â·  6Comments

phuocnt0612 picture phuocnt0612  Â·  3Comments

kk86bioinfo picture kk86bioinfo  Â·  6Comments

vituocgia picture vituocgia  Â·  5Comments