graphql / graphql-http Goto Github PK
View Code? Open in Web Editor NEWSimple, pluggable, zero-dependency, GraphQL over HTTP spec compliant server, client and audit suite.
Home Page: https://graphql-http.com
License: MIT License
Simple, pluggable, zero-dependency, GraphQL over HTTP spec compliant server, client and audit suite.
Home Page: https://graphql-http.com
License: MIT License
express-graphql had a Graphiql. And that module is now deprecated. I want that feature in this module.
The spec has a paragraph that states:
Note: Specifying
null
in JSON (or equivalent values in other formats) as values for optional request parameters is equivalent to not specifying them at all.
The audit suite should test this explicitly.
(I was inspired by the audit suite to be stricter about banning things like variables: 0
and got carried away and also banned variables: null
. So the suite should prevent this over-fitting.)
I would like to integrate the audits in my Jest test suite as shown in the README.
I don’t want to have a fixed port for my URL: I want to be able to listen on port 0 and get the URL back and pass that to the tests.
But I don’t want to actually start and listen on a server at the “top level” of a file, because I don't want it to run unless the particular tests are selected (eg, if it.only
or the like disables this part of the test file, I don't want to start a server). So listening should go in beforeAll or beforeEach or something.
But you need to give Jest the list of tests before this code runs, and the API here only gives you the list of audit tests once you already have an URL.
It would work better if the url was an argument to fn instead, or if you can pass a function returning an URL or something.
Expected Behaviour
I expected it to works :)
Actual Behaviour
but instead it did this.
Debug Information
Just install latest version and used it with vite.
Further Information
Obviously, something is wrong with bunling - in lib folder there is no audits.mjs
, so it should be audits/index.mjs
in reexport
Continuation of #29.
Using pull_request_target
as the trigger in workflows wont allow forks to change the workflows; meaning, new implementation audits PRs wont work - we'd need to prepare.
For example, a server MAY support GET requests - if it does, it MUST do this and that.
Additionally something like "watershed readiness" checks; for example, express-graphql should pass the basic tests but won't pass the watershed test because how could it (it's depricated)?
I was looking forward to starting to learn graphql and migrate from rest for my a personal project. Every other tutorial in the realm of NodeJS and Express recommend to use express-graph
but it is deprecated and this module is recommend. However, I noticed one feature seems to be missing, graphiql
. This isn't a dealbreaker but it would be nice to have this feature in graphql-http
.
I apologize if this bug is invalid. I tried searching the internet for similar issues but could not find one.
I believe this has something to do with how libraries are bundled in vite-node.
Here is a reproduction
https://stackblitz.com/edit/stackblitz-starters-se6shc
node src/server.js
works but running yarn dev
fails
If this is a vite-node
or graphql
issue, let me know.
Many things can be wrong or it all may just be an incompatibility issue. It would be nice if someone could explain what is going on and let others know the solution if they are encountering the same issue.
The audit SHOULD not contain the data entry on JSON parsing failure when accepting application/graphql-response+json
does this:
assert(
'Data entry',
(await assertBodyAsExecutionResult(res)).data,
).toBe(undefined);
This will throw if the body is not actually JSON, with the misleading error about "SHOULD not contain the data entry".
First, I'm not actually sure if the spec actually has a SHOULD that JSON parse errors should be returned as JSON at all (as opposed to having opinions about its structure if it is JSON). Apollo Server now expects you to use your web framework's JSON parsing capabilities (eg, body-parser
with Express) rather than handling it "in-house" and it is primarily structured as a non-error-handling middleware, so it's challenging for us to respond to invalid JSON with any particular error format. Maybe that's a self-imposed limitation but we're probably not going to change it. But I don't really see anything that says you SHOULD have a JSON response here. There's
When a server receives a well-formed GraphQL-over-HTTP request, it must return a well‐formed GraphQL response.
but in this case there is no well-formed request, so that doesn't apply.
Second, even if this is a legitimate thing to (optionally) test for, I think it should probably be explicitly tested for separately from this test case, and this particular test shouldn't fail claiming there's a data entry where there really isn't one. ie if the response is not JSON at all then I think this test should pass?
As a user or client or server
I want some feature
So that some value
Expected Behaviour
One expects the default/fallback behaviour to correctly assemble UTF-8 multibyte characters in the request body.
Actual Behaviour
The default/fallback behaviour incorrectly assembles requests that exceed the input stream chunk size. Multibyte characters that straddle chunks are incorrectly parsed, resulting in replacement characters or arbitrary single byte characters.
Example: https://github.com/graphql/graphql-http/blob/main/src/use/http.ts#L144-L146
Debug Information
Send an HTTP request with a variable assigned to a large number of fx "å" that exceeds the request body stream high-water mark. The value passed to the schema will be intermittently corrupted.
Further Information
It appears as though simply calling req.setEncoding("utf8");
is enough to address the issue.
As a user or client or server
I want some feature
I want to add to the context values the response of the route, because it is usefull for set cookies for example.
So that some value
I want to add to the context values the response of the route, because it is usefull for set cookies for example.
Something like this:
createHandler({
schema,
context: (req, res, params) => ({ req, res, params })
})
% yarn run -s ts-node-esm test.ts
warning package.json: No license field
/private/tmp/a/node_modules/ts-node/src/index.ts:859
return new TSError(diagnosticText, diagnosticCodes, diagnostics);
^
TSError: ⨯ Unable to compile TypeScript:
test.ts:1:10 - error TS2305: Module '"graphql-http"' has no exported member 'createHandler'.
1 import { createHandler } from 'graphql-http';
~~~~~~~~~~~~~
at createTSError (/private/tmp/a/node_modules/ts-node/src/index.ts:859:12)
at reportTSError (/private/tmp/a/node_modules/ts-node/src/index.ts:863:19)
at getOutput (/private/tmp/a/node_modules/ts-node/src/index.ts:1077:36)
at Object.compile (/private/tmp/a/node_modules/ts-node/src/index.ts:1433:41)
at transformSource (/private/tmp/a/node_modules/ts-node/src/esm.ts:400:37)
at /private/tmp/a/node_modules/ts-node/src/esm.ts:278:53
at async addShortCircuitFlag (/private/tmp/a/node_modules/ts-node/src/esm.ts:409:15)
at async nextLoad (node:internal/modules/esm/loader:163:22)
at async ESMLoader.load (node:internal/modules/esm/loader:605:20)
at async ESMLoader.moduleProvider (node:internal/modules/esm/loader:457:11) {
diagnosticCodes: [ 2305 ]
}
Expected Behaviour
I expected it to work importing graphql-http
module with ESM TypeScript.
Actual Behaviour
but instead it did fail with Module '"graphql-http"' has no exported member '...'
error.
Debug Information
test.ts
import { createHandler } from 'graphql-http';
package.json
{
"type": "module",
"dependencies": {
"graphql": "^16.6.0",
"graphql-http": "^1.17.0"
},
"devDependencies": {
"ts-node": "^10.9.1",
"typescript": "^5.0.3"
}
}
tsconfig.json
{
"compilerOptions": {
"module": "esnext",
"moduleResolution": "nodenext",
"strict": true
}
}
Further Information
Looking at the type definition of graphql-http
in node_modules/graphql-http/lib/index.d.mts
, there is no .js
extension.
export * from './common';
export * from './handler';
export * from './client';
export * from './audits';
It may works correctly by changing the following code:
export * from './common.js';
export * from './handler.js';
export * from './client.js';
export * from './audits/index.js';
Debug through graphql-http instead of the auditing server. A great step forwards would already be to attach the full response as a part of the audit result.
I'm looking for an audit that enforces:
https://github.com/graphql/graphql-over-http/blob/main/spec/GraphQLOverHTTP.md#variable-coercion-failure
...but I'm not finding one. Is this missing, and would you be interested in a PR to add it?
Spotted by @glasser
Hi,
graphql-http seems to be vulnerable to CSRF attack.
Is it planed to implement an anti-CSRF system, like tokens management on GraphQL endpoints ?
If people make changes to the audits in the repo and open a PR, the CI should be able to push the reports updates.
Issue appeared here: #27.
As a GraphQL library maintainer I would like to be able to run HTTP spec audit locally to ensure my client/server remains compliant with the spec.
As a _user
I want parseRequestParams function to be exported
So that same implementation can be used outside the package when interacting with graphql-http.
This was the behaviour in express-graphql implementation.
Expected Behaviour
I expected the error response to be structured like this:
{
"errors": [
{
"locations": [
{
"column": 8,
"line": 1
}
],
"message": "Variable \"$input\" got invalid value \"foo\"; Int cannot represent non-integer value: \"foo\""
}
]
}
Actual Behaviour
but instead it was nested twice like so:
{
"errors": [
{
"errors": [
{
"locations": [
{
"column": 8,
"line": 1
}
],
"message": "Variable \"$input\" got invalid value \"foo\"; Int cannot represent non-integer value: \"foo\""
}
]
}
]
}
Debug Information
Minimal example to reproduce:
Code:
const { GraphQLSchema, GraphQLObjectType, GraphQLInt } = require("graphql");
const express = require("express");
const { createHandler } = require("graphql-http/lib/use/express");
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: "Query",
fields: {
hello: {
type: GraphQLInt,
args: {
input: {
type: GraphQLInt,
},
},
},
},
}),
});
const app = express();
app.all("/graphql", createHandler({ schema }));
app.listen({ port: 4000 });
console.log("Listening to port 4000");
Send a query such as:
query ($input: Int) {
hello(input: $input)
}
with variables:
{ "input": "foo" }
At first glance after briefly debugging it appears as though the error is here in the makeResponse
function.
Further Information
The nesting format shown above under the "Expected Behaviour" section is the response that is returned by other GraphQL server frameworks such as express-graphql
and graphql-yoga
. Other errors returned by graphql-http
are also not nested twice, such as when sending the following query against the example above.
Query
{
hello(input: "foo")
}
Response:
{
"errors": [
{
"locations": [
{
"column": 16,
"line": 1
}
],
"message": "Int cannot represent non-integer value: \"foo\""
}
]
}
Screenshot
Expected Behaviour
I followed the recipe from https://github.com/graphql/graphql-http#recipes for migration from express-graphql
. When I run the server I would expect it to work as with express-graphql (no errors).
Actual Behaviour
When starting the server I get:
0|www | Internal error occurred during request handling. Please check your implementation. Error: The GraphQL schema is not provided
0|www | at handler (/Users/e/Desktop/projects/my/node_modules/graphql-http/lib/handler.js:202:23)
0|www | at processTicksAndRejections (node:internal/process/task_queues:96:5)
0|www | at async requestListener (/Users/e/Desktop/projects/my/node_modules/graphql-http/lib/use/express.js:28:34)
Debug Information
Help us debug the bug?
Further Information
Using:
graphql-http 1.7.0
@graphql-tools/schema 9.0.4
to create my schema (is this not supported?)Created new fresh project followed steps from provided documentation and I set graphiql:true and hit localhost:3001/graphql from browser so it's just showing following error instead graphqlUI.
{"errors":[{"message":"Missing query"}]}
`const express = require('express');
const app = express();
const port = 3001;
const { createHandler } = require('graphql-http/lib/use/express');
const { GraphQLSchema, GraphQLObjectType, GraphQLString } = require('graphql');
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: {
hello: {
type: GraphQLString,
resolve: () => 'world',
},
},
}),
});
app.get('/', (req, res) => {
res.send('Hello World!')
})
// Create a express instance serving all methods on /graphql
app.all('/graphql', createHandler({ schema,graphiql:true }));
app.listen(port, () => {
console.log(Example app listening on port ${port}
)
})`
As a server, I want to add an extensions
callback function similar to what's available in the express-graphql package options
so that I can add additional key-value metadata to each response. This is useful for capturing runtime and metrics for a given request.
graphql-http
createHandler
function should have an optional extensions
function for adding additional metadata to the GraphQL response as a key-value object. The result will be added to the "extensions" field in the resulting JSON. This is often a useful place to add development time metadata such as the runtime of a query or the amount of resources consumed. This may be an async function. The function is given one object as an argument: { document, variables, operationName, result, context }.As a user migrating from express-graphql
, I want to pass a rootValue
resolver. With express-graphql
, I was able to do the following:
app.get('/graphql', graphqlHTTP((req, res) => ({
schema,
rootValue: resolvers
})))
Ideally, I would like to set rootValue
as an option of createHandler
app.use(
'/graphql',
createHandler({ schema, rootValue }),
)
rootValue
without overriding the whole ExecutionContext
with onSubscribe
rootValue
Maybe using a rootValue
is not recommended anymore? Maybe there's an alternative? For reference, here's how I declare my schema/resolvers:
module.exports = {
/**
* Create an article.
*/
articles: async (args, { req }) => {
// ...
}
/**
* Delete an article.
*/
deleteArticle: async (args, { req }) => {
// ...
},
}
const gql = require('graphql-tag')
const { buildASTSchema } = require('graphql')
module.exports = buildASTSchema(gql`
type Article {
_id: ID!
title: String
content: String
createdAt: String
updatedAt: String
}
type RootQuery {
articles (user: ID): [Article!]!
}
type RootMutation {
deleteArticle(article: ID!): Article!
}
schema {
query: RootQuery
mutation: RootMutation
}
`)
The npm package of graphql-http
had a few releases before. Deprecate all of them before releasing v1.
npm deprecate graphql-http@"< 1.0.0" "This package has a new owner and has completely changed as of v1! Please go to https://github.com/enisdenjo/graphql-http for more info."
Create an online website which accepts an URL and performs a GQL over HTTP audit for quick checks without having to install anything.
Would work for local servers too because you can simply provide a localhost address too.
Expected Behaviour
A request with the HTTP header:
Accept: application/json; charset=utf-8
is accepted as a GraphQL request
Actual Behaviour
The request is rejected with:
HTTP 406 Not Acceptable
Debug Information
I think the check here is wrong and should be looking for utf-8
not utf8
.
https://github.com/graphql/graphql-http/blob/v1.22.0/src/handler.ts#L593
Screenshot
SHOULD use 4xx or 5xx status codes on document validation failure when accepting application/graphql-response+json => ./test.ts:9:8
error: AssertionError: Test case is leaking 1 resource:
- A fetch response body (rid 380) was created during the test, but not consumed during the test. Consume or close the response body `ReadableStream`, e.g `await resp.text()` or `await resp.body.cancel()`.
at assert (ext:deno_web/00_infra.js:353:11)
at resourceSanitizer (ext:cli/40_testing.js:417:5)
at async Object.exitSanitizer [as fn] (ext:cli/40_testing.js:435:7)
at async runTest (ext:cli/40_testing.js:840:5)
at async runTests (ext:cli/40_testing.js:1098:20)
Expected Behaviour
It should be possible to use the server audits in Deno.test()
in a way that does not leak resources.
Actual Behaviour
As discussed in #63 (comment), the tests leak resources.
I am not sure why, but the fix I added to the PR now does not work (fully) in my project.
Debug Information
The following run shows what happens without any cleanup: https://github.com/nuwave/lighthouse/actions/runs/4488866245/jobs/7893989167.
With a cleanup step, some portion of the tests is fixed (I think the failing ones), but others still leak: https://github.com/nuwave/lighthouse/actions/runs/4488817464/jobs/7893880714.
Further Information
Here is the link to the PR where I try to run the audit in my project: nuwave/lighthouse#2359.
Hi,
First, thanks for all the work you are doing for these libraries!
Its not much of an issue as it is a question following my transition from express-graphql to graphql-http. Express-graphql used to work with graphql-upload but now it seems to me that the handler is blocking my POST request with an image because the Content-Type is not "application/json".
Is this limitation is expected?
Thanks,
Expected Behaviour
I expect this library to accept multipart/form-data Content-Type.
Actual Behaviour
Right now, the library only accepts "application/json" as Content-Type for POST requests. Otherwise, it throws a 415 Unsupported Media Type
Expected Behaviour
Should return
{
"data": {
"hello": "world"
}
}
Actual Behaviour
Check screenshot, loads forever.
Debug Information
I used 2 code snippets: one with express-graphql
, the other graphql-http
const express = require("express")
const {createHandler} = require('graphql-http');
const { GraphQLSchema, GraphQLObjectType, GraphQLString } = require("graphql");
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: {
hello: {
type: GraphQLString,
resolve: () => 'world',
},
},
}),
});
const app = express()
app.use(
"/graphql",
createHandler({
schema
})
)
app.listen(4000)
console.log("Running a GraphQL API server at http://localhost:4000/graphql")
const express = require("express")
const { graphqlHTTP } = require("express-graphql")
const { GraphQLSchema, GraphQLObjectType, GraphQLString } = require("graphql");
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: {
hello: {
type: GraphQLString,
resolve: () => 'world',
},
},
}),
});
const app = express()
app.use(
"/graphql",
graphqlHTTP({
schema: schema
})
)
app.listen(4000)
console.log("Running a GraphQL API server at http://localhost:4000/graphql")
Further Information
I'm with node v16.16.0
package.json
{
"name": "demo",
"version": "1.0.0",
"description": "demo",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"license": "ISC",
"dependencies": {
"express": "^4.18.2",
"express-graphql": "^0.12.0",
"graphql-http": "^1.18.0"
}
}
I tried to implement the code sample for express
in order to migrate away from express-graphql
. The express-graphql
version works and returns a response, but the http-graphql
version does not respond.
Code:
import * as express from 'express';
import { graphqlHTTP } from 'express-graphql';
import { GraphQLObjectType, GraphQLSchema, GraphQLString } from 'graphql';
import { createHandler } from 'graphql-http/lib/use/express';
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: "Query",
fields: {hello: {type: GraphQLString, resolve: () => "hello"}}
})
});
const app = express();
// express-graphql implementation
app.use('/graphql', graphqlHTTP({ schema: schema }));
// graphql-http express implementation
app.all('/graphql2', createHandler({ schema }));
app.listen(4000);
The I use curl:
curl http://localhost:4000/graphql --data-urlencode "query=query Q { hello }"
{"data":{"hello":"hello"}}
curl http://localhost:4000/graphql2 --data-urlencode "query=query Q { hello }"
Expected Behaviour
A response of {"data":{"hello":"hello"}}
for both /graphql
and /graphql2
.
Actual Behaviour
Only /graphql
(the express-graphql implementation) returns any response.
Version: 1.17.1
Node version: 16.14.0
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.