Closed ivanvujisic closed 10 years ago
What kind of error are you getting with setting ZfrCors ? Can you show me your ZfrCors config?
Sure np, but my question is - isn't it simplier with those three header lines above?
config/application.config.php
<?php
/**
* Configuration file generated by ZF Apigility Admin
*
* The previous config file has been stored in application.config.old
*/
return array(
'modules' => array(
'Application',
'ZF\\DevelopmentMode',
'ZF\\Apigility',
'ZF\\Apigility\\Provider',
'ZF\\Apigility\\Documentation',
'AssetManager',
'ZF\\ApiProblem',
'ZF\\Configuration',
'ZF\\MvcAuth',
'ZF\\OAuth2',
'ZF\\Hal',
'ZF\\ContentNegotiation',
'ZF\\ContentValidation',
'ZF\\Rest',
'ZF\\Rpc',
'ZF\\Versioning',
'nuagetel',
'ZfrCors'
),
'module_listener_options' => array(
'module_paths' => array(
'./module',
'./vendor'
),
'config_glob_paths' => array(
'config/autoload/{,*.}{global,local}.php'
)
)
);
Apache error_log
[Thu Jun 26 00:48:11 2014] [error] [client 212.178.238.122] PHP Fatal error: Uncaught exception 'Zend\\ModuleManager\\Exception\\RuntimeException' with message 'Module (ZfrCors) could not be initialized.' in /var/www/html/api-zf2-02/apigility/vendor/zendframework/zendframework/library/Zend/ModuleManager/ModuleManager.php:189\nStack trace:\n#0 /var/www/html/api-zf2-02/apigility/vendor/zendframework/zendframework/library/Zend/ModuleManager/ModuleManager.php(163): Zend\\ModuleManager\\ModuleManager->loadModuleByName(Object(Zend\\ModuleManager\\ModuleEvent))\n#1 /var/www/html/api-zf2-02/apigility/vendor/zendframework/zendframework/library/Zend/ModuleManager/ModuleManager.php(90): Zend\\ModuleManager\\ModuleManager->loadModule('ZfrCors')\n#2 [internal function]: Zend\\ModuleManager\\ModuleManager->onLoadModules(Object(Zend\\ModuleManager\\ModuleEvent))\n#3 /var/www/html/api-zf2-02/apigility/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php(468): call_user_func(Array, Object(Zend\\ModuleManager\\ModuleEvent))\n#4 /var/www/html/api-zf2-02/apigility/vendor/zendframework/zendframework/l in /var/www/html/api-zf2-02/apigility/vendor/zendframework/zendframework/library/Zend/ModuleManager/ModuleManager.php on line 189
Did you copy-paste the .dist file? Please read the installation part: https://github.com/zf-fr/zfr-cors#installation
Yes, I put
<?php
/**
* This is the config file for ZfrCors. Just drop this file into your config/autoload folder (don't
* forget to remove the .dist extension from the file), and configure it as you want
*/
return array(
'zfr_cors' => array(
/**
* Set the list of allowed origins domain with protocol.
*/
'allowed_origins' => array('*'),
/**
* Set the list of HTTP verbs.
*/
'allowed_methods' => array('GET', 'POST', 'PATCH', 'PUT', 'DELETE', 'OPTIONS'),
/**
* Set the list of headers. This is returned in the preflight request to indicate
* which HTTP headers can be used when making the actual request
*/
'allowed_headers' => array('Authorization'),
/**
* Set the max age of the preflight request in seconds. A non-zero max age means
* that the preflight will be cached during this amount of time
*/
// 'max_age' => 120,
/**
* Set the list of exposed headers. This is a whitelist that authorize the browser
* to access to some headers using the getResponseHeader() JavaScript method. Please
* note that this feature is buggy and some browsers do not implement it correctly
*/
// 'exposed_headers' => array(),
/**
* Standard CORS requests do not send or set any cookies by default. For this to work,
* the client must set the XMLHttpRequest's "withCredentials" property to "true". For
* this to work, you must set this option to true so that the server can serve
* the proper response header.
*/
// 'allowed_credentials' => false,
),
);
in the config/autoload/zfr_cors.global.php
sorry, it is:
'allowed_origins' => array('*'),
Strange. It does not seem to be an issue of ZfrCors logic, but it just does not seem to initialize it. I'm not sure to understand why :/. Did you check that the configuration got properly loaded (for instance by dumping the 'Config' object from the service locator, and check if the ZfrCors config is present)?
I appreciate your effort to help, but my initial question was -> it "seems" to me I resolved CORS issue with Apigility using three simple PHP header commands (confirmed by AngularJS front end developer).
Would you be so kind to comment on this, is it security issue?
OK, I made progress, zfr-cors wasn't installed due to proc_open disabled in my php.ini So, uncaught php runtime exception is gone, say zfr-cors is installed properly.
Now I put:
'allowed_origins' => array('www.example.com'),
in the zfr_cors.global.php but api query still works. Any clue?
There is to be an exact match of origins. So for instance, in CORS, http://www.example.com is different than https://www.example.com, for instance. Try to add the exact origin that performs calls to your API.
If you're unsure, try to see a request made in your browser, and check thje "Origin" header in the request, and copy-paste this value into your config :).
Mate, I put
'allowed_origins' => array('http://www.ronaldmcdonald.com'),
but it still works properly, and I'm sure ZfrCors is loaded properly since there's no error trace in the error_log
Ok, just stupid thing (sorry, trying to find the obvious...): did you remove your hack from index.php as it had a wildcard ?
Yup, those two are separate ZF2 Apigility installations.
Hhmmm.
Can you please open the inspector (Safari, Chrome), and make a screenshot of the API request, along with the request and response headers?
API queries are triggered from AngularJS app, so I can't inspect from web browser, right?
Yes you can :). In Chrome all requests that are done asynchronously are logged in the inspector. In Safari, you have to open the section with a timer, and click on the grey circle on the left so that it listens to all AJAX requests.
I was also having issues with zfrCors (more specifically this: https://github.com/zf-fr/zfr-cors/issues/14 and this: https://github.com/zf-fr/zfr-cors/issues/18) so I decided to set the CORS headers manually and disable zfrCors, since I don't need any advanced CORS functionality.
I ended up with a solution where I get the Response object in a module bootstrap and set the headers using that, which I think is a better way than calling the header function directly in index.php.
So I added the following method to a Module.php
file:
public function onBootstrap(MvcEvent $event)
{
// Set CORS headers to allow all requests
$headers = $event->getResponse()->getHeaders();
$headers->addHeaderLine('Access-Control-Allow-Origin: *');
$headers->addHeaderLine('Access-Control-Allow-Methods: PUT, GET, POST, PATCH, DELETE, OPTIONS');
$headers->addHeaderLine('Access-Control-Allow-Headers: Authorization, Origin, X-Requested-With, Content-Type, Accept');
}
Hi,
Actually, I've myself ended up NOT using ZfrCors. The problem is that you need to have the overhead of the whole application bootstrapping just to send headers.
A much better solution is actually to handle that on Apache side (although it offers you less flexibility, but for most cases, this is enough). Here is my VirtualHost for instance:
<VirtualHost *:80>
ServerName default
ServerAlias *
DocumentRoot "/var/www/html/public"
# First, let's handle CORS requests
SetEnvIfNoCase Access-Control-Request-Method "(GET|POST|PUT|DELETE|OPTIONS)" IsPreflight=1
SetEnvIfNoCase Origin "https://(url1.com|url2.com)$" AccessControlAllowOrigin=$0
Header always set Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
Header always set Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" env=IsPreflight
Header always set Access-Control-Allow-Headers "Content-Type, Authorization, Accept" env=IsPreflight
Header always set Access-Control-Max-Age "7200" env=IsPreflight
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteCond %{ENV:IsPreflight} 1
RewriteRule ^(.*)$ $1 [R=200,L]
<Directory "/var/www/html/public">
DirectoryIndex index.php
AllowOverride All
Order allow,deny
Allow from all
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]
</Directory>
</VirtualHost>
OK, I get stuck with zfr-cors installation, so I get mad and put this:
header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS'); header('Access-Control-Allow-Headers: Authorization, WWW-Authenticate, Origin, X-Requested-With, Content-Type, Accept');
in Apigility /public/index.php, above this line:
Zend\Mvc\Application::init($appConfig)->run();
So, it "seems" to me I resolved CORS issue with Apigility (confirmed by AngularJS front end developer), but I'm sure you guys have some comments on this.
Thanks.