Seamlessly inject client IP address into your GraphQL resolvers with full TypeScript support.
- 🔒 Type-safe: Full TypeScript support with proper type definitions
- 🌐 Comprehensive IP Detection: Supports all major proxy headers and IP sources
- 🏠 Development-friendly: Special handling for local development environments
- ⚡ Zero Dependencies: Lightweight with minimal overhead
- 🔧 Envelop Compatible: Works seamlessly with the Envelop plugin system
- 📦 Universal: Works with GraphQL Yoga, Apollo Server, and any Envelop-based setup
npm install graphql-ip
yarn add graphql-ip
pnpm add graphql-ip
bun add graphql-ip
import { useGraphQLIp } from 'graphql-ip'
import { envelop } from '@envelop/core'
const getEnveloped = envelop({
plugins: [
// ... other plugins
useGraphQLIp(process.env.NODE_ENV === 'development'),
]
})
import { useGraphQLIp } from 'graphql-ip'
import { envelop } from '@envelop/core'
const getEnveloped = envelop({
plugins: [
// ... other plugins
useGraphQLIp(false), // false for production, true for local development
]
})
const resolvers = {
Query: {
getClientInfo: (parent, args, context) => {
return `Client connected from: ${context.ip}`
}
}
}
// Local development mode
useGraphQLIp(true) // Provides fallback to 127.0.0.1 and console logging
// Production mode
useGraphQLIp(false) // Strict IP detection without fallbacks
import { createYoga } from 'graphql-yoga'
import { useGraphQLIp } from 'graphql-ip'
const yoga = createYoga({
plugins: [
useGraphQLIp(process.env.NODE_ENV === 'development')
]
})
import { ApolloServer } from '@apollo/server'
import { envelop, useApolloTracing } from '@envelop/core'
import { useGraphQLIp } from 'graphql-ip'
const getEnveloped = envelop({
plugins: [
useApolloTracing(),
useGraphQLIp(false)
]
})
The plugin checks for IP addresses in the following order of priority:
x-forwarded-for
(first IP in comma-separated list)x-real-ip
x-client-ip
x-forwarded
x-cluster-client-ip
forwarded-for
forwarded
cf-connecting-ip
(Cloudflare)true-client-ip
(Cloudflare Enterprise)x-original-forwarded-for
request.ip
request.ips[0]
request.socket.remoteAddress
request.connection.remoteAddress
- IPv6 Prefix Cleaning: Automatically removes
::ffff:
prefix from IPv4-mapped IPv6 addresses - Array Header Support: Handles headers that come as arrays (takes first value)
- Headers Object Support: Works with both
Headers
instances and plain objects - Graceful Fallbacks: Returns 'unknown' when no IP can be determined
The plugin provides full TypeScript support with proper type definitions:
import type { GraphQLContextWithIp } from 'graphql-ip'
// Your context will automatically include the 'ip' property
const resolver = (parent, args, context: GraphQLContextWithIp) => {
console.log(context.ip) // TypeScript knows this exists
}
Creates the GraphQL IP plugin.
Parameters:
isLocal
(optional):boolean
- Enable development mode with console logging and localhost fallback
Returns: Plugin
- Envelop plugin instance
export interface GraphQLContextWithIp {
ip: string
}
export interface RequestLike {
headers: Headers | Record<string, string | string[] | undefined>
socket?: { remoteAddress?: string }
connection?: { remoteAddress?: string }
ip?: string
ips?: string[]
}
export interface ContextWithRequest {
request?: RequestLike
}
Contributions are welcome! Please feel free to submit a Pull Request.
MIT © Kaan Mert Ağyol