A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/dreamit-de/graphql-server below:

dreamit-de/graphql-server: GraphQL server implementation written in NodeJS/Typescript using graphql-js

A GraphQL server implementation written in NodeJS/Typescript. It uses the standard graphql library to receive GraphQL requests and send back appropriate responses.

Deprecated: This library will no longer be maintained. Use graphql-yoga or graphql-http instead!

npm install --save @dreamit/graphql-server

TypeScript declarations are provided within the project.

The following table shows which version of graphql-js, @dreamit/graphql-server-base and @dreamit/funpara are compatible with which version of @dreamit/graphql-server. As @dreamit/graphql-server defines them as peerDependency you might want to choose a fitting version used in your project and by other libraries depending on them.

graphql-js version graphql-server version graphql-server-base version funpara version Github branch Development Status ^15.2.0 1.x n.a. n.a. legacy-graphql15 end of life ^16.0.0 2.x n.a. n.a. legacy-server-v2 end of life ^16.0.0 3.x ^1.0.1 n.a. legacy-server-v3 end of life ^16.0.0 4.x ^2.7 ^1.0 legacy-server-v4 maintenance ^16.0.0 5.x ^3.1 ^1.0 main active Handling and executing requests

GraphQLServer provides the function handleRequest to handle and execute requests. Depending on the provided parameters different actions will be executed in order to send or return the ExecutionResult

class GraphQLServer {
    async handleRequest(
        request: GraphQLServerRequest | GraphQLRequestInfo,
        response?: GraphQLServerResponse,
    ): Promise<GraphQLExecutionResult> {}
}

The handleRequest function can be used for many use cases. The following part lists some use cases with a short description. It is possible to use handleRequest with different parameters with a single GraphQLServer instance, e.g. when using a webserver with websockets or messaging.

Usage as webserver middleware

You can create a new instance of GraphQLServer with the options necessary for your tasks. The handleRequest function of the GraphQLServer can be integrated with many fitting webservers.

Note regarding POST requests:

graphql-server version 5 and higher tries to extract the request information from the request.body field or response.text function if request.body is undefined. Some webserver frameworks like Express might need a fitting body parser in order to populate this body field.

const graphQLServerPort = 3592
const graphQLServerExpress = express()
const customGraphQLServer = new GraphQLServer({ schema: someExampleSchema })
graphQLServerExpress.use(bodyParser.text({ type: '*/*' }))
graphQLServerExpress.all('/graphql', (req, res) => {
    return customGraphQLServer.handleRequest(req, res)
})
graphQLServerExpress.listen({ port: graphQLServerPort })
console.info(`Starting GraphQL server on port ${graphQLServerPort}`)

GraphQLServer provides default values and behavior out of the box. It is recommended to at least provide a schema so the request won't be rejected because of a missing/invalid schema. When using it with a local schema it is recommended to provide a rootValue to return a fitting value. Examples for these requests can be found in the integration test in the GraphQLServer.integration.test.ts class in the tests/server folder.

GraphQLServer supports two response formats:

Which response format will be used depends on the set accept request header. If the header is not set, set to application/json or application/json with a higher priority this format will be used. application/graphql-response+json will be used only if it is set in accept header or set with higher priority then application/json.

Schema validation and disabling Introspection

Validation rules can be used to define how the GraphQLServer should behave when validating the request against the given schema. To ease the use GraphQLServer uses the specifiedRules from graphql-js library. If you don't want to use the default validation rules you can overwrite them by setting defaultValidationRules option to [].

Warning! Setting both defaultValidationRules and customValidationRules options to [] will disable validation. This might result in unexpected responses that are hard to use for API users or frontends.

import { NoSchemaIntrospectionCustomRule } from 'graphql'

const graphQLServerPort = 3592
const graphQLServerExpress = express()
const customGraphQLServer = new GraphQLServer({
    schema: someExampleSchema,
    defaultValidationRules: [],
})
graphQLServerExpress.use(bodyParser.text({ type: '*/*' }))
graphQLServerExpress.all('/graphql', (req, res) => {
    return customGraphQLServer.handleRequest(req, res)
})
graphQLServerExpress.listen({ port: graphQLServerPort })
console.info(`Starting GraphQL server on port ${graphQLServerPort}`)

If you want to define custom validation rules you can use the customValidationRules option (e.g. to handle introspection like shown in the example below).

Introspection can be used to get information about the available schema. While this may be useful in development environments and public APIs you should consider disabling it for production if e.g. your API is only used with a specific matching frontend.

Introspection can be disabled by adding the NoSchemaIntrospectionCustomRule from the graphql-js library to the customValidationRules option.

import { NoSchemaIntrospectionCustomRule } from 'graphql'

const graphQLServerPort = 3592
const graphQLServerExpress = express()
const customGraphQLServer = new GraphQLServer({
    schema: someExampleSchema,
    customValidationRules: [NoSchemaIntrospectionCustomRule],
})
graphQLServerExpress.use(bodyParser.text({ type: '*/*' }))
graphQLServerExpress.all('/graphql', (req, res) => {
    return customGraphQLServer.handleRequest(req, res)
})
graphQLServerExpress.listen({ port: graphQLServerPort })
console.info(`Starting GraphQL server on port ${graphQLServerPort}`)

The GraphQL response can be validated using the responseStandardSchema option. It accepts a StandardSchemaV1 and will, when using sendResponse, put found issues into the response as GraphQLErrors. By default noOpStandardSchema is used and returns the value and no issues. To validate the response a StandardSchemaV1 compliant schema like @dreamit/graphql-std-schema can be used.

import { graphQLResponseSchema } from '@dreamit/graphql-std-schema'

const graphQLServerPort = 3592
const graphQLServerExpress = express()
const customGraphQLServer = new GraphQLServer({
    responseStandardSchema: graphQLResponseSchema(),
    schema: someExampleSchema,
})
graphQLServerExpress.use(bodyParser.text({ type: '*/*' }))
graphQLServerExpress.all('/graphql', (req, res) => {
    return customGraphQLServer.handleRequest(req, res)
})
graphQLServerExpress.listen({ port: graphQLServerPort })
console.info(`Starting GraphQL server on port ${graphQLServerPort}`)

Hot reload of the GraphQL schema can be used to update the existing schema to a new version without restarting the GraphQL server, webserver or whole application. When setting a new schema it will be used for the next incoming request while the old schema will be used for requests that are being processed at the moment. Hot reloading is especially useful for remote schemas that are processed in another application like a webservice.

The schema can be changed simply by calling setSchema in the GraphQLServer instance. In the example below a second route is used to trigger a schema update.

const graphQLServerPort = 3592
const graphQLServerExpress = express()
const customGraphQLServer = new GraphQLServer({ schema: someExampleSchema })
graphQLServerExpress.use(bodyParser.text({ type: '*/*' }))
graphQLServerExpress.all('/graphql', (req, res) => {
    return customGraphQLServer.handleRequest(req, res)
})
graphQLServerExpress.all('/updateme', (req, res) => {
    const updatedSchema = someMagicHappened()
    customGraphQLServer.setSchema(updatedSchema)
    return res.status(200).send()
})
graphQLServerExpress.listen({ port: graphQLServerPort })
console.info(`Starting GraphQL server on port ${graphQLServerPort}`)

There are 2 builtin MetricsClient implementations available.

The SimpleMetricsClient provides three custom metrics for the GraphQL server:

A simple metrics endpoint can be created by using getMetricsContentType and getMetrics functions from the GraphQLServer instance. In the example below a second route is used to return metrics data.

const graphQLServerPort = 3592
const graphQLServerExpress = express()
const customGraphQLServer = new GraphQLServer({ schema: someExampleSchema })
graphQLServerExpress.use(bodyParser.text({ type: '*/*' }))
graphQLServerExpress.all('/graphql', (req, res) => {
    return customGraphQLServer.handleRequest(req, res)
})
graphQLServerExpress.get('/metrics', async (req, res) => {
    return res
        .contentType(customGraphQLServer.getMetricsContentType())
        .send(await customGraphQLServer.getMetrics())
})
graphQLServerExpress.listen({ port: graphQLServerPort })
console.info(`Starting GraphQL server on port ${graphQLServerPort}`)

The GraphQLServer does not handle CORS requests on its own. It is recommended to handle this on the webserver level, e.g. by using cors library with an Express webserver like in the example below.

const graphQLServerPort = 3592
const graphQLServerExpress = express()
graphQLServerExpress.use(cors())
const customGraphQLServer = new GraphQLServer({ schema: someExampleSchema })
graphQLServerExpress.use(bodyParser.text({ type: '*/*' }))
graphQLServerExpress.all('/graphql', (req, res) => {
    return customGraphQLServer.handleRequest(req, res)
})
graphQLServerExpress.listen({ port: graphQLServerPort })
console.info(`Starting GraphQL server on port ${graphQLServerPort}`)

The handleRequest function works with webservers that provide a fitting request and response object that matches GraphQLServerRequest and GraphQLServerResponse interface. As Express (since version 2.x) matches both no further adjustment is necessary. If one or both objects do not match GraphQLServerRequest and GraphQLServerResponse it might still be possible to map the webserver request and response objects to these interfaces.

In the following table a list of webserver frameworks/versions can be found that are able to run GraphQLServer. The Version column shows the version of the webserver framework we tested GraphQLServer version 4 with.
If the request and/or response has to be mapped it is noted in the Mapping column. There is a code examples on how to use handleRequest without providing a GraphQLServerResponse and sending the response with the functionality provided by the webserver.

GraphQLServerRequest and GraphQLServerResponse interfaces

The GraphQLServerRequest and GraphQLServerResponse are available in the @dreamit/graphql-server-base module. This allows extensions such as custom Logger or MetricsClient implementations to implement these interfaces without defining @dreamit/graphql-server as dependency.

Working with context function

GraphQLServer, like many GraphQL libraries, uses a context function to create a context object of type Record<string, unknown> that is available during the whole request execution process. This can for example be used to inject information about request headers or adjust responses. An example can be found in the CustomSendResponse.integration.test.ts class in the test/server folder.

export interface GraphQLServerOptions {
    contextFunction: (contextParameters: {
        serverOptions: GraphQLServerOptions
        request?: GraphQLServerRequest
        response?: GraphQLServerResponse
    }) => Record<string, unknown>
}

The GraphQLServer accepts the following GraphQLServerOptions. When calling the constructor or setOptions function, useful defaults from defaultGraphQLServerOptions are set and overwritten by the options provided in the constructor/function parameter.

Response Validation options Technical components and options Customize and extend GraphQLServer

To make it easier to customize and extend the GraphQLServer classes and class functions are public. This makes extending a class and overwriting logic easy.

In the example below the logic of TextLogger is changed to add the text "SECRETAPP" in front of every log output.

export class SecretApplicationTextLogger extends TextLogger {
    prepareLogOutput(logEntry: LogEntry): string {
        return `SECRETAPP - ${super.prepareLogOutput(logEntry)}`
    }
}

If you have problems, questions or issues please visit our Issue page and open a new issue if there are no fitting issues for your topic yet.

graphql-server is under MIT-License.


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4