Laravel Api Request Firing Twice on Production Server - php

Im using Ionic as my apps development and laravel as the server. I recently moved my laravel project from localhost to production VPS Server. At localhost, my API requests are fine. But when i moved the project to VPS Server, the request firing twice at one time.
What i've done =
Re-Upload the project from localhost to vps server (including database)
Re-Upload the project using git.
Cleared route, view, cache, config (laravel cache)
But nothing change, the problem still occur.
{\"data\":[{\"id\":53,\"name\":\"Rumah\",\"user_id\":2,\"receipent\":\"John Doe\",\"receipent_phone\":\"62812345678\",\"address\":\"Los Angeles\",\"district\":\"Bengkong, Batam, Kepulauan Riau\",\"district_id\":5}]}"}}
[2020-07-10 20:59:01] local.INFO: app.requests {"request":[],"method":"DELETE","response":{"Illuminate\\Http\\JsonResponse":"HTTP/1.1 200 OK
Access-Control-Allow-Headers: X-Requested-With, Content-Type, X-Token-Auth, Authorization
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin: *
Cache-Control: no-cache, private
Content-Type: application/json
Date: Fri, 10 Jul 2020 13:59:01 GMT
X-Ratelimit-Limit: 120
X-Ratelimit-Remaining: 115
{\"message\":\"Sukses menghapus data\"}"}}
[2020-07-10 20:59:01] local.INFO: app.requests {"request":[],"method":"DELETE","response":{"Illuminate\\Http\\JsonResponse":"HTTP/1.1 404 Not Found
Access-Control-Allow-Headers: X-Requested-With, Content-Type, X-Token-Auth, Authorization
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin: *
Cache-Control: no-cache, private
Content-Type: application/json
Date: Fri, 10 Jul 2020 13:59:01 GMT
X-Ratelimit-Limit: 120
X-Ratelimit-Remaining: 114
{\"message\":\"No data\"}"}}
Above are the Logging details from my laravel project about the API incoming request on VPS server. You can see the request Time are the same. But, when im using Postman, the request is normal, like when i'm using localhost I'm new to this. any help would be appreciated, Thank you.

Related

CORS Headers are altered in the browser resulting in content becoming blocked

Update 2 (A complete set of logs)
From Client's Perspective
Request headers:
POST /dev/micro_server.php HTTP/1.1
Host: production-server.com
Connection: keep-alive
Content-Length: 86
Pragma: no-cache
Cache-Control: no-cache
Accept: text/html, /; q=0.01
Origin: https://debug.dev
User-Agent: Mozilla/5.0 (X11; Linux x86_64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98
Safari/537.36 OPR/58.0.3135.90
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: https://debug.dev/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: debugger_session=iq4tbdk374mtvodsd3edcf2jq5
Response headers:
HTTP/1.1 200 OK
Server: nginx/1.4.6 (Ubuntu)
Date: Tue, 12 Mar 2019 12:01:27 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
X-Powered-By: PHP/5.5.9-1ubuntu4.17
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Origin: https://production-server.com
Access-Control-Allow-Credentials: true
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Encoding: gzip
Console Error:
Access to XMLHttpRequest at 'https://production-server.com/dev/micro_server.php' from origin 'https://debug.dev' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header has a value 'https://production-server.com' that is not equal to the supplied origin.
Console Warning:
Cross-Origin Read Blocking (CORB) blocked cross-origin response https://daikai.no/dev/micro_server.php with MIME type text/html. See https://www.chromestatus.com/feature/5629709824032768 for more details.
From Server's Perspective
This is what the server says it has received and sent (check the code that does the logging in update 1):
Array
(
[req] => Array
(
...
[HTTP_ORIGIN] => https://debug.dev
...
)
[rsp] => Array
(
[0] => X-Powered-By: PHP/5.5.9-1ubuntu4.17
[1] => Access-Control-Allow-Origin: https://debug.dev
[2] => Access-Control-Allow-Methods: GET, POST, OPTIONS
[3] => Access-Control-Allow-Credentials: true
)
)
Update
I have added some logging on the server and the script now begins with these lines:
# allow access from other domains
header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']);
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
header("Access-Control-Allow-Credentials: true");
$all = [
'req' => $_SERVER,
'rsp' => headers_list()
];
$s = print_r($all, true);
$p = '/var/www/path/to/file_' . uniqid() . '.txt';
file_put_contents($p, $s);
With this I can confirm that the request arrives on the server with the correct Origin, AND the server sends back the correct CORS headers. Yet, the Access-Control-Allow-Origin in the developer console is wrong and the request is blocked.
Here is a stripped down log obtained with the code above:
Array
(
[req] => Array
(
...
[HTTP_ORIGIN] => https://debug.dev
...
)
[rsp] => Array
(
[0] => X-Powered-By: PHP/5.5.9-1ubuntu4.17
[1] => Access-Control-Allow-Origin: https://debug.dev
[2] => Access-Control-Allow-Methods: GET, POST, OPTIONS
[3] => Access-Control-Allow-Credentials: true
)
)
Question
How and why does the Access-Control-Allow-Origin is changed to https://production.com when the actual header received is Access-Control-Allow-Origin: https://debug.dev?
(Original Post)
Background
I have a web-based debug tool that I have installed on my local development machine. With an entry in my /etc/hosts I have assigned to it the domain debug.dev. I have also added a local CA authority and have successfully created a SSL certificate for the domain name so now I can open https://debug.dev/ in my browser and the debug tool opens normally.
This tool is supposed to work with staging and production servers. So it needs to send AJAX requests to other domains. I have full control over those servers and I am sending back CORS headers from those servers like so:
header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']);
header("Access-Control-Allow-Credentials: true");
The Issue
Now I am facing a baffling situation in which when I send an AJAX request to the production server I get back Wrong CORS headers with the SERVER's domain like this:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://production-server.com
But if I right click and use Open in new tab the CORS headers are what they ought to be; i.e.
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://debug.dev
The only differences between the requests as far as I can see is that the first one is sent as an AJAX POST request and thus sends a HTTP_X_REQUESTED_WITH header whereas the second request is sent as an ordinary GET request. How could this result in a different CORS header be returned by the server?
The issue could be similar as my answer here:
The server is not configured to respond to OPTIONS requests with the correct "Access-Control-Allow-" headers.
Opening the url in a new Tab is a GET request and is working because it is not making a preflight request, as it meets the criteria to be a simple request as defined by the CORS documentation
On the other hand, the ajax request is a POST request and meets the criteria to be a Preflighted request, meaning a preflight OPTIONS request should be made first.
In short, you have correctly setup the CORS response headers, but the server is not configured to add these headers for OPTIONS method requests.
The solution is to handle OPTIONS requests on the server code with a 2xx response and add the **Access-Control-Allow- as you do for GET and POST requests. Keep in mind that OPTIONS requests do not include any parameters, so this should be done before any validation or request parsing.
Moreover, according to Access-Control-Allow-Origin documentation:
If the server specifies a single origin rather than the "*" wildcard, then the server should also include Origin in the Vary response header — to indicate to clients that server responses will differ based on the value of the Origin request header.
So set the Vary response header also:
eg at the top of you script try:
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']);
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
header("Access-Control-Allow-Credentials: true");
header("Vary: Origin");
exit;
}
References
Preflighted requests
response for preflight 403 forbidden
The problem is that you use header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']); (BTW: not very recommended) and you get the wrong header. I bet on one of the reasons:
The web server overwrites the headers.
The browser uses cache, although it should not. (BFC).
You did not upload the updated code to the requesting server.
Let's start from the end.
Do not believe herself, verify. (Not once did I look, we do not work, and then came the reflection that I did not upload changes :) ).
Turn off the cache in the browser debugger. (you must have open debugger) If this is a problem and the function is to be available in the pool, add timestamp to the request.
Check the configuration of nginx / apache / server panel
Are you aware that the construction used by you is synonymous with Access-Control-Allow-Origin: *? You should check HTTP_ORIGIN if it belongs to the allowed pool.

CORS AJAX-request fails even though the correct headers are specified

I am trying to send an AJAX-request from a page hosted on Github Pages (with https) to a php script hosted on a different domain (also https).
This is the code I am using in my AngularJS controller (although I don't think that is the problem):
$http.get('//thorin.epizy.com/cors.php?url=Place%2FGetClosestPlacesExtension%3Fcoordinates%3Dx%3D'+Math.round(vm.coords[0])+'%2Cy%3D'+Math.round(vm.coords[1])+'%26proposals%3D12').success(function (data) {
vm.success = true;
console.log('Recieved data from Ruter:',data);
});
The request fails and gives this error in the console:
When opening the Network panel in Chrome I see that the CORS headers are not present:
However, when I visit the page directly in the browser (typing the url into the url field) and open the Network panel all the correct headers are present:
I have tried sending the request from pages on other domains as well, bu I get the same error and no CORS headers. This makes very little sense to me and I have no idea how to fix it. I would really appreciate any help.
For a strange reason, thorin.epizy.com/cors.php doesn't send CORS headers without cookies:
curl -I 'http://thorin.epizy.com/cors.php?[...]' <other headers>
Date: Sun, 04 Dec 2016 16:42:57 GMT
Content-Type: text/html
Content-Length: 920
Connection: keep-alive
Vary: Accept-Encoding
Expires: Thu, 01 Jan 1970 00:00:01 GMT
Cache-Control: no-cache
With cookies, we get the correct headers:
curl -I -H 'Cookie: __test=b142b58439ba4f78e04c32cd1ba0a991' 'http://thorin.epizy.com/cors.php?[...]' <other headers>
HTTP/1.1 200 OK
Server: nginx
Date: Sun, 04 Dec 2016 16:45:04 GMT
Content-Type: application/json;charset=utf-8
Connection: keep-alive
Vary: Accept-Encoding
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
Access-Control-Allow-Methods: GET, POST, PUT, OPTIONS
Cache-Control: max-age=0
Expires: Sun, 04 Dec 2016 16:45:04 GMT
When you do a cross site request and want cookies, you need to ask for them with withCredentials (withCredentials: true with angularjs).
Then, the server will need to change two things:
add Access-Control-Allow-Credentials: true in the response
change Access-Control-Allow-Origin: * to Access-Control-Allow-Origin: your-web-site.com (usually taken from the Origin request header)
If you don't you will get the following message:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at ‘http://thorin.epizy.com/cors.php?url=[...]’. (Reason: Credential is not supported if the CORS header ‘Access-Control-Allow-Origin’ is ‘*’).

Internet Explorer/Edge randomly displaying response headers with 200 OK and compressed (?) data instead of HTML

I'm the sole developer building a LAMP web application for a small infancy-stage startup and have been crying myself to sleep over a bug that only occurs when using the web app in Internet Explorer 10-11 and Edge (Chrome, FF, and Opera work like a charm). Worse yet, it happens randomly and about 50% of the time after a user has authenticated and logged into the web app. Here's a screenshot:
Here's what shows up in the DOM Explorer when inspecting:
15447HTTP/1.1 200 OK
Date: Wed, 17 Aug 2016 09:27:27 GMT
Server: Apache/2.4.12 (Ubuntu)
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 4972
Keep-Alive: timeout=15, max=97
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8
‹í]ëvÛ¶²þÝ<ʶGöÙÖÅò-±-u9²8©/µ¤mVVDBlŠdJ²Òößy’ýo¿Æy”ó$gðŠÔ
l÷ê^‹j‹¸|33`$}zݹÿùæ
‚¡Ý~vý!Øj?Cð:’CnàUÉç·ÓuâÕ`ê…O-# OAW?BæûŒ­w÷çÕ熊壠—d4°IûÄSæú/©õÿóÏãºLTêz¾ë?˜¶
º.ö­9IËS2ñ\?PŠO¨ZS“TÅâ
(¶«ÌÄ6imóÚÿSõÝIµã=ÐnŠ‰‹³±ú$‡<
®¯Í)ÓwݾMªŒ¤:&>íQ(¸ŽRë`ûm÷Ç;ëf·7ö¼ó÷¿ü8=øùËã®Îß¿ï¼ß}8MN'ýæ¥ê!
Ë`ÁÔ&l#ˆ‚÷^Øi&cø¤}ËXÝqý!¶éRãš ÒíÙã¡K­Š(TáÂëõˆ‡Õ¤ø°GYÍt‡ìûR{Úºöˆó;ì
k·Ñ¨6*ÉF%b£2Ër…A÷æ(#:£2P§Ã~Ývûn
R+\à²Ú×Õ*úÁÅz%xB'¶§5ªVCdfúÔäB½‘cò¾Þ [lËÝêoù[xk¸ùýX‘1Äu÷˜AåSË?¢ýO-þÏï¿Çõ7!
~ÿýã§Íš7bƒ
<more garbled text>
As one can see from the response headers, the server returned a status of 200, and there are no errors or warnings in the console. Under the 'Network' tab, everything appears to have returned with either 200 or 302, with the exception of a couple 404s when retrieving profile pictures from the LinkedIn REST API (the pics still show up though in the other 50% of the time that the page actually displays properly...). On the server side, there is nothing in the Apache error log, and syslog is clean. The actual content appears to be compressed, which shouldn't be a problem given that the server is specifying the content encoding as gzip. Either that, or I'm looking at encrypted content.
I'm running Apache 2.4.12 on Ubuntu 15.10. Content is (of course) served over HTTPS, and the cert doesn't expire for another year. The application is written in PHP, and this happens on both the staging and production servers. I've scoured SO, Serverfault, and Google for a similar problem but haven't been successful. If anyone has encountered this error before or has any possible idea as to what's going on, any help would be greatly appreciated.

CORS slim framework. Angular request to apache not working

I have a chorme plugin that allows me to toggle CORS by inserting a header. If I use that my slim code works. If not then I get an error as follows.
(index):1 XMLHttpRequest cannot load
http://localhost/api/flowers. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:9000' is therefore not allowed
access.
My code
$app = new \Slim\Slim();
$app->response->headers->set('Content-Type', 'application/json');
$app->response->header('Access-Control-Allow-Headers',>
'Content-Type');
$app->response->header('Access-Control-Allow-Methods', 'GET, PUT,
POST, DELETE');
$app->response->header('Access-Control-Allow-Origin','*');
$app->get('/', function() use($app){
$ins = new Lead();
$products = $ins->run();
echo
json_encode($products);
});
If I use the crome extension then the header response from the server is as follows.
HTTP/1.1 200 OK Date: Wed, 16 Dec 2015 23:04:26 GMT Server:
Apache/2.4.7 (Ubuntu) X-Powered-By: PHP/5.5.9-1ubuntu4.14
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Methods: GET, PUT, POST, DELETE
Access-Control-Allow-Origin: * Keep-Alive: timeout=5, max=100
Connection: Keep-Alive Transfer-Encoding: chunked Content-Type:
application/json
So the headers are being sent. But CORS still does not work without the extension. I need to fix this for all browsers of course. Not just mine. I'm pretty sure its a small mistake but I'm not seing it. What's wrong here?
Your system needs to handle "options" routes.
Browsers use an OPTIONS request at the same URL. So essentially you need to handle 2 requests.
If you add in a $app->options("/:name+"); it should fix it.

laravel handling the OPTION http method request

I am developing an angularjs app which uses laravel as its back end server.
I am having trouble accessing data from laravel since before each GET request, angular first sends an OPTION request as below.
OPTIONS /61028/index.php/api/categories HTTP/1.1
Host: localhost
Connection: keep-alive
Cache-Control: max-age=0
Access-Control-Request-Method: GET
Origin: http://localhost:3501
Access-Control-Request-Headers: origin, x-requested-with, accept
Accept: */*
Referer: http://localhost:3501/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: UTF-8,*;q=0.5
I have tried to respond this by adding the following code in the before filter
if (Request::getMethod() == "OPTIONS") {
$headers = array(
'Access-Control-Allow-Origin' => '*',
'Access-Control-Allow-Methods' => 'POST, GET, OPTIONS, PUT, DELETE',
'Access-Control-Allow-Headers' => 'X-Requested-With, content-type'
);
return Response::make('', 200, $headers);
}
This creates a response with the headers:
Content-Encoding: gzip
X-Powered-By: PHP/5.3.5-1ubuntu7.11
Connection: Keep-Alive
Content-Length: 20
Keep-Alive: timeout=15, max=97
Server: Apache/2.2.17 (Ubuntu)
Vary: Accept-Encoding
access-control-allow-methods: POST, GET, OPTIONS, PUT, DELETE
Content-Type: text/html; charset=UTF-8
access-control-allow-origin: *
cache-control: no-cache
access-control-allow-headers: X-Requested-With, content-type
Although the headers are set, the browser still throws an error
XMLHttpRequest cannot load http://localhost/61028/index.php/api/categories. Origin http://localhost:3501 is not allowed by Access-Control-Allow-Origin.
I have also tried setting the allow origin to the origin presented in the request header as below
$origin=Request::header('origin');
//then within the headers
'Access-Control-Allow-Origin' =>' '.$origin[0],
and still the same error
What am i doing wrong? Any help is greatly appreciated.
Edit 1
I am currently using a very ugly hack where i over-ride laravels initialization when an OPTIONS request is received. This i have done in the index.php
<?php
if ($_SERVER['REQUEST_METHOD']=='OPTIONS') {
header('Access-Control-Allow-Origin : *');
header('Access-Control-Allow-Methods : POST, GET, OPTIONS, PUT, DELETE');
header('Access-Control-Allow-Headers : X-Requested-With, content-type');
}else{
/**
* Laravel - A PHP Framework For Web Artisans
*
* #package Laravel
* #version 3.2.13
* #author Taylor Otwell <taylorotwell#gmail.com>
* #link http://laravel.com
*/
I also had to add the allow-origin header to the before filter.
I know this is not smart but it is my only solution for now
This is with reference to your question regarding the above issue. You did not mention the version of laravel and angularJS. I assume you are using lattest angularJS and Laravel. I also assume, the angular is hosted on http://localhost:3501 and the laravel is hosted on http://localhost
Just follow the below steps.
Put below code block in /public/.htaccess file of laravel
Header set Access-Control-Allow-Origin "http://localhost:3501"
Header set Access-Control-Allow-Methods "GET,POST,PUT,DELETE,OPTIONS"
Header set Access-Control-Allow-Credentials "true"
Put below line in config of angular
$httpProvider.defaults.withCredentials = true;
Never use * as wild card character. Larvel can not identify the domain for session management. So set http://localhost:3501 as full domain name to Access-Control-Allow-Origin.
I think these will help you.
It's a bug in Laravel that got recently fixed. You may want to update to the latest revision.
Also, you need to enable CORS support for your server.
add this in your index.php file
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token');

Categories