Skip to content

Commit 412bc9b

Browse files
committed
Update README with enhanced IP detection features
Introduce detailed descriptions of the module's IP detection capabilities, including IPv4 and IPv6 support, header customization, and integration options. Add sections for best practices, troubleshooting, and supported headers.
1 parent c9371d0 commit 412bc9b

File tree

1 file changed

+79
-30
lines changed

1 file changed

+79
-30
lines changed

README.md

Lines changed: 79 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,18 @@
99
[![GolangCI Lint](https://github.com/dmitrymomot/clientip/actions/workflows/golangci-lint.yml/badge.svg)](https://github.com/dmitrymomot/clientip/actions/workflows/golangci-lint.yml)
1010
[![Go Report Card](https://goreportcard.com/badge/github.com/dmitrymomot/clientip)](https://goreportcard.com/report/github.com/dmitrymomot/clientip)
1111

12-
This Go module provides functionality to accurately determine a client's IP address from HTTP requests, considering various headers that might contain the real IP address, especially when your application is behind a proxy or load balancer.
12+
A lightweight, production-ready Go module for accurately determining client IP addresses in HTTP applications. Particularly useful for applications behind proxies, load balancers, or CDNs like Cloudflare, DigitalOcean App Platform, and Fastly.
1313

1414
## Features
1515

16-
- **LookupFromRequest**: Retrieve the client IP address directly from an HTTP request with consideration for custom headers.
17-
- **Middleware**: An easy-to-integrate middleware function for HTTP servers that automatically sets the `RemoteAddr` field of the request to the client's real IP address.
16+
- **Accurate IP Detection**: Intelligently extracts client IPs from various standard and vendor-specific headers
17+
- **IPv4 & IPv6 Support**: Full support for both IPv4 and IPv6 addresses with proper canonicalization
18+
- **Flexible Header Configuration**: Use default headers or specify custom ones for your specific setup
19+
- **Multiple Integration Options**:
20+
- Direct IP lookup function for manual integration
21+
- Drop-in middleware for automatic IP detection
22+
- Context-based IP storage for thread-safe access
23+
- **Production-Ready**: Used in production environments with comprehensive test coverage
1824

1925
## Installation
2026

@@ -26,64 +32,107 @@ go get github.com/dmitrymomot/clientip
2632

2733
## Usage
2834

29-
### LookupFromRequest Function
30-
31-
`LookupFromRequest` retrieves the client IP address from the provided HTTP request. It checks a list of headers for the IP address and uses a default set if none are specified.
35+
### Direct IP Lookup
3236

3337
```go
34-
import "github.com/dmitrymomot/clientip"
35-
3638
func handler(w http.ResponseWriter, r *http.Request) {
37-
clientIP := clientip.LookupFromRequest(r)
38-
fmt.Fprintf(w, "Client IP: %s", clientIP)
39+
// Use default headers
40+
ip := clientip.LookupFromRequest(r)
41+
42+
// Or specify custom headers
43+
ip = clientip.LookupFromRequest(r, "X-Custom-IP", "X-Real-IP")
44+
45+
fmt.Fprintf(w, "Your IP: %s", ip)
3946
}
4047
```
4148

42-
With custom headers:
49+
### Middleware Integration
4350

4451
```go
45-
import "github.com/dmitrymomot/clientip"
52+
func main() {
53+
mux := http.NewServeMux()
4654

47-
func handler(w http.ResponseWriter, r *http.Request) {
48-
clientIP := clientip.LookupFromRequest(r, "X-Custom-Real-IP")
49-
fmt.Fprintf(w, "Client IP: %s", clientIP)
55+
// Basic middleware usage with default headers
56+
handler := clientip.Middleware()(mux)
57+
58+
// Or with custom headers
59+
handler = clientip.Middleware("X-Custom-IP", "CF-Connecting-IP")(mux)
60+
61+
http.ListenAndServe(":8080", handler)
5062
}
5163
```
5264

53-
### Middleware
54-
55-
The `Middleware` function returns a middleware handler that modifies the request's `RemoteAddr` based on the client IP address found in the specified headers.
65+
### Context-Based IP Access
5666

5767
```go
58-
import (
59-
"net/http"
60-
"github.com/dmitrymomot/clientip"
61-
)
62-
6368
func main() {
6469
mux := http.NewServeMux()
65-
mux.HandleFunc("/", handler)
6670

67-
// Init the middleware with custom header. If not specified, the default headers are used.
68-
mdw := clientip.Middleware("X-Custom-Real-IP")
71+
// Chain both middlewares
72+
handler := clientip.Middleware()(mux)
73+
handler = clientip.IpToContext(handler) // Store IP in context, it must be called after Middleware
6974

70-
http.ListenAndServe(":8080", mdw(mux))
75+
http.ListenAndServe(":8080", handler)
7176
}
7277

7378
func handler(w http.ResponseWriter, r *http.Request) {
74-
// The RemoteAddr now contains the real client IP
75-
fmt.Fprintf(w, "Client IP: %s", r.RemoteAddr)
79+
// Get IP from context anywhere in your handler chain
80+
if ip := clientip.GetIPAddress(r.Context()); ip != "" {
81+
fmt.Fprintf(w, "Your IP from context: %s", ip)
82+
}
7683
}
7784
```
7885

86+
### Supported Headers
87+
88+
The module checks the following headers by default (in order):
89+
90+
- `DO_Connecting-IP`, `DO-Connecting-IP` (DigitalOcean)
91+
- `True-Client-IP`
92+
- `X-Real-IP`
93+
- `CF-Connecting-IP` (Cloudflare)
94+
- `Fastly-Client-IP`
95+
- `X-Cluster-Client-IP`
96+
- `X-Client-IP`
97+
- `X-Forwarded-For` (first IP in the chain)
98+
99+
You can override these by providing your own headers to the functions.
100+
79101
## Customization
80102

81103
Both `LookupFromRequest` and `Middleware` functions accept an optional list of headers to consider when looking for the client IP address. By default, a predefined set of common headers used for forwarding client IPs in proxy setups are checked.
82104

105+
## Best Practices
106+
107+
- **Security**: Always validate and sanitize IP addresses before using them in security-critical contexts
108+
- **Header Order**: Configure headers in order of trust (most trusted first)
109+
- **Performance**: Use the middleware approach for consistent IP handling across your application
110+
- **Context Usage**: Prefer context-based IP access when working with complex handler chains
111+
112+
## Troubleshooting
113+
114+
### Common Issues
115+
116+
1. **Empty IP Address**
117+
118+
- Check if your proxy/load balancer is properly configured to forward IP headers
119+
- Verify the header names match your infrastructure setup
120+
121+
2. **Incorrect IP Address**
122+
123+
- Ensure headers are being set in the correct order of precedence
124+
- Check if intermediate proxies are modifying the headers
125+
126+
3. **IPv6 Handling**
127+
- The module automatically canonicalizes IPv6 addresses to their /64 prefix
128+
- If you need the full address, use the raw header value instead
129+
130+
For more help, please open an issue on GitHub.
131+
83132
## Contributing
84133

85134
If you wish to contribute to this project, please fork the repository and submit a pull request.
86135

87136
## License
88137

89-
This project is licensed under the [Apache 2.0](LICENSE) - see the `LICENSE` file for details.
138+
This project is licensed under the [Apache 2.0](LICENSE) - see the `LICENSE` file for details.

0 commit comments

Comments
 (0)