Coder Social home page Coder Social logo

oslabs-beta / gleiphql Goto Github PK

View Code? Open in Web Editor NEW
20.0 3.0 2.0 97.97 MB

GleiphQL is an GraphQL library which enhances performance and security by calculating query complexity, optimizing resource allocation, and monitoring your API traffic.

Home Page: https://www.gleiphql.dev/

TypeScript 100.00%
developer-tools graphql middleware rate-limiting express complexity-analysis

gleiphql's Introduction

Summary

This package is intended to be a combined monitoring/rate limiting solution for GraphQL, with pre-query execution static complexity analysis. The primary opinionation of this cost analysis implementation is that the user's schema should be augmented with an @cost directive on relevant non-polymorphic fields and that lists should be provided with an @paginationLimit directive that detail the expected bounds of said list. These directives being applied to the schema are the primary vehicle for user configurability, along with a configuration object that defines default parameters such as whether or not you opt into usage of the monitoring portion of our package, default pagination limits to be applied to lists without an @paginationLimit directive assigned to them, maximum depth etc.

This project derived significant inspiration from this paper by IBM and certain aspects of their specification for cost analysis, such as the @cost directive.

GraphQL Endpoint Monitor

The GraphQL Endpoint Monitor is a package designed to log and monitor traffic metrics for a GraphQL endpoint. The package is available as a plugin for Apollo server or as an Express Middlware. It sends the collected data to our Developer Portal for visualization. This package is intended to be used alongside our rate limiter package.

Metrics Collected

The apolloEndpointMonitor plugin and expressEndpointMonitor middleware collects the following metrics for each GraphQL request:

Metric Type Description
depth Number The depth of the GraphQL query.
ip String The IP address of the client making the request.
url String The URL of the GraphQL endpoint.
timestamp String The timestamp when the request was made.
objectTypes {String} An object containing the count of each GraphQL object type used in the query.
queryString String The original GraphQL query string.
complexityScore Number The complexity score of the GraphQL query.
blocked Boolean If the query was blocked by the rate limiter.
complexityLimit Number The complexity limit set by the user in the rate limiter.

These metrics will be sent to the web application for visualization and monitoring.

Prerequisites

  1. Signup/login to the GleiphQL developer portal.

  2. Add the endpoint URL to your account. Make sure the endpoint url you enter in the developer portal matches the endpoint URL of your graphQL API.

  3. Import and configure the GleiphQL rate-limiting package

Apollo Server Installation and Usage

If you would like to monitor your endpoint with Apollo server, follow the instructions in this section. The apolloEndpointMonitor plugin is intended to be used alongside the apolloRateLimiter plugin and the gleiphqlContext function, with the apolloEndpointMonitor plugin placed alongside the apolloRateLimiter plugin in the Apollo server.

Installation:

npm install gleiphql

Usage:

import { apolloRateLimiter, apolloEndpointMonitor, gleiphqlContext } from 'gleiphql';
import { startStandaloneServer } from '@apollo/server/standalone';
import { ApolloServer } from '@apollo/server';


// Configuration for the expressEndpointMonitor middleware.
const monitorConfig = {
  gleiphqlUsername: process.env.GLEIPHQL_USERNAME,
  gleiphqlPassword: process.env.GLEIPHQL_PASSWORD,
};

// Apply the apolloEndpointMonitor plugin along with the apolloRateLimiter middleware.
const apolloServer = new ApolloServer({
  schema: schema,
  plugins: [
    apolloRateLimiter(apolloConfig),
    apolloEndpointMonitor(monitorConfig)
  ],
});

// Add the gleipqlContext to the stand alone server
const { url } = await startStandaloneServer(apolloServer, {
  context: gleiphqlContext
});
console.log(`๐Ÿš€ Server ready at ${url}`);

The apolloEndpointMonitor plugin takes a configuration object with the following properties:

  • gleiphqlUsername: The username to access the web application where the metrics will be displayed.
  • gleiphqlPassword: The password for the web application authentication.

Express Installation and Usage

If you would like to monitor your endpoint with Express, follow the instructions in this section. The expressEndpointMonitor middleware is intended to be used alongside the expressRateLimiter middleware, with the expressRateLimiter middleware placed AFTER the expressEndpointMonitor middleware in the middleware chain.

Installation:

npm install gleiphql

Usage:

import express from 'express';
import { expressEndpointMonitor, expressRateLimiter } from 'gleiphql';
import { createHandler } from 'graphql-http/lib/use/express';

const app = express();

// Configuration for the expressEndpointMonitor middleware.
const monitorConfig = {
  gleiphqlUsername: process.env.GLEIPHQL_USERNAME,
  gleiphqlPassword: process.env.GLEIPHQL_PASSWORD,
};

// Apply the expressEndpointMonitor middleware before the expressRateLimiter middleware.
app.use('/graphql', expressEndpointMonitor(monitorConfig), expressRateLimiter(rateLimitConfig), createHandler({ schema }));

// Your other middleware and routes go here.
// ...

// Start the server
app.listen(3000, () => {
  console.log('Server is running on port 3000.');
});

The expressEndpointMonitor middleware takes a configuration object with the following properties:

  • gleiphqlUsername: The username to access the web application where the metrics will be displayed.
  • gleiphqlPassword: The password for the web application authentication.

GraphQL Rate-limiter

The GraphQL Rate-limiter is a package that rate-limits incoming queries based on user defined @cost and @paginationLimit directives applied on the schema level. Infinitely recursive queries are handled by a user-defined depth limit. The default value for maximum depth is 10 if not explicitly configured. The package is available as an Express Middleware or as a plugin for Apollo server. This package can be used with or without the monitoring package.

Prerequisites

The primary opinionation of this complexity analysis is that the user augments any relevant non-abstract/polymorphic fields and relevant arguments (generally slicing arguments) with a @cost directive. Lists can be augmented with a @paginationLimit directive, or the default paginationLimit defined in the configuration object will be applied to any lists that are encountered.

An example SDL with these specifications is as follows:

      directive @cost(value: Int) on FIELD_DEFINITION | ARGUMENT_DEFINITION
      directive @paginationLimit(value: Int) on FIELD_DEFINITION

      type Related {
        content: [Content!]!
      }

      interface Content {
        id: ID!
        title: String!
        related: Related
      }

      type Post implements Content {
        id: ID! @cost(value: 3)
        title: String! @cost(value: 4)
        body: String! @cost(value: 10)
        tags: [String!]! @cost(value: 5)
        related: Related
      }

      type Image implements Content {
        id: ID! @cost(value: 5)
        title: String! @cost(value: 6)
        uri: String! @cost(value: 2)
        related: Related
      }

      union UnionContent = Post | Image

      type Query {
        content: [Content] @paginationLimit(value: 10)
        posts(limit: Int @cost(value:10): [Post] @cost(value: 3) @paginationLimit(value: 10))
        images: [Image] @cost(value: 5) @paginationLimit(value: 10)
        related: [Related] @paginationLimit(value: 10)
        unionContent: [UnionContent] @paginationLimit(value: 10)
      }

Each field is augmented with a @cost directive that assigns a cost to each field of the schema based on user input. The @cost directive is strictly there to ensure the cost data is accessible to the complexity analysis portion of the package, it should have no functionality assigned to it beyond that. Without these directives a default value of 1 will be applied to each field. While the cost analysis will still run without augmenting the given schema, the results may not be usable as a heuristic for applying pre-query execution rate-limiting.

Express Installation and Usage

Installation:

npm install gleiphql

Usage:

import express from 'express';
import { expressRateLimiter } from 'gleiphql';
import { createHandler } from 'graphql-http/lib/use/express';

const app = express();

// Configuration for the expressRateLimiter middleware.

Below is a sample configuration for the sample GraphQL endpoint, the complexityLimit, paginationLimit, refillTime, and refillAmount properties are all up to user interpretation/use case.

const spacexConfig: RateLimitConfig = {
  complexityLimit: 3000,
  paginationLimit: 15,
  schema: spaceXSchema,
  refillTime: 300000,   // 5 minutes
  refillAmount: 1000,
  redis: false
  maxDepth: 15
}

// Apply the expressRateLimiter middleware after the expressRateLimiter middleware, or you can elect to use the rate-limiter alone

app.use('/graphql', expressEndpointMonitor(monitorConfig), expressRateLimiter(rateLimitConfig), createHandler({ schema }));

// Your other middleware and routes go here.
// ...

// Start the server
app.listen(3000, () => {
  console.log('Server is running on port 3000.');
});

Apollo Server Installation and Usage

If you would like to rate-limit on Apollo server, follow the instructions in this section. The apolloRateLimiter plugin is intended to work with the gleiphqlContext function.

Installation:

npm install gleiphql

Usage:

import { apolloRateLimiter, gleiphqlContext } from 'gleiphql';
import { startStandaloneServer } from '@apollo/server/standalone';


// Configuration for the complexity analysis/rate-limiting middleware.

const spacexConfig: RateLimitConfig = {
  complexityLimit: 3000,
  paginationLimit: 15,
  refillTime: 300000,   // 5 minutes
  refillAmount: 1000,
  redis: false,
  maxDepth: 15,
}


// Apply the apolloRateLimiter plug-in.
const apolloServer = new ApolloServer({
  schema: schema,
  plugins: [
    apolloRateLimiter(apolloConfig),
  ],
});

// Add the gleipqlContext to the stand alone server
const { url } = await startStandaloneServer(apolloServer, {
  context: gleiphqlContext
});
console.log(`๐Ÿš€ Server ready at ${url}`);

Contributing

If you find any issues or have suggestions for improvements, please feel free to open an issue or submit a pull request on our GitHub repository.

gleiphql's People

Contributors

jiedong111 avatar kp824 avatar larkinaj avatar wendyys96 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

gleiphql's Issues

Readme Adjustments

  1. I think the rate limiting section should be above the endpoint monitor section since that is the main functionality
  2. I think there should be a table of contents at the top of the readme showing the order of each section

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.