GoogleCloudPlatform / functions-framework-dart

FaaS (Function as a service) framework for writing portable Dart functions
https://pub.dev/packages/functions_framework
Apache License 2.0
538 stars 54 forks source link

CORS support #222

Open subfuzion opened 3 years ago

subfuzion commented 3 years ago

If a request comes from a script running under a different origin (for our purposes here, a tuple that includes a host and port) from the origin that is hosting a function app, the request will fail due to lack of cross-origin resource sharing (CORS protocol) support.

For background, browsers restrict cross-origin HTTP requests initiated from scripts for security purposes, so if a browser runs, for example, a Flutter app loaded from a different origin than the origin hosting, for example, a Dart function app, the request will fail if the function app doesn't support CORS.

As part of supporting CORS, a function app must be able to handle the CORS preflight, which is sent as an HTTP OPTIONS request.

What would be useful for this situation is to add CORS support to the framework that would allow specifying a CORS policy, possible as metadata annotation or as an API, for setting a policy. For inspiration, see the Node.js cors package.

References:

subfuzion commented 3 years ago

This is not a spec right now, but just a brainstorming comment.

Initial support could be to handle a CORS request for no support and for wildcard support.

Following that, we could extend support for specific origins. As long as we ensure the framework responds to the client with an Access-Control-Allow-Origin that returns the origin exactly as supplied by the client in the preflight request, we can design the CORS support on the framework side to enhance the basic spec with at least basic globbing support, if not full regex support, to handle at least the following case:

When the client sends an Origin request header (scheme "://" host [ ":" port ]), the port will generally be auto-selected by the browser. On the server side, the spec only supports a specific integer value, if supplied. We want to make it easy to handle requests from a particular origin on any port, with support for globbing or regexes, etc.

Kleak commented 3 years ago

I provide a cors middleware in my self_helpers but something like cors from ktor could be really great.

We can probably improve my API but for those who want something basic it can do it, just add the middleware :)

Would be happy to participate to improving this.

djildo commented 3 years ago

Hello, not being able to use CORS as middleware, the expected is a List Args, any tips?

djildo commented 3 years ago

Hello, not being able to use CORS as middleware, the expected is a List Args, any tips?

djildo commented 3 years ago

Hello, not being able to use CORS as middleware, the expected is a List Args, any tips?

mtwichel commented 3 years ago

I provide a cors middleware in my self_helpers but something like cors from ktor could be really great.

We can probably improve my API but for those who want something basic it can do it, just add the middleware :)

Would be happy to participate to improving this.

I think adding middleware support could be really cool. I brought up some ideas how to do it in this comment. That way we could handle cors but also verify authentication tokens, initialize api clients, ect.

Kleak commented 3 years ago

I provide a cors middleware in my self_helpers but something like cors from ktor could be really great.

We can probably improve my API but for those who want something basic it can do it, just add the middleware :)

Would be happy to participate to improving this.

I think adding middleware support could be really cool. I brought up some ideas how to do it in this comment. That way we could handle cors but also verify authentication tokens, initialize api clients, ect.

In fact you don't need to change the API. If you use Pipeline.addMiddleware will do the same no ? Or is this more to initialize things before hand

jpeiffer commented 2 years ago

I created this PR: https://github.com/GoogleCloudPlatform/functions-framework-dart/pull/317

With it is an example of using shelf_cors_headers now applied to the fullstack/backend.

I'm hoping the simplicity of this change will allow it to avoid the fate of https://github.com/GoogleCloudPlatform/functions-framework-dart/pull/250.

jpeiffer commented 2 years ago

I think it's fair to assume my hopes have been crushed...

mtwichel commented 2 years ago

Haha I really recommend checking out dart_frog if you want to do more complicated stuff with Dart on the server and want a framework to simplify the shelf stuff. It's pretty clear that at least for now, Google wants this project to be super simple and easy to use (which I understand).

jimmyff commented 2 years ago

Here is my little solution/shim using the shelf_cors_headers package:

I'm using the middleware in the lib/functions.dart file like so:


// lib/functions.dart

@CloudFunction()
Future<Response> function(Request request) async {
  var handler = const Pipeline()
      .addMiddleware(corsHeaders(
          // Allow specific headers expected by my app
          headers: {'Access-Control-Allow-Headers': 'Token, Content-Type'},
          // Check origin against a list of my client domains
          originChecker: (origin) {
            return const [
              'https://mydomain.com',
              'https://example.mydomain.com',
              'https://myfirebaseapp.web.app',
              'https://myfirebaseapp.firebaseapp.com',
            ].contains(origin);
          }))
      .addHandler(corsFunction);
  return handler(request);
}

Future<Response> corsFunction(Request request) async {
  // main cloud function body...
}

The corsHeaders arguments are optional and this is just how I have it configured for my specific app.