storj/satellite/console/consoleweb/utils.go
Wilfred Asomani 516241e406 cmd,satellite: remove Graphql code and dependencies
This change removes unused GraphQL code. It also updates storj sim code
to use the GraphQL replacement HTTP endpoints and removes the GraphQL
dependency.

Issue: https://github.com/storj/storj/issues/6142

Change-Id: Ie502553706c4b1282cd883a9275ea7332b8fc92d
2023-08-22 12:23:14 +00:00

134 lines
3.9 KiB
Go

// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package consoleweb
import (
"fmt"
"mime"
"net/http"
"regexp"
"strings"
"storj.io/common/memory"
)
// ContentLengthLimit describes 4KB limit.
const ContentLengthLimit = 4 * memory.KB
func init() {
err := mime.AddExtensionType(".ttf", "font/ttf")
if err != nil {
panic(err.Error())
}
err = mime.AddExtensionType(".txt", "text/plain")
if err != nil {
panic(err.Error())
}
}
// getClientIPRegExp is used by the function getClientIP.
var getClientIPRegExp = regexp.MustCompile(`(?i:(?:^|;)for=([^,; ]+))`)
// getClientIP gets the IP of the proxy (that's the value of the field
// r.RemoteAddr) and the client from the first exiting header in this order:
// 'Forwarded', 'X-Forwarded-For', or 'X-Real-Ip'.
// It returns a string of the format "{{proxy ip}} ({{client ip}})" or if there
// isn't any of those headers then it returns "{{client ip}}" where "client ip"
// is the value of the field r.RemoteAddr.
//
// The 'for' field of the 'Forwarded' may contain the IP with a port, as defined
// in the RFC 7239. When the header contains the IP with a port, the port is
// striped, so only the IP is returned.
//
// NOTE: it doesn't check that the IP value get from wherever source is a well
// formatted IP v4 nor v6; an invalid formatted IP will return an undefined
// result.
func getClientIP(r *http.Request) string {
requestIPs := func(clientIP string) string {
return fmt.Sprintf("%s (%s)", r.RemoteAddr, clientIP)
}
h := r.Header.Get("Forwarded")
if h != "" {
// Get the first value of the 'for' identifier present in the header because
// its the one that contains the client IP.
// see: https://datatracker.ietf.org/doc/html/rfc7230
matches := getClientIPRegExp.FindStringSubmatch(h)
if len(matches) > 1 {
ip := strings.Trim(matches[1], `"`)
ip = stripPort(ip)
if ip[0] == '[' {
ip = ip[1 : len(ip)-1]
}
return requestIPs(ip)
}
}
h = r.Header.Get("X-Forwarded-For")
if h != "" {
// Get the first the value IP because it's the client IP.
// Header sysntax: X-Forwarded-For: <client>, <proxy1>, <proxy2>
// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For
ips := strings.SplitN(h, ",", 2)
if len(ips) > 0 {
return requestIPs(ips[0])
}
}
h = r.Header.Get("X-Real-Ip")
if h != "" {
// Get the value of the header because its value is just the client IP.
// This header is mostly sent by NGINX.
// See https://www.nginx.com/resources/wiki/start/topics/examples/forwarded/
return requestIPs(h)
}
return r.RemoteAddr
}
// stripPort strips the port from addr when it has it and return the host
// part. A host can be a hostname or an IP v4 or an IP v6.
//
// NOTE: this function expects a well-formatted address. When it's hostname or
// IP v4, the port at the end and separated with a colon, nor hostname or IP can
// have colons; when it's a IP v6 with port the IP part is enclosed with square
// brackets (.i.e []) and the port separated with a colon, otherwise the IP
// isn't enclosed by square brackets.
// An invalid addr produce an unspecified value.
func stripPort(addr string) string {
// Ensure to strip the port out if r.RemoteAddr has it.
// We don't use net.SplitHostPort because the function returns an error if the
// address doesn't contain the port and the returned host is an empty string,
// besides it doesn't return an error that can be distinguished from others
// unless that the error message is compared, which is discouraging.
if addr == "" {
return ""
}
// It's an IP v6 with port.
if addr[0] == '[' {
idx := strings.LastIndex(addr, ":")
if idx <= 1 {
return addr
}
return addr[1 : idx-1]
}
// It's a IP v4 with port.
if strings.Count(addr, ":") == 1 {
idx := strings.LastIndex(addr, ":")
if idx < 0 {
return addr
}
return addr[0:idx]
}
// It's a IP v4 or v6 without port.
return addr
}