Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v3] Defer/Stream Content-Type assertions #2079

Closed
Tracked by #1358
n1ru4l opened this issue Nov 10, 2022 · 2 comments
Closed
Tracked by #1358

[v3] Defer/Stream Content-Type assertions #2079

n1ru4l opened this issue Nov 10, 2022 · 2 comments

Comments

@n1ru4l
Copy link
Collaborator

n1ru4l commented Nov 10, 2022

We should not allow SSE for incremental delivery.

Currently, if I send the following an event stream response will be sent.

const response = await fetch(`http://localhost:${port}/graphql`, {
  method: 'POST',
  headers: {
    'content-type': 'application/json',
  },
  body: JSON.stringify({
    query: '{ hi @stream }',
  }),
})

Instead, a multipart/mixed response should be sent.

Also, for the following requests 406: Not Acceptable should be sent.

 await fetch(`http://localhost:${port}/graphql`, {
  method: 'POST',
  headers: {
    'content-type': 'application/json',
    accept: 'application/json',
  },
  body: JSON.stringify({
    query: '{ hi @stream }',
  }),
})

await fetch(`http://localhost:${port}/graphql`, {
  method: 'POST',
  headers: {
    'content-type': 'application/json',
    accept: 'text/event-stream',
  },
  body: JSON.stringify({
    query: '{ hi @stream }',
  }),
})
@n1ru4l n1ru4l changed the title [v3] Defer/Stream works over SSE [v3] Defer/Stream Content-Type assertions Nov 10, 2022
@theguild-bot theguild-bot mentioned this issue Nov 10, 2022
@ardatan ardatan closed this as completed Nov 11, 2022
@filiperochalopes
Copy link

filiperochalopes commented Jul 8, 2023

@n1ru4l I did not understand what is the error. Which content-type should work? I am trying to request a subscription and got 406 - Not Acceptable I think it might have something with this issue.

sendMessage Mutation

import { Op } from 'sequelize'

export default async (_, { userToId, message }, { pubSub, ...context }) => {
  console.log(context.request)
  const { checkAuth } = context;
  // Usuário que está mandando a mensagem
  const user = await checkAuth(['client', 'partner', 'admin'], context);
  // Verifica se já existe a sala, senão, cria
  const { models } = context;

  let chatRoom = await models.ChatRoom.findOrCreate({
    where: {
      [Op.or]: [
        {
          userOneId: user.id,
          userTwoId: userToId,
        },
        {
          userOneId: userToId,
          userTwoId: user.id,
        },
      ],
    },
    defaults: {
      userOneId: user.id, // Primeiramente o id do usuário que iniciou o chat
      userTwoId: userToId,
    },
  });
  
  const chatCreated = await models.Chat.create({
    chatRoomId: chatRoom[0].id,
    message,
    userId: user.id,
  });
  // Para poder adicionar o include
  const chat = await models.Chat.findByPk(chatCreated.id, {
    include: [
      { association: 'user' },
      {
        association: 'room',
        include: [{ association: 'userOne' }, { association: 'userTwo' }],
      },
    ],
  });

  pubSub.publish('messageSent', { messageSent: chat });

  return chat;
};

messageSent Subscription

import { pipe, filter } from 'graphql-yoga';

export default {
  subscribe: (_, { chatRoomId }, { pubSub }) => {
    return pipe(
      pubSub.subscribe('messageSent'),
      filter((value) => value.messageSent.chatRoomId === chatRoomId)
    );
  },
};

The mutation is running well...
image

But the subscription is running in error at GraphIQL...
image

And at FireCamp...
image
image

package.json

{
  "name": "node_boilerplate",
  "version": "1.0.0",
  "main": "src/server.js",
  "license": "MIT",
  "type": "module",
  "scripts": {
    "start:dev": "nodemon --experimental-specifier-resolution=node src/server.js",
    "start": "node --experimental-specifier-resolution=node src/server.js",
    "prepare": "husky install",
    "test": "jest --silent=false --verbose --detectOpenHandles"
  },
  "dependencies": {
    "@babel/cli": "^7.10.5",
    "@babel/node": "^7.10.5",
    "@graphql-tools/graphql-file-loader": "^8.0.0",
    "@graphql-tools/load": "^8.0.0",
    "@graphql-tools/load-files": "^7.0.0",
    "@graphql-tools/schema": "^10.0.0",
    "@graphql-yoga/subscription": "^4.0.0",
    "app-root-path": "^3.0.0",
    "axios": "^0.21.1",
    "bcrypt": "^5.0.0",
    "colors": "^1.4.0",
    "cookie-parser": "^1.4.5",
    "cors": "^2.8.5",
    "crypto-js": "^4.1.1",
    "date-fns": "^2.15.0",
    "dotenv": "^8.2.0",
    "express": "^4.18.2",
    "graphql": "^16.7.1",
    "graphql-tag": "^2.11.0",
    "graphql-upload": "^13.0.0",
    "graphql-yoga": "^4.0.3",
    "js-crypto-hmac": "^1.0.2",
    "jsonwebtoken": "^8.5.1",
    "nodemailer": "^6.4.5",
    "pg": "^8.7.3",
    "pg-hstore": "^2.3.4",
    "sequelize": "^6.28.0",
    "stripe": "^12.10.0",
    "totalvoice-node": "^1.10.0",
    "uuid": "^8.3.0"
  },
  "devDependencies": {
    "@babel/cli": "^7.10.5",
    "@babel/core": "^7.11.4",
    "@babel/eslint-parser": "^7.22.5",
    "@babel/plugin-proposal-optional-chaining": "^7.11.0",
    "@babel/preset-env": "^7.11.0",
    "eslint": "^8.43.0",
    "form-data": "^4.0.0",
    "husky": "^8.0.0",
    "jest": "^29.5.0",
    "node-fetch": "^2.6.11",
    "nodemon": "^2.0.2",
    "prettier": "^2.8.8",
    "pretty-quick": "^3.1.3",
    "sequelize-cli": "^6.5.2"
  }
}

server.js

import express from 'express';
import bodyParser from 'body-parser';
import cors from 'cors';
import schema from './graphql/schema';
import { graphqlUploadExpress } from 'graphql-upload';
import 'colors';
import cookieParser from 'cookie-parser';
import db from './models';
import dbConfig from './config/database';
import stripe from './config/stripe';
import { checkAuth, throwError } from './services/utils';
import { createYoga } from 'graphql-yoga'
import { createPubSub } from '@graphql-yoga/subscription'

import dotenv from 'dotenv';
dotenv.config();


console.log(
  `[SERVER - DATABASE SEQUELIZE CONN] Connecting to database host ${dbConfig.host}`
);

db.sequelize
  .authenticate()
  .then(() => {
    console.log('[SERVER - DATABASE SEQUELIZE CONN] Database connected.');
  })
  .catch((err) => {
    console.error('[SERVER - DATABASE SEQUELIZE CONN] Error: ', err);
  });

const app = express();

const pubSub = createPubSub()
const yoga = createYoga({
  schema,
  maskedErrors: false,
  graphqli: true,
  context: async ({request, response}) => ({
    request,
    response,
    models: db.sequelize.models,
    stripe,
    checkAuth,
    pubSub,
    utils: {
      throwError,
    },
  })
})

app.use(cors());

app.use(cookieParser());

app.use(
  graphqlUploadExpress({
    maxFileSize: 50000000,
    maxFiles: 10,
  })
);

app.use(bodyParser.json());

const BASE_URL = '/api/v1';

app.use(`${BASE_URL}/graphql`, yoga)

app.listen(process.env.NODE_PORT || 8080, () =>
  console.log(
    `[SERVER - EXPRESS SERVER] server listening on port ${
      process.env.NODE_PORT || 8080
    }...`.green
  )
);

@filiperochalopes
Copy link

Never mind. i don't know why but it was a problem with yoga.graphqlEndpoint not set. I think graphql-yoga can't split slashes on endpoint string if not passed trough yoga.graphqlEndpoint.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants