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

Bypass query and variables validation #3436

Open
lokesh-yellow opened this issue Sep 17, 2024 · 0 comments
Open

Bypass query and variables validation #3436

lokesh-yellow opened this issue Sep 17, 2024 · 0 comments

Comments

@lokesh-yellow
Copy link

lokesh-yellow commented Sep 17, 2024

Describe the bug

Hey,
I am using graphql-yoga as a proxy to hasura to restrict the graphql introspection and to disable batching. I am also trying to disable query and variable validation by using onValidate hook and allow hasura to validate the query as shown in the code snippet below. But yoga server still tries to validate the variables passed and throws an error
Some context of why validation needs to be disabled in our case:
I have an xyz variable which is Int as per the schema, but the client passes it as a string, the hasura server seems to be capable of parsing the string into an Int and execute the query, But when its proxied through graphql-yoga, It throws a validation error. So we are trying to add graphql-yoga as a reverse proxy to hasura and trying to make it in place without any client side code changes

Steps to Reproduce the Bug or Issue

Code snippet

const getInboxKBSchema = async () => {
  const remoteExecutor = buildHTTPExecutor({
    endpoint: HASURA_ENDPOINT,
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Accept: "application/json",
    }
  })
  // ymlogger.log(graphqlSchema.getQueryType());
  const executorWrapper = async (args: any) => {
    ymlogger.info('Executing query: ', print(args.document));
    const result = await remoteExecutor(args);
    ymlogger.info('Execution result: ', result);
    return result;
  };

  const remoteSchema = await schemaFromExecutor(remoteExecutor)

  const wrappedSchema = wrapSchema({
    schema: remoteSchema,
    executor: executorWrapper, // Wrap the executor for logging and error tracing
  });
  return wrappedSchema;
  // const yogaInstance = createYoga({ schema: graphqlSchema })
  // const schemaWithMiddleware = applyMiddleware(graphqlSchema, defaultValueMiddleware)

  // return createServer(yogaInstance)
}


const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))


const disableValidation = (): Plugin => {
  return {
    onValidate({ setValidationFn, setResult, params, context }) {
      ymlogger.info("Received request for validation:", { requestBody: context.request.body, params });
      setResult([])
      setValidationFn(() => {
        return []
      })

    },
    onExecute({ setExecuteFn, args, executeFn }) {
      ymlogger.info("The request is in onexecute hook")
      setExecuteFn(() => {
        ymlogger.info('Bypassing validation and executing query:', args.document);
        // Directly execute without validation
        return executeFn(args);
      });
    },
    onResponse({ request, response }) {
      response.headers.set('X-GraphQL-Server', 'Yoga')
    }
  }
}

// const BypassValidationPlugin: Plugin = {
//   // You can use onExecute or directly modify the validation phase
//   onExecute({ setResult }) {
//     // Bypass validation logic - direct execution for all queries
//     setResult((args) => {
//       return args.execute(args.args)
//     })
//   },
// }


const startServer = async (retry: number, maxRetries = MAX_RETRIES_COUNT) => {
  let schema: GraphQLSchema
  try {
    schema = await getInboxKBSchema()
  } catch (error) {
    ymlogger.error(`Error in fetching the graphql schema, retrying after ${SLEEP_INTERVAL}, retryCount:: ${retry}`, error)
    await sleep(SLEEP_INTERVAL)
    retry++;
    return startServer(retry, maxRetries)
  }
  ymlogger.info("Fetched the schema, starting the server now", { schema })
  const yogaInstance = createYoga({ schema, plugins: [disableValidation()], graphqlEndpoint: "/v1/graphql" })
  app.use(yogaInstance.graphqlEndpoint, yogaInstance)
  app.use(yogaInstance)
  app.listen(3000, () => {
    ymlogger.info("Running in 3000 successfully")
  })
}

startServer(0).catch((error) => {
  ymlogger.error("Error in starting the server", error)
})

Expected behavior

Expected behaviour is when validation is bypassed by using setValidationFn which returns no validation errors, the validation seems to be happening which is throwing errors

Screenshots or Videos

No response

Platform

  • OS: Linux
  • NodeJS: node 18
  • @graphql-yoga/* version(s): 5.7.0

Additional context

No response

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

1 participant