connectrpc / connect-es

The TypeScript implementation of Connect: Protobuf RPC that works.
https://connectrpc.com/
Apache License 2.0
1.38k stars 80 forks source link

Content-Type and other HTTP headers missing with gRPC requests when launching in Cypress E2E Test #1010

Open robertwenquan opened 9 months ago

robertwenquan commented 9 months ago

Describe the bug

As clearly as you can, please tell us what the bug is.

In the Cypress E2E (end to end) test, the Content-Type header is missing(not attached) to the request when launched with the Cypress when the client is making the transport as transport = createConnectTransport

However, in the normal browser case, everything works fine. The Content-Type HTTP header could be observed when it's launched in a regular Chrome browser.

The workaround is to switch the transport to transport = createGrpcWebTransport, the problem is gone.

To Reproduce

If you encountered an error message, please copy and paste it verbatim. If the bug is specific to an RPC or payload, please provide a reduced example.

The business logic part of the code is simplied to this


/* external dependencies */
import { createPromiseClient } from "@connectrpc/connect";
import { createConnectTransport } from "@connectrpc/connect-web";
import type { PromiseClient } from "@connectrpc/connect";

/* local dependencies */
import { UserService } from "./api/user/v1/service_connect";
import { SigninRequest } from "./api/user/v1/service_pb";

// createApp(App).use(router).mount('#app')

const client: PromiseClient<typeof UserService> = createPromiseClient(
    UserService,
    createConnectTransport({
      baseUrl: "https://service.company.com:443",
    })
);

async function signin(email = "", password = "") {

    const request = new SigninRequest({email, password})
    console.log(request);

    if (client) {
        try {
            const response = await client.signin(request)
            console.log(response);
        } catch(error: any) {
            // gRPC errors will be caught here
            console.error('gRPC Error code:', error.code);
            console.error('gRPC Error:', error.message);
        }
    }
}

await signin("a.b@c.com", "sfsdf");

This is what's expected, when launched from a regular browser

image

This is what happened within Cypress run. With the same request, but missing a few HTTP headers. Specifically, the Content-Type header is missing when it's launched in Cypress.

image

Environment (please complete the following information):

If your problem is specific to bundling, please also provide the following information:



**Additional context**
Add any other context about the problem here.

An issue https://github.com/cypress-io/cypress/issues/28849 was reported on the cypress side as well.
srikrsna-buf commented 9 months ago

Thank you for opening the issue on both repos. The code for headers is pretty much identical between the two transports except for the contents of the headers. I don't see any fetch overrides in the sample snippet, just to be sure you are not overriding the fetch function, right?

One odd thing from the cypress screenshot is that it is receiving the headers and is trying to stringify the function properties of the Headers type, notice the FoEach, Entries and others. I am leaning towards this issue being in cypress, lets wait for them to get back.

yordis commented 5 months ago

I switched the client, and still failing,

--- a/packages/zitadel-node/src/index.ts
+++ b/packages/zitadel-node/src/index.ts
@@ -1,8 +1,9 @@
 import { NewAuthorizationBearerInterceptor } from "@zitadel/client2";
-import {
-  createGrpcWebTransport,
-  GrpcTransportOptions,
-} from "@connectrpc/connect-node";
+// import {
+//   createGrpcWebTransport,
+//   GrpcTransportOptions,
+// } from "@connectrpc/connect-node";
+import { createGrpcWebTransport, GrpcWebTransportOptions } from "@connectrpc/connect-web";
 import { importPKCS8, SignJWT } from "jose";

 /**
@@ -12,7 +13,7 @@ import { importPKCS8, SignJWT } from "jose";
  */
 export function createServerTransport(
   token: string,
-  opts: GrpcTransportOptions,
+  opts: GrpcWebTransportOptions,
 ) {
   return createGrpcWebTransport({
     ...opts,
[test]  ⨯ ConnectError: [unknown] fetch failed
[test]     at async Page (loginname/page.tsx:30:27)
[test] digest: "1552443515"
[test] Cause: TypeError: fetch failed
[test]     at node:internal/deps/undici/undici:12345:11
[test]     at async next (webpack-internal:///(rsc)/../../node_modules/.pnpm/@connectrpc+connect-web@1.4.0_@bufbuild+protobuf@1.9.0_@connectrpc+connect@1.4.0_@bufbuild+protobuf@1.9.0_/node_modules/@connectrpc/connect-web/dist/esm/grpc-web-transport.js:93:38)
[test]     at async Object.unary (webpack-internal:///(rsc)/../../node_modules/.pnpm/@connectrpc+connect-web@1.4.0_@bufbuild+protobuf@1.9.0_@connectrpc+connect@1.4.0_@bufbuild+protobuf@1.9.0_/node_modules/@connectrpc/connect-web/dist/esm/grpc-web-transport.js:71:20)
[test]     at async Object.eval [as getLoginSettings] (webpack-internal:///(rsc)/../../node_modules/.pnpm/@connectrpc+connect@1.4.0_@bufbuild+protobuf@1.9.0/node_modules/@connectrpc/connect/dist/esm/promise-client.js:80:26)
[test]     at async Page (webpack-internal:///(rsc)/./src/app/(login)/loginname/page.tsx:30:27) {
[test]   cause: HTTPParserError: Response does not match the HTTP/1.1 protocol (Expected HTTP/)
[test]       at Parser.execute (node:internal/deps/undici/undici:8593:19)
srikrsna-buf commented 5 months ago

@yordis I don't think the issue related, the error trace you pasted is using undici which is a node package, it is not related to web.

If you are using the clients on node, you should use the transports from the @connectrpc/connect-node package

yordis commented 5 months ago

@srikrsna-buf As you could notice, it used to be the connect-node, and still, the same issue. I am gonna research about cy.request since that is being used as well https://github.com/zitadel/typescript/blob/dafe5fe25ab8d0ee776ba7138450240e1c3ba4ee/apps/login/cypress/support/mock.ts

leandro-branco commented 2 months ago

I switched the client, and still failing,

--- a/packages/zitadel-node/src/index.ts
+++ b/packages/zitadel-node/src/index.ts
@@ -1,8 +1,9 @@
 import { NewAuthorizationBearerInterceptor } from "@zitadel/client2";
-import {
-  createGrpcWebTransport,
-  GrpcTransportOptions,
-} from "@connectrpc/connect-node";
+// import {
+//   createGrpcWebTransport,
+//   GrpcTransportOptions,
+// } from "@connectrpc/connect-node";
+import { createGrpcWebTransport, GrpcWebTransportOptions } from "@connectrpc/connect-web";
 import { importPKCS8, SignJWT } from "jose";

 /**
@@ -12,7 +13,7 @@ import { importPKCS8, SignJWT } from "jose";
  */
 export function createServerTransport(
   token: string,
-  opts: GrpcTransportOptions,
+  opts: GrpcWebTransportOptions,
 ) {
   return createGrpcWebTransport({
     ...opts,
[test]  ⨯ ConnectError: [unknown] fetch failed
[test]     at async Page (loginname/page.tsx:30:27)
[test] digest: "1552443515"
[test] Cause: TypeError: fetch failed
[test]     at node:internal/deps/undici/undici:12345:11
[test]     at async next (webpack-internal:///(rsc)/../../node_modules/.pnpm/@connectrpc+connect-web@1.4.0_@bufbuild+protobuf@1.9.0_@connectrpc+connect@1.4.0_@bufbuild+protobuf@1.9.0_/node_modules/@connectrpc/connect-web/dist/esm/grpc-web-transport.js:93:38)
[test]     at async Object.unary (webpack-internal:///(rsc)/../../node_modules/.pnpm/@connectrpc+connect-web@1.4.0_@bufbuild+protobuf@1.9.0_@connectrpc+connect@1.4.0_@bufbuild+protobuf@1.9.0_/node_modules/@connectrpc/connect-web/dist/esm/grpc-web-transport.js:71:20)
[test]     at async Object.eval [as getLoginSettings] (webpack-internal:///(rsc)/../../node_modules/.pnpm/@connectrpc+connect@1.4.0_@bufbuild+protobuf@1.9.0/node_modules/@connectrpc/connect/dist/esm/promise-client.js:80:26)
[test]     at async Page (webpack-internal:///(rsc)/./src/app/(login)/loginname/page.tsx:30:27) {
[test]   cause: HTTPParserError: Response does not match the HTTP/1.1 protocol (Expected HTTP/)
[test]       at Parser.execute (node:internal/deps/undici/undici:8593:19)

@yordis, same issue when using playwright. I'm wondering if you managed to solve it and mind sharing please.

yordis commented 2 months ago

Our issue was due to the server not being able to handle the header;