nitrictech / dart-sdk

Dart integration for Nitric.
https://nitric.io
Apache License 2.0
5 stars 4 forks source link

Middleware seems to work differently on Dart vs. Node #34

Closed chimon2000 closed 3 months ago

chimon2000 commented 3 months ago

Bug Report

Issue

It seems like middleware works differently depending on the SDK used. When using the Node version, I can add a middleware to enable cors for the entire API like so:

import { HttpMiddleware } from '@nitric/sdk'

export const corsMiddleware: HttpMiddleware = (ctx, next) => {
  ctx.res.headers['Access-Control-Allow-Origin'] = ['*']
  ctx.res.headers['Access-Control-Allow-Headers'] = [
    'Origin, Content-Type, Accept, Authorization',
  ]
  ctx.res.headers['Access-Control-Allow-Methods'] = ['GET,POST,DELETE,OPTIONS']

  return next(ctx)
}

If I apply that same version in Dart, the middleware fails to work as expected.

import 'package:nitric_sdk/nitric.dart';

final HttpHandler corsMiddleware = (ctx) {
  ctx.res.headers['Access-Control-Allow-Origin'] = ['*'];
  ctx.res.headers['Access-Control-Allow-Headers'] = [
    'Origin, Content-Type, Accept, Authorization',
  ];
  ctx.res.headers['Access-Control-Allow-Methods'] = ['GET,POST,DELETE,OPTIONS'];

  return ctx.next();
};

Steps

Steps to reproduce the behavior:

  1. Use the above middleware in a Dart project
  2. Observe requests being blocked
  3. Use middleware in Node project
  4. Observe requests succeeding

Expected

The middleware should function the same regardless of the environment.

Environment and setup information

N/A

Other info

N/A

davemooreuws commented 3 months ago

Hi @chimon2000 ,

I cannot reproduce this with the code below on nitric start or deployed to AWS, nothing is blocked for me. Can you try with the example code below?

I am using: Dart SDK version: 1.4.0 Nitric CLI: v1.50.6

import 'package:nitric_sdk/nitric.dart';

Future<HttpContext> corsMiddleware(HttpContext ctx) {
  ctx.res.headers['Access-Control-Allow-Origin'] = ['*'];
  ctx.res.headers['Access-Control-Allow-Headers'] = [
    'Origin, Content-Type, Accept, Authorization',
  ];
  ctx.res.headers['Access-Control-Allow-Methods'] = ['GET,POST,DELETE,OPTIONS'];

  return ctx.next();
}

void main() {
  final helloApi = Nitric.api("main",
      opts: ApiOptions(middlewares: List.from([corsMiddleware])));

  helloApi.get("/hello/:name", (ctx) async {
    final name = ctx.req.pathParams["name"]!;

    ctx.res.body = "Hello $name";

    return ctx.next();
  });
}
chimon2000 commented 3 months ago

@davemooreuws I was able to narrow down the error. It occurs when I add the authorization header. Here's a very small example:

https://github.com/chimon2000/nitric_middleware

davemooreuws commented 3 months ago

@davemooreuws I was able to narrow down the error. It occurs when I add the authorization header. Here's a very small example:

https://github.com/chimon2000/nitric_middleware

Thanks for the example @chimon2000 , I'll take a look.

davemooreuws commented 3 months ago

Hi @chimon2000,

This is simply the way CORs works with an Authorization header. It requires a successful "preflight request". Like so:

api.options("/hello/:name", (ctx) async {
    return ctx.next();
});

My forked repo with the changes: https://github.com/davemooreuws/nitric_middleware

More information on CORs: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests

We do have an open feature request for CORs helpers: https://github.com/nitrictech/nitric/issues/520#issuecomment-2292511984 This would avoid you needing to handle the preflight requests manually.

davemooreuws commented 3 months ago

Closing, middleware checked for both node and dart. No issues.