mirror of
https://github.com/lukaszraczylo/go-simple-graphql.git
synced 2026-10-14 00:58:32 +00:00
100 lines
3.5 KiB
Go
100 lines
3.5 KiB
Go
package gql
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
|
|
libpack_logger "github.com/lukaszraczylo/go-simple-graphql/logging"
|
|
"golang.org/x/net/http2"
|
|
)
|
|
|
|
func (b *BaseClient) createHttpClient() (*http.Client, error) {
|
|
// Optimized connection pool settings for better performance
|
|
httpTransport := &http.Transport{
|
|
MaxIdleConns: 100, // Reduced from 512
|
|
MaxConnsPerHost: 50, // Reduced from 512
|
|
MaxIdleConnsPerHost: 10, // Reduced from 512
|
|
IdleConnTimeout: 30 * time.Second, // Increased for better reuse
|
|
ResponseHeaderTimeout: 10 * time.Second, // Reduced for faster timeouts
|
|
DisableKeepAlives: false,
|
|
DisableCompression: true, // Disable automatic request compression to prevent "trailing garbage" errors
|
|
WriteBufferSize: 4096, // Optimize buffer size
|
|
ReadBufferSize: 4096, // Optimize buffer size
|
|
}
|
|
|
|
var http_client *http.Client
|
|
|
|
// Protect read of endpoint field
|
|
b.mu.RLock()
|
|
endpoint := b.endpoint
|
|
b.mu.RUnlock()
|
|
|
|
if strings.HasPrefix(endpoint, "http://") {
|
|
http_client = &http.Client{
|
|
Timeout: 30 * time.Second, // Increased for better reliability
|
|
Transport: httpTransport,
|
|
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
|
return http.ErrUseLastResponse
|
|
},
|
|
}
|
|
b.Logger.Debug(&libpack_logger.LogMessage{
|
|
Message: "Using HTTP/1.1 over http",
|
|
Pairs: nil,
|
|
})
|
|
} else if strings.HasPrefix(endpoint, "https://") {
|
|
tlsClientConfig := getHTTPClientTLSConfig()
|
|
if strings.HasPrefix(endpoint, "https://") && tlsClientConfig.InsecureSkipVerify {
|
|
b.Logger.Warning(&libpack_logger.LogMessage{
|
|
Message: "TLS certificate verification is disabled. This is insecure and should not be used in production.",
|
|
})
|
|
}
|
|
http2Transport := &http2.Transport{
|
|
AllowHTTP: true,
|
|
TLSClientConfig: tlsClientConfig,
|
|
ReadIdleTimeout: 30 * time.Second, // Increased for better reuse
|
|
PingTimeout: 10 * time.Second, // Reduced for faster detection
|
|
WriteByteTimeout: 10 * time.Second, // Add write timeout
|
|
DisableCompression: true, // Disable automatic request compression to prevent "trailing garbage" errors
|
|
}
|
|
http_client = &http.Client{
|
|
Timeout: 30 * time.Second, // Increased for better reliability
|
|
Transport: http2Transport,
|
|
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
|
return http.ErrUseLastResponse
|
|
},
|
|
}
|
|
b.Logger.Debug(&libpack_logger.LogMessage{
|
|
Message: "Using HTTP/2 over https",
|
|
Pairs: nil,
|
|
})
|
|
} else {
|
|
b.Logger.Critical(&libpack_logger.LogMessage{
|
|
Message: "Invalid endpoint - neither http or https",
|
|
})
|
|
// Return error instead of nil to prevent nil pointer dereference
|
|
return nil, fmt.Errorf("invalid endpoint: %s - must start with http:// or https://", endpoint)
|
|
}
|
|
return http_client, nil
|
|
}
|
|
|
|
// getHTTPClientTLSConfig returns TLS configuration for HTTP client
|
|
// By default, TLS verification is enabled for security.
|
|
// Set GRAPHQL_INSECURE_SKIP_VERIFY=true to disable verification (NOT RECOMMENDED for production)
|
|
func getHTTPClientTLSConfig() *tls.Config {
|
|
skipVerify := os.Getenv("GRAPHQL_INSECURE_SKIP_VERIFY") == "true"
|
|
|
|
if skipVerify {
|
|
// Log warning to stderr when running in insecure mode
|
|
fmt.Fprintf(os.Stderr, "WARNING: TLS certificate verification is disabled. This is insecure and should not be used in production.\n")
|
|
}
|
|
|
|
return &tls.Config{
|
|
InsecureSkipVerify: skipVerify,
|
|
MinVersion: tls.VersionTLS12, // Enforce minimum TLS 1.2 for security
|
|
}
|
|
}
|