Skip to content

474420502/gcurl

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

68 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Parse cURL To Golang Requests

Go Version Test Coverage License Latest Release

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

πŸš€ Features

  • 🌐 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, -C continue
  • πŸ” 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

πŸ“¦ Installation

go get github.com/474420502/gcurl@v1.2.0

🎯 Quick Start

Transform 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())
}

πŸ“– Examples

Example 1: Basic GET Request with Headers

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())
}

Example 2: POST Request with JSON Data

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())
}

Example 3: Multipart Form Data with File Upload

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())
}

Example 4: File Download with Output Options

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")
	}
}

Example 5: Authentication Methods

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")
	}
}

Example 6: HTTP Version Control

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")
	}
}

Example 7: Debug and Verbose Output

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())
}

Example 8: Advanced Session Management

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 ===")
}

πŸ”§ Advanced Usage

Session Reuse Pattern

// 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

Direct Execution for Simple Cases

// For one-off requests, use direct execution
curl, _ := gcurl.Parse(`curl "https://httpbin.org/get"`)
resp, err := curl.Request().Execute() // Auto-creates session

Custom Session Configuration

curl, _ := 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()

Example 9: Script Features and Write-Out Formats

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")
	}
}

Example 10: DNS Resolution Control with --resolve

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
}

Example 11: Connection Redirection with --connect-to

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
}

Example 12: GET Mode with Data (-G/--get)

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")
}

πŸ“Š API Reference

Core Functions

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\"")

CURL Object Methods

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

Response Object Methods

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

βœ… Supported cURL Options

Comprehensive Feature Matrix

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

πŸ” Debug and Troubleshooting

Enable Debug Output

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
===============================

Common Issues and Solutions

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

Best Practices

  1. Always handle errors:

    curl, err := gcurl.Parse(curlCommand)
    if err != nil {
        log.Printf("Parse error: %v", err)
        return
    }
  2. Reuse sessions for multiple requests:

    session := curl.CreateSession()
    // Use session for multiple requests to same host
  3. Set appropriate timeouts:

    session.Config().SetTimeout(30 * time.Second)
  4. Use debug mode during development:

    fmt.Println(curl.Debug()) // See parsed configuration

🎯 Performance Tips

Connection Reuse

// 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

Timeout Configuration

// Set reasonable timeouts
session := curl.CreateSession()
session.Config().SetTimeout(30 * time.Second)          // Total timeout
session.Config().SetConnectTimeout(10 * time.Second)   // Connection timeout

Memory Efficiency

// 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
}

πŸ§ͺ Testing

Run Tests

# 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

Test Statistics

  • 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

🀝 Contributing

We welcome contributions from the community! Here's how you can help:

Ways to Contribute

  1. πŸ› Report Bugs

    • Open an issue with detailed reproduction steps
    • Include the cURL command that's causing problems
    • Provide Go version and OS information
  2. πŸ’‘ Suggest Features

    • Propose new cURL options to support
    • Share use cases and examples
    • Discuss implementation approaches
  3. πŸ”§ Submit Pull Requests

    • Add tests for any new functionality
    • Follow existing code style and conventions
    • Update documentation as needed
  4. πŸ“š Improve Documentation

    • Fix typos and clarify explanations
    • Add more examples and use cases
    • Translate documentation

Development Setup

# 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 ./...

Code Style Guidelines

  • 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

Pull Request Process

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes with tests
  4. Ensure all tests pass (go test -v)
  5. Commit your changes (git commit -m 'Add amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

πŸš€ Roadmap

Phase 3: Advanced Features (Upcoming)

  • 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

Long-term Vision

  • Become the standard cURL-to-Go conversion library
  • Support for enterprise-grade features
  • Integration with popular Go frameworks
  • Advanced debugging and profiling tools

πŸ“‹ Version History

v1.2.1 (Current)

  • πŸ› οΈ 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

v1.2.0

  • βœ… Added --connect-to option for network troubleshooting and load balancing
  • βœ… Implemented -G/--get option for converting POST data to GET query parameters
  • βœ… Enhanced --resolve with 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

v1.1.0

  • βœ… 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

οΏ½πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ™ Acknowledgments

  • 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

πŸ”— Related Projects

πŸ“ž Support


⭐ Star this project if it helps you convert cURL commands to Go code! Your support motivates continued development and improvements.

πŸ† Success Stories

"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

About

parse curl bash to code of golang

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors