framework-one / fw1

FW/1 - Framework One - is a lightweight, convention over configuration, MVC application framework for ColdFusion / CFML.
http://framework-one.github.io
Other
374 stars 141 forks source link

fw1 4.2 (CORS policy problem) #529

Open asimakos opened 3 years ago

asimakos commented 3 years ago

Hello! I intend to use fw1 4.2 for json ajax requests along with Framework7. Unfortunately i came across CORS policy problem by using ONLY two distinct json ajax requests (POST and GET) as route paths in Application.cfc. Soon i intend to add much more json route paths GET, POST, PUT and DELETE for other services. I attach the code (fw1 and Framework7) for better convenience (https://we.tl/t-JXCwYD8x9v).

Regards

error_1

error_3

matthewjones commented 3 years ago

Are you sure what you are asking for isn't already available? have you enabled preflightoptions and setup routes?
It would enable options and attempt to auto create the access control, allowing you to override. It will use the defined routes to indicate which methods are allowed.

https://framework-one.github.io/documentation/4.2/developing-applications/#options-support

asimakos commented 3 years ago

I have already discussed all these matters (https://bit.ly/3qw0i1M).

Regards

tonyjunkes commented 3 years ago

First,

As an aside to anyone else who has followed along with this, I had helped the author of this issue with a previous issue that was created in relation. I have also provided some assistance via email to gain access to an example application. I do not believe there is any issue with how FW/1 handles HTTP methods and request/response calls with CORS involved. It is less about the framework and more about how the code in the app using the framework.

@asimakos,

You might be receiving an unexpected error in your FW/1 application that is not being handled correctly. Because of this, the response does not have the expected header(s), in this case Access-Control-Allow-Origin, resulting in the CORS error. The reason is unknown without seeing logs from the FW/1 application, full responses/requests from the console, etc.

I tried running the example application you provided via email, but it is expecting a database to be set up. On top of that, the GET route that you mention did not appear to be accessible for me to test because of the previous requirement mentioned. When providing a way to reproduce an issue, please make it as simple as you can; with as few requirements as possible. Putting together an example application that demonstrates only the issue will help with finding a solution.

I removed the database specific logic and was able to set up the JavaScript to call the route on the index page. When I had the controller return just the rc scope variable, everything worked, and I was able to see the expected response without any CORS errors. But, because there are parts that I could not include in the replication, it's difficult to say what the issue could have been. I strongly suggest reviewing your controller and how it is using your user service to make sure everything works as expected. Review the logs for any errors in the FW/1 app. Your framework settings look ok and your response from the controller method is sending the expected header as long as there are no exceptions occurring.

In future situations, I highly recommend joining the CFML Slack group and checking out the FW/1 channel for asking questions when you run into issues with your FW/1 applications. It can prove to be more effective in receiving help/feedback from multiple people, including myself. From there we can better define if it merits an issue being created here to look into possible bugs or simply how the framework handles something.

asimakos commented 3 years ago

Fortunately the error has to do ONLY with passing the right parameter value type from Controller to the Service. All the code in my service function is correct, but unfortunately i have not figured out correctly the parameter value type to be passed and thus got CORS policy error (not at all user friendly message)!

I also logged in CFML Slack group (#Fw1) and all these messages are visible there too, but unfortunately no one replied all these days except @tonyjunkes who i owe him a big thank you. By the way just today they suggested me to use chrome plugin Allow CORS: Access-Control-Allow-Origin, perhaps i might use it in a different situation.

Regards

tonyjunkes commented 3 years ago

Happy to help. Unfortunately, It's difficult to narrow down the issue without a working example I can reproduce. The app you provided shows the error happening, but there are parts that I do not have set up that are causing it instead.

The Chrome plugin may help with bypassing the CORS error, but it will not help a user who uses this app in the future or if the plugin is off. It certainly could help with development and maybe shed light on any other issues that may not have been noticed. When I have some more time I will take another look.

cfmitrah commented 3 years ago

Seems like condition in https://github.com/framework-one/fw1/blob/develop/framework/one.cfc#L873-L875 never get satisfied

      if ( variables.framework.preflightOptions &&
            request._fw1.cgiRequestMethod == "OPTIONS" &&
             structCount( request._fw1.routeMethodsMatched ) ) {

Try to check something like

if ( variables.framework.preflightOptions 
            // &&
            //  request._fw1.cgiRequestMethod == "OPTIONS" &&
            //  structCount( request._fw1.routeMethodsMatched ) 
             ) {
            // OPTIONS support enabled and at least one possible match
            // bypass all normal controllers and render headers and data:
            var resp = getPageContext().getResponse();

            resp.setHeader( "Actual-http-method", request._fw1.cgiRequestMethod );
            resp.setHeader( "Actual-routeMethodsMatched-strcut", serializeJSON(request._fw1.routeMethodsMatched) );

            resp.setHeader( "Access-Control-Allow-Origin", variables.framework.optionsAccessControl.origin );
            resp.setHeader( "Access-Control-Allow-Methods", "OPTIONS," & uCase( structKeyList( request._fw1.routeMethodsMatched ) ) );
            resp.setHeader( "Access-Control-Allow-Headers", variables.framework.optionsAccessControl.headers );
            resp.setHeader( "Access-Control-Allow-Credentials", variables.framework.optionsAccessControl.credentials ? "true" : "false" );
            resp.setHeader( "Access-Control-Max-Age", "#variables.framework.optionsAccessControl.maxAge#" );
            renderData( "text", "" );
        }

image

For me, request._fw1.routeMethodsMatched is always empty & request._fw1.cgiRequestMethod is whatever http method used in the xhr request, never it has value as "OPTIONS"

tonyjunkes commented 3 years ago

Do you have a working example you can provide showing the issue? I'm not following where this relates to the original post issue. They needed to provide a working example that anyone could run and reproduce. When I removed the database driven code, everything worked as expected. That suggests there is an issue with their service somewhere and not FW/1.

cfmitrah commented 3 years ago

Start using commandbox, then you have to run this URL http://abcd.localhost:8500/test.html to get cors issue. CF server setup with rest.localhost:8500

rest_cors_bug.zip

tonyjunkes commented 3 years ago

@cfmitrah Thanks! When I get a chance, I'll have a look.