A powerful Go library that converts cURL commands into Go HTTP requests with full feature compatibility.
- Based on the robust requests library
- Seamlessly transform cURL bash commands to Go code
- Inherits all cURL functionality while adding Go's flexibility for configuration, cookies, headers, and URL handling
- Supports both Bash and Windows Cmd cURL formats
- Production-ready with comprehensive test coverage
- π Complete cURL command parsing - Parse any cURL command to Go requests
- π§ Full cURL compatibility - Support for all major cURL options
- π File output support - Save responses to files with
-o,-O,--output-dir,--create-dirs,-Ccontinue - π Authentication - Basic auth, digest auth, and bearer tokens (
--oauth2-bearer) - π HTTP protocol control - HTTP/1.0, HTTP/1.1, HTTP/2 support
- πͺ Cookie management - Full cookie handling and session persistence
- π Form data & file uploads - Multipart forms and file uploads with remote header names (
-J) - π Redirect handling - Automatic redirect following with limits
- β±οΈ Timeout controls - Connection and request timeouts
- π Proxy support - HTTP/HTTPS/SOCKS5 proxy configuration with authentication
- π‘οΈ SSL/TLS options - Custom certificates and SSL verification control
- π― Debug output - Detailed debugging information like cURL
-v - π Script features - Write-out formats (
-w), fail on errors (-f), silent mode (-s) - π DNS resolution control - Custom host resolution with
--resolve - π Connection redirection - Advanced connection control with
--connect-to - π GET mode with data - Convert POST data to query parameters with
-G/--get
go get github.com/474420502/gcurl@v1.2.0Transform any cURL command into Go code instantly:
package main
import (
"fmt"
"log"
"github.com/474420502/gcurl"
)
func main() {
// Parse any cURL command
curl, err := gcurl.Parse(`curl -H "Accept: application/json" https://httpbin.org/get`)
if err != nil {
log.Fatal(err)
}
// Execute the request
resp, err := curl.Request().Execute()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Status: %d\n", resp.GetStatusCode())
fmt.Printf("Response: %s\n", resp.ContentString())
}Transform cURL commands with custom headers:
package main
import (
"fmt"
"log"
"github.com/474420502/gcurl"
)
func main() {
// Parse cURL command with multiple headers
curlCmd := `curl "https://httpbin.org/get" \
-H "Accept: application/json" \
-H "User-Agent: MyApp/1.0" \
-H "Authorization: Bearer token123"`
curl, err := gcurl.Parse(curlCmd)
if err != nil {
log.Fatal(err)
}
// Create session and execute
session := curl.CreateSession()
resp, err := curl.CreateRequest(session).Execute()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Status: %d\n", resp.GetStatusCode())
fmt.Printf("Headers sent: %v\n", session.GetHeader())
fmt.Printf("Response: %s\n", resp.ContentString())
}Handle POST requests with JSON payload:
package main
import (
"fmt"
"log"
"github.com/474420502/gcurl"
)
func main() {
curlCmd := `curl -X POST "https://httpbin.org/post" \
-H "Content-Type: application/json" \
-d '{"name":"John Doe","email":"john@example.com","age":30}'`
curl, err := gcurl.Parse(curlCmd)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Method: %s\n", curl.Method)
fmt.Printf("Content-Type: %s\n", curl.ContentType)
fmt.Printf("Request Body: %s\n", curl.Body.Content)
resp, err := curl.Request().Execute()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Response Status: %d\n", resp.GetStatusCode())
fmt.Printf("Response: %s\n", resp.ContentString())
}Upload files using multipart form data:
package main
import (
"fmt"
"log"
"os"
"github.com/474420502/gcurl"
)
func main() {
// Create a test file
testFile := "/tmp/sample.txt"
err := os.WriteFile(testFile, []byte("This is a test file content"), 0644)
if err != nil {
log.Fatal(err)
}
defer os.Remove(testFile)
curlCmd := fmt.Sprintf(`curl -X POST "https://httpbin.org/post" \
-F "file=@%s" \
-F "name=John" \
-F "description=Sample file upload"`, testFile)
curl, err := gcurl.Parse(curlCmd)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Form upload with %d fields\n", len(curl.Body.Forms))
resp, err := curl.Request().Execute()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Upload Status: %d\n", resp.GetStatusCode())
fmt.Printf("Response: %s\n", resp.ContentString())
}Save responses to files with various output configurations:
package main
import (
"fmt"
"log"
"os"
"github.com/474420502/gcurl"
)
func main() {
examples := []struct {
name string
command string
description string
}{
{
name: "Save to specific file",
command: `curl -o /tmp/response.json https://httpbin.org/json`,
description: "Save response to a specific file",
},
{
name: "Use remote filename",
command: `curl -O https://httpbin.org/robots.txt`,
description: "Use the remote filename (robots.txt)",
},
{
name: "Save to directory",
command: `curl -O --output-dir /tmp/downloads --create-dirs https://httpbin.org/uuid`,
description: "Save to specific directory, create if needed",
},
{
name: "Resume download",
command: `curl -C 1024 -o /tmp/partial.dat https://httpbin.org/bytes/2048`,
description: "Resume download from byte offset 1024",
},
{
name: "Auto-resume",
command: `curl -C - -o /tmp/auto_resume.dat https://httpbin.org/bytes/4096`,
description: "Auto-detect existing file size and resume",
},
}
for i, example := range examples {
fmt.Printf("\n%d. %s\n", i+1, example.name)
fmt.Printf(" Description: %s\n", example.description)
fmt.Printf(" Command: %s\n", example.command)
curl, err := gcurl.Parse(example.command)
if err != nil {
fmt.Printf(" β Parse error: %v\n", err)
continue
}
// Show parsed configuration
if curl.OutputFile != "" {
fmt.Printf(" π Output file: %s\n", curl.OutputFile)
}
if curl.RemoteName {
fmt.Printf(" π Using remote filename\n")
}
if curl.OutputDir != "" {
fmt.Printf(" π Output directory: %s\n", curl.OutputDir)
}
if curl.ContinueAt > 0 {
fmt.Printf(" β© Resume from byte: %d\n", curl.ContinueAt)
} else if curl.ContinueAt == -1 {
fmt.Printf(" π Auto-resume enabled\n")
}
fmt.Printf(" β
Configuration parsed successfully\n")
}
}Handle various authentication scenarios:
package main
import (
"fmt"
"log"
"github.com/474420502/gcurl"
)
func main() {
authExamples := []struct {
name string
command string
description string
}{
{
name: "Basic Authentication",
command: `curl -u "username:password" "https://httpbin.org/basic-auth/username/password"`,
description: "HTTP Basic Authentication",
},
{
name: "Digest Authentication",
command: `curl --digest -u "user:pass" "https://httpbin.org/digest-auth/auth/user/pass"`,
description: "HTTP Digest Authentication",
},
{
name: "Bearer Token",
command: `curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" "https://httpbin.org/bearer"`,
description: "Bearer token authentication",
},
{
name: "API Key Header",
command: `curl -H "X-API-Key: your-api-key-here" "https://httpbin.org/get"`,
description: "API Key in custom header",
},
}
for i, example := range authExamples {
fmt.Printf("\n%d. %s\n", i+1, example.name)
fmt.Printf(" Description: %s\n", example.description)
fmt.Printf(" Command: %s\n", example.command)
curl, err := gcurl.Parse(example.command)
if err != nil {
fmt.Printf(" β Parse error: %v\n", err)
continue
}
// Show authentication configuration
if curl.Auth != nil {
fmt.Printf(" π Basic auth configured\n")
}
if curl.DigestAuth != nil {
fmt.Printf(" π Digest auth configured\n")
}
if len(curl.Headers) > 0 {
fmt.Printf(" π Headers configured: %d\n", len(curl.Headers))
}
fmt.Printf(" β
Authentication parsed successfully\n")
}
}Control HTTP protocol versions:
package main
import (
"fmt"
"log"
"github.com/474420502/gcurl"
)
func main() {
versionExamples := []struct {
name string
command string
version string
}{
{
name: "HTTP/1.0",
command: `curl --http1.0 https://httpbin.org/get`,
version: "HTTP/1.0",
},
{
name: "HTTP/1.1",
command: `curl --http1.1 https://httpbin.org/get`,
version: "HTTP/1.1",
},
{
name: "HTTP/2",
command: `curl --http2 https://httpbin.org/get`,
version: "HTTP/2",
},
{
name: "Auto-detect",
command: `curl https://httpbin.org/get`,
version: "Auto",
},
}
fmt.Println("HTTP Version Control Examples:")
fmt.Println("==============================")
for i, example := range versionExamples {
fmt.Printf("\n%d. %s\n", i+1, example.name)
fmt.Printf(" Command: %s\n", example.command)
curl, err := gcurl.Parse(example.command)
if err != nil {
fmt.Printf(" β Parse error: %v\n", err)
continue
}
fmt.Printf(" π HTTP Version: %s\n", curl.HTTPVersion.String())
fmt.Printf(" β
Version control configured\n")
}
}Get detailed debugging information like cURL's verbose mode:
package main
import (
"fmt"
"log"
"github.com/474420502/gcurl"
)
func main() {
curlCmd := `curl -v -X POST https://api.example.com/data \
-H "Content-Type: application/json" \
-H "Authorization: Bearer token123" \
-H "User-Agent: MyApp/2.0" \
-d '{"action":"create","data":{"name":"test"}}'`
curl, err := gcurl.Parse(curlCmd)
if err != nil {
log.Fatal(err)
}
fmt.Println("=== Curl Command Parsed ===")
fmt.Printf("URL: %s\n", curl.ParsedURL.String())
fmt.Printf("Method: %s\n", curl.Method)
fmt.Printf("Verbose Mode: %v\n", curl.Verbose)
fmt.Println("\n=== Debug Output (like curl -v) ===")
fmt.Println(curl.Debug())
fmt.Println("\n=== Verbose Info Simulation ===")
fmt.Println(curl.VerboseInfo())
fmt.Println("\n=== Quick Summary ===")
fmt.Println(curl.Summary())
}Reuse sessions for multiple requests:
package main
import (
"fmt"
"log"
"time"
"net/http"
"github.com/474420502/gcurl"
)
func main() {
// First request: login and get session cookie
loginCmd := `curl -X POST "https://httpbin.org/cookies/set/sessionid/abc123" \
-H "Content-Type: application/json" \
-d '{"username":"testuser","password":"testpass"}'`
// Second request: use the session
dataCmd := `curl "https://httpbin.org/cookies" \
-H "Accept: application/json"`
// Parse both commands
loginCurl, err := gcurl.Parse(loginCmd)
if err != nil {
log.Fatal(err)
}
dataCurl, err := gcurl.Parse(dataCmd)
if err != nil {
log.Fatal(err)
}
// Create a shared session
session := loginCurl.CreateSession()
// Customize session with timeout and custom headers
session.Config().SetTimeout(30 * time.Second)
customHeaders := make(http.Header)
customHeaders.Set("X-Client-Version", "v2.0")
customHeaders.Set("X-Request-ID", "req-12345")
session.SetHeader(customHeaders)
fmt.Println("=== Executing Login Request ===")
loginResp, err := loginCurl.CreateRequest(session).Execute()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Login Status: %d\n", loginResp.GetStatusCode())
fmt.Println("\n=== Executing Data Request (with session) ===")
dataResp, err := dataCurl.CreateRequest(session).Execute()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Data Status: %d\n", dataResp.GetStatusCode())
fmt.Printf("Response: %s\n", dataResp.ContentString())
fmt.Println("\n=== Session cookies were automatically shared ===")
}// Create multiple cURL parsers
curl1, _ := gcurl.Parse(`curl "https://httpbin.org/cookies/set/session/123"`)
curl2, _ := gcurl.Parse(`curl "https://httpbin.org/cookies"`)
curl3, _ := gcurl.Parse(`curl "https://httpbin.org/user-agent"`)
// Create a shared session for connection pooling and cookie persistence
session := curl1.CreateSession()
// Execute all requests with the same session
resp1, _ := curl1.CreateRequest(session).Execute()
resp2, _ := curl2.CreateRequest(session).Execute() // Cookies from resp1 are available
resp3, _ := curl3.CreateRequest(session).Execute() // Same session, connection reuse// For one-off requests, use direct execution
curl, _ := gcurl.Parse(`curl "https://httpbin.org/get"`)
resp, err := curl.Request().Execute() // Auto-creates sessioncurl, _ := gcurl.Parse(`curl "https://httpbin.org/delay/2"`)
session := curl.CreateSession()
// Configure timeouts
session.Config().SetTimeout(10 * time.Second)
// Add custom headers to all requests in this session
headers := make(http.Header)
headers.Set("X-Client-ID", "my-app")
headers.Set("X-API-Version", "v2")
session.SetHeader(headers)
// Use the customized session
resp, err := curl.CreateRequest(session).Execute()Demonstrate script automation features like write-out formats, fail on errors, and silent mode:
package main
import (
"fmt"
"log"
"github.com/474420502/gcurl"
)
func main() {
scriptExamples := []struct {
name string
command string
description string
}{
{
name: "Write-out HTTP Code",
command: `curl -w "%{http_code}" -s -o /dev/null https://httpbin.org/get`,
description: "Get just the HTTP status code",
},
{
name: "Write-out Response Time",
command: `curl -w "Time: %{time_total}s\nSize: %{size_download} bytes\n" -s -o /dev/null https://httpbin.org/get`,
description: "Get timing and size information",
},
{
name: "Fail on HTTP Errors",
command: `curl -f https://httpbin.org/status/404`,
description: "Fail and exit on HTTP 4xx/5xx errors",
},
{
name: "Silent Mode with JSON",
command: `curl -s https://httpbin.org/json`,
description: "Silent mode - no progress or error info",
},
{
name: "Remote Header Name for Downloads",
command: `curl -J -O https://httpbin.org/response-headers?Content-Disposition=attachment;filename=test.json`,
description: "Use filename from Content-Disposition header",
},
}
fmt.Println("Script Features Examples:")
fmt.Println("=========================")
for i, example := range scriptExamples {
fmt.Printf("\n%d. %s\n", i+1, example.name)
fmt.Printf(" Description: %s\n", example.description)
fmt.Printf(" Command: %s\n", example.command)
curl, err := gcurl.Parse(example.command)
if err != nil {
fmt.Printf(" β Parse error: %v\n", err)
continue
}
// Show parsed script features
if curl.WriteOut != "" {
fmt.Printf(" π Write-out format: %s\n", curl.WriteOut)
}
if curl.FailOnError {
fmt.Printf(" π« Fail on HTTP errors: enabled\n")
}
if curl.Silent {
fmt.Printf(" π Silent mode: enabled\n")
}
if curl.RemoteHeaderName {
fmt.Printf(" π Remote header name: enabled\n")
}
fmt.Printf(" β
Script features configured\n")
}
}Master DNS resolution for testing and development scenarios:
package main
import (
"fmt"
"log"
"strings"
"github.com/474420502/gcurl"
)
func main() {
resolutionExamples := []struct {
name string
command string
description string
}{
{
name: "Local Development",
command: `curl -v https://api.production.com/health --resolve api.production.com:443:127.0.0.1`,
description: "Test production API locally without modifying /etc/hosts",
},
{
name: "Load Balancing Test",
command: `curl https://service.com/status --resolve service.com:443:10.0.1.100,10.0.1.101`,
description: "Test multiple backend servers",
},
{
name: "Staging Environment",
command: `curl -H "X-Env: staging" https://api.myapp.com/version --resolve api.myapp.com:443:staging.internal.com`,
description: "Point production domain to staging server",
},
{
name: "Force Override",
command: `curl --resolve +problematic.service.com:443:127.0.0.1 https://problematic.service.com/debug`,
description: "Force override DNS resolution (+ prefix)",
},
{
name: "Multi-Port Service",
command: `curl https://service.com/api --resolve service.com:80:192.168.1.10 --resolve service.com:443:192.168.1.11`,
description: "Different servers for HTTP and HTTPS",
},
}
fmt.Println("DNS Resolution Control Examples:")
fmt.Println("=================================")
for i, example := range resolutionExamples {
fmt.Printf("\n%d. %s\n", i+1, example.name)
fmt.Printf(" Description: %s\n", example.description)
fmt.Printf(" Command: %s\n", example.command)
curl, err := gcurl.Parse(example.command)
if err != nil {
fmt.Printf(" β Parse error: %v\n", err)
continue
}
// Show DNS resolution mappings
fmt.Printf(" π URL: %s\n", curl.ParsedURL.String())
if len(curl.Resolve) > 0 {
fmt.Printf(" π DNS Resolutions:\n")
for j, resolve := range curl.Resolve {
fmt.Printf(" [%d] %s\n", j+1, resolve)
}
}
// Show verbose output if enabled
if curl.Verbose {
fmt.Printf(" π Verbose Output Preview:\n")
verboseLines := strings.Split(curl.VerboseInfo(), "\n")
for k, line := range verboseLines[:min(5, len(verboseLines))] {
if strings.TrimSpace(line) != "" {
fmt.Printf(" %s\n", line)
}
if k >= 4 {
fmt.Printf(" ... (truncated)\n")
break
}
}
}
fmt.Printf(" β
DNS resolution configured\n")
}
fmt.Println("\nπ― Key Benefits of --resolve:")
fmt.Println(" β’ No need to modify /etc/hosts for testing")
fmt.Println(" β’ Perfect for local development and staging")
fmt.Println(" β’ Load balancer and failover testing")
fmt.Println(" β’ Debugging problematic DNS issues")
fmt.Println(" β’ Works seamlessly with -v for detailed output")
}
// min helper function
func min(a, b int) int {
if a < b {
return a
}
return b
}Control connection routing for testing and debugging:
package main
import (
"fmt"
"log"
"github.com/474420502/gcurl"
)
func main() {
connectionExamples := []struct {
name string
command string
description string
}{
{
name: "Local Development",
command: `curl -v https://api.production.com/users --connect-to api.production.com:443:localhost:3000`,
description: "Redirect production API to local development server",
},
{
name: "Load Balancer Testing",
command: `curl https://service.com/health --connect-to service.com:443:backend-1.internal:8080`,
description: "Test specific backend server bypassing load balancer",
},
{
name: "Proxy All Traffic",
command: `curl https://example.com/test --connect-to ::proxy.company.com:8080`,
description: "Route all connections through proxy server",
},
{
name: "Multi-Environment Testing",
command: `curl https://app.company.com/api --connect-to app.company.com:443:staging.internal.com:443`,
description: "Point production domain to staging environment",
},
}
fmt.Println("Connection Redirection Examples:")
fmt.Println("=================================")
for i, example := range connectionExamples {
fmt.Printf("\n%d. %s\n", i+1, example.name)
fmt.Printf(" Description: %s\n", example.description)
fmt.Printf(" Command: %s\n", example.command)
curl, err := gcurl.Parse(example.command)
if err != nil {
fmt.Printf(" β Parse error: %v\n", err)
continue
}
// Show connection redirection details
fmt.Printf(" π Target URL: %s\n", curl.ParsedURL.String())
if len(curl.ConnectTo) > 0 {
fmt.Printf(" π Connection Redirections:\n")
for j, redirect := range curl.ConnectTo {
fmt.Printf(" [%d] %s\n", j+1, redirect)
}
}
// Show verbose output if enabled
if curl.Verbose {
fmt.Printf(" π Verbose Output Preview:\n")
verboseLines := strings.Split(curl.VerboseInfo(), "\n")
for k, line := range verboseLines[:min(4, len(verboseLines))] {
if strings.TrimSpace(line) != "" {
fmt.Printf(" %s\n", line)
}
if k >= 3 {
fmt.Printf(" ... (truncated)\n")
break
}
}
}
fmt.Printf(" β
Connection redirection configured\n")
}
fmt.Println("\nπ― Key Benefits of --connect-to:")
fmt.Println(" β’ Redirect connections without DNS changes")
fmt.Println(" β’ Perfect for load balancer testing")
fmt.Println(" β’ Local development with production domains")
fmt.Println(" β’ Staging environment validation")
fmt.Println(" β’ Works seamlessly with -v for debugging")
}
// min helper function
func min(a, b int) int {
if a < b {
return a
}
return b
}Convert POST data to query parameters for GET requests:
package main
import (
"fmt"
"log"
"github.com/474420502/gcurl"
)
func main() {
getModeExamples := []struct {
name string
command string
description string
}{
{
name: "Simple Search",
command: `curl -G -d "q=golang" -d "limit=10" https://api.github.com/search/repositories`,
description: "GitHub repository search with parameters",
},
{
name: "Complex Filters",
command: `curl -G -d "filters[status]=active" -d "filters[type]=user" https://api.example.com/users`,
description: "Complex filtering with nested parameters",
},
{
name: "Analytics Query",
command: `curl -G -d "start_date=2023-01-01" -d "end_date=2023-12-31" -d "metrics=views,clicks" https://analytics.example.com/api`,
description: "Analytics data with date range and metrics",
},
{
name: "Pagination",
command: `curl -G -d "page=2" -d "per_page=50" -d "include=profile" https://api.example.com/users`,
description: "Paginated API request with includes",
},
}
fmt.Println("GET Mode with Data Examples:")
fmt.Println("============================")
for i, example := range getModeExamples {
fmt.Printf("\n%d. %s\n", i+1, example.name)
fmt.Printf(" Description: %s\n", example.description)
fmt.Printf(" Command: %s\n", example.command)
curl, err := gcurl.Parse(example.command)
if err != nil {
fmt.Printf(" β Parse error: %v\n", err)
continue
}
// Show GET mode details
fmt.Printf(" π Base URL: %s\n", curl.ParsedURL.String())
fmt.Printf(" π Method: %s\n", curl.Method)
fmt.Printf(" π GET Mode: %t\n", curl.GetMode)
// Show data conversion info
if curl.Body != nil {
fmt.Printf(" π Has data for query parameter conversion\n")
fmt.Printf(" π‘ Data will be appended as URL parameters when executed\n")
}
fmt.Printf(" β
GET mode configuration ready\n")
}
fmt.Println("\nπ― Key Benefits of -G/--get:")
fmt.Println(" β’ Convert POST data to query parameters")
fmt.Println(" β’ Perfect for API search and filtering")
fmt.Println(" β’ Maintains data structure in URLs")
fmt.Println(" β’ Compatible with caching and bookmarking")
fmt.Println(" β’ Ideal for analytics and reporting APIs")
}| Function | Description | Example |
|---|---|---|
gcurl.Parse(cmd string) |
Parse any cURL command | curl, err := gcurl.Parse("curl https://api.example.com") |
gcurl.ParseBash(cmd string) |
Parse Bash-style cURL | curl, err := gcurl.ParseBash("curl 'https://api.example.com'") |
gcurl.ParseCmd(cmd string) |
Parse Windows CMD-style | curl, err := gcurl.ParseCmd("curl \"https://api.example.com\"") |
| Method | Description | Return Type |
|---|---|---|
CreateSession() |
Create a new HTTP session | *requests.Session |
CreateRequest(session) |
Create request with session | *requests.Request |
Request() |
Create request (auto-session) | *requests.Request |
Debug() |
Get detailed debug info | string |
VerboseInfo() |
Get verbose output like curl -v |
string |
Summary() |
Get brief summary | string |
| Method | Description | Return Type |
|---|---|---|
GetStatusCode() |
HTTP status code | int |
Content() |
Response body as bytes | []byte |
ContentString() |
Response body as string | string |
GetHeader(key) |
Get response header | string |
GetHeaders() |
Get all response headers | http.Header |
| Category | cURL Option | Description | Status | Example |
|---|---|---|---|---|
| HTTP Methods | -X, --request |
HTTP method (GET, POST, etc.) | β | curl -X POST |
| Headers | -H, --header |
Custom headers | β | curl -H "Accept: application/json" |
| Request Body | -d, --data |
Send POST data | β | curl -d "name=value" |
--data-raw |
Send raw data | β | curl --data-raw '{"json":true}' |
|
--data-urlencode |
URL encode data | β | curl --data-urlencode "name=John Doe" |
|
-F, --form |
Multipart form data | β | curl -F "file=@path/file.txt" |
|
| Authentication | -u, --user |
Basic authentication | β | curl -u "user:pass" |
--digest |
Digest authentication | β | curl --digest -u "user:pass" |
|
| Cookies | -b, --cookie |
Send cookies | β | curl -b "session=abc123" |
-c, --cookie-jar |
Save cookies to file | β | curl -c cookies.txt |
|
| File Operations | -o, --output |
Write output to file | β | curl -o output.txt |
-O, --remote-name |
Use remote filename | β | curl -O |
|
--output-dir |
Output directory | β | curl --output-dir /downloads |
|
--create-dirs |
Create output directories | β | curl --create-dirs |
|
-C, --continue-at |
Resume/continue transfer | β | curl -C 1024 |
|
--remove-on-error |
Remove file on HTTP error | β | curl --remove-on-error |
|
| HTTP Versions | --http1.0 |
Force HTTP/1.0 | β | curl --http1.0 |
--http1.1 |
Force HTTP/1.1 | β | curl --http1.1 |
|
--http2 |
Force HTTP/2 | β | curl --http2 |
|
| Redirects | -L, --location |
Follow redirects | β | curl -L |
--max-redirs |
Maximum redirect count | β | curl --max-redirs 5 |
|
| Timeouts | --connect-timeout |
Connection timeout | β | curl --connect-timeout 10 |
--max-time |
Maximum total time | β | curl --max-time 30 |
|
| Proxy | --proxy |
Use proxy server | β | curl --proxy http://proxy:8080 |
--proxy-user |
Proxy authentication | β | curl --proxy-user "user:pass" |
|
| SSL/TLS | -k, --insecure |
Skip SSL verification | β | curl -k |
--cacert |
CA certificate file | β | curl --cacert ca.pem |
|
--cert |
Client certificate | β | curl --cert client.pem |
|
--key |
Client private key | β | curl --key client.key |
|
| Authentication | --oauth2-bearer |
OAuth2 Bearer token | β | curl --oauth2-bearer "token123" |
| Script Features | -w, --write-out |
Write-out format | β | curl -w "%{http_code}" |
-f, --fail |
Fail on HTTP errors | β | curl -f |
|
-J, --remote-header-name |
Use remote header filename | β | curl -J -O |
|
| Output Control | -v, --verbose |
Verbose output | β | curl -v |
-i, --include |
Include response headers | β | curl -i |
|
-I, --head |
HEAD request only | β | curl -I |
|
-s, --silent |
Silent mode | β | curl -s |
|
| User Agent | -A, --user-agent |
Set User-Agent | β | curl -A "MyApp/1.0" |
| Compression | --compressed |
Accept compressed response | β | curl --compressed |
| Range Requests | -r, --range |
Byte range request | β | curl -r 0-1023 |
| DNS Resolution | --resolve |
Custom host:port:address mapping | β | curl --resolve example.com:443:127.0.0.1 |
| Connection Control | --connect-to |
Connection redirection | β | curl --connect-to host:port:connect-host:connect-port |
| Data Conversion | -G, --get |
Convert POST data to GET query params | β | curl -G -d "q=search" https://api.example.com |
curl, _ := gcurl.Parse(`curl -v -X POST -H "Content-Type: application/json" -d '{"test":true}' https://api.example.com`)
// Get detailed debug information
fmt.Println("=== Debug Output ===")
fmt.Println(curl.Debug())
// Get verbose info (simulates curl -v)
fmt.Println("=== Verbose Output ===")
fmt.Println(curl.VerboseInfo())Sample Debug Output:
=== CURL Debug Information ===
Method: POST
URL: https://api.example.com
Scheme: https
Host: api.example.com
Path: /
Headers (1):
Content-Type: application/json
Body:
Type: raw
Length: 13 bytes
Content: {"test":true}
Network Configuration:
Timeout: 30s
HTTP Version: Auto
Debug Flags: verbose
===============================
| Issue | Symptom | Solution |
|---|---|---|
| URL not parsed | invalid or malformed URL |
Ensure URL is properly quoted:curl "https://example.com" |
| Headers ignored | Headers not sent | Check header format:curl -H "Key: Value" |
| File upload fails | Multipart parsing error | Verify file exists:curl -F "file=@/path/to/file" |
| Auth not working | 401 Unauthorized | Check credentials format:curl -u "user:password" |
| SSL errors | Certificate verification failed | Use -k to skip verification: curl -k https://... |
| Timeout issues | Request hangs | Set timeouts:curl --max-time 30 --connect-timeout 10 |
-
Always handle errors:
curl, err := gcurl.Parse(curlCommand) if err != nil { log.Printf("Parse error: %v", err) return }
-
Reuse sessions for multiple requests:
session := curl.CreateSession() // Use session for multiple requests to same host
-
Set appropriate timeouts:
session.Config().SetTimeout(30 * time.Second)
-
Use debug mode during development:
fmt.Println(curl.Debug()) // See parsed configuration
// Good: Reuse session for multiple requests
session := curl1.CreateSession()
resp1, _ := curl1.CreateRequest(session).Execute()
resp2, _ := curl2.CreateRequest(session).Execute() // Reuses connection
// Avoid: Creating new session for each request
resp1, _ := curl1.Request().Execute() // New session
resp2, _ := curl2.Request().Execute() // Another new session// Set reasonable timeouts
session := curl.CreateSession()
session.Config().SetTimeout(30 * time.Second) // Total timeout
session.Config().SetConnectTimeout(10 * time.Second) // Connection timeout// For large responses, consider streaming
resp, err := curl.Request().Execute()
if err == nil {
// Process response.Content() efficiently
// Don't store large responses in memory unnecessarily
}# Run all tests
go test -v
# Run tests with coverage report
go test -v -cover
# Run specific test categories
go test -v -run TestFileOutput
go test -v -run TestAuthentication
go test -v -run TestHTTPVersion
# Run tests with race detection
go test -v -race
# Generate detailed coverage report
go test -coverprofile=coverage.out
go tool cover -html=coverage.out- Total Tests: 100+ comprehensive test cases
- Coverage: 86.9% of code statements
- Categories:
- Basic parsing tests
- HTTP method tests
- Authentication tests
- File output tests
- HTTP version control tests
- Error handling tests
- Integration tests
We welcome contributions from the community! Here's how you can help:
-
π Report Bugs
- Open an issue with detailed reproduction steps
- Include the cURL command that's causing problems
- Provide Go version and OS information
-
π‘ Suggest Features
- Propose new cURL options to support
- Share use cases and examples
- Discuss implementation approaches
-
π§ Submit Pull Requests
- Add tests for any new functionality
- Follow existing code style and conventions
- Update documentation as needed
-
π Improve Documentation
- Fix typos and clarify explanations
- Add more examples and use cases
- Translate documentation
# Clone the repository
git clone https://github.com/474420502/gcurl.git
cd gcurl
# Install dependencies
go mod tidy
# Run tests to verify setup
go test -v
# Run tests with coverage
go test -v -cover
# Check code formatting
go fmt ./...
# Run static analysis
go vet ./...- Follow standard Go conventions
- Write comprehensive tests for new features
- Include examples in documentation
- Use descriptive variable and function names
- Add comments for complex logic
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes with tests
- Ensure all tests pass (
go test -v) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
-
Enhanced Session Management
- Session persistence and restoration
- Session configuration templates
- Advanced connection pooling
-
Performance Monitoring
- Request timing and statistics
- Connection reuse metrics
- Memory usage optimization
-
Advanced Authentication
- OAuth 2.0 flow support
- JWT token handling
- API key management
-
Concurrent Processing
- Parallel request execution
- Batch command processing
- Request queue management
- Become the standard cURL-to-Go conversion library
- Support for enterprise-grade features
- Integration with popular Go frameworks
- Advanced debugging and profiling tools
- π οΈ Major code quality and architecture improvements
- Refactored all global variables for thread safety (e.g., gserver β getTestServer with sync.Once)
- Debug function refactored from complexity 46 to 1 (split into 10+ helpers)
- Added comprehensive thread safety documentation for optionRegistry
- Created detailed CODE_QUALITY_REPORT.md with metrics and analysis
- All gserver references updated to use new thread-safe accessor
- Maintained 86.9% test coverage with all tests passing
- Improved code comments and technical debt tracking
- β
Added
--connect-tooption for network troubleshooting and load balancing - β
Implemented
-G/--getoption for converting POST data to GET query parameters - β
Enhanced
--resolvewith multi-IP and force-replacement (+) support - β Improved examples structure with organized subdirectories
- β Updated test coverage to 86.9% with comprehensive edge case testing
- β Added detailed implementation documentation
- β Cleaned up repository for professional release standards
- β
Comprehensive file output support (
-o,-O,--output-dir, etc.) - β Complete Digest Authentication implementation
- β HTTP protocol version control
- β Enhanced debugging capabilities
- β Improved test coverage (86.9%)
- β Production-ready stability
This project is licensed under the MIT License - see the LICENSE file for details.
- requests - The powerful HTTP library that powers gcurl
- cURL - The amazing command-line tool that inspired this project
- Go Community - For the excellent ecosystem and tools
- All Contributors - Everyone who has helped improve this library
- requests - The HTTP client library used by gcurl
- IMPLEMENTATION_REPORT.md - Detailed technical documentation of v1.2.0 features
- GitHub Issues: Report bugs and request features
- Documentation: Check this README and code examples
- Community: Join discussions in GitHub issues
β Star this project if it helps you convert cURL commands to Go code! Your support motivates continued development and improvements.
"gcurl saved us hours of manual conversion work when migrating our API tests from shell scripts to Go. The authentication and file upload features work flawlessly!" - Development Team Lead
"Perfect for our CI/CD pipeline where we needed to convert existing cURL-based health checks to Go services. The session reuse feature improved our performance significantly." - DevOps Engineer
"The debug output helped us understand exactly how our complex cURL commands were being interpreted. Great for troubleshooting API integration issues." - Backend Developer
Made with β€οΈ for the Go community