Giter Club home page Giter Club logo

curl-to-go's Introduction

curl-to-Go

curl-to-Go is a tool to instantly convert curl commands to Go code in the browser. It does not guarantee high-fidelity conversions, but it's good enough for most API docs that have curl samples.

This is a sister tool to JSON-to-Go, which converts JSON to a Go struct type definition. To do the reverse, check out moul/http2curl.

Try it

Check it out! It works inside your browser. Just give the code a once-over since it will need you to flesh out some parts like error handling.

FAQ

Does any curl command work?

Any curl command should work, but only certain flags are understood and converted into Go code. The rest of the flags will be ignored.

Which kinds of curl commands are understood?

Mostly simple HTTP commands (headers, basic auth, body, etc).

Will you consider supporting this-or-that flag?

curl has like a bajillion options, so don't expect all of them to be implemented; just the most common/important ones to stub out code from API samples and docs, etc. But feel free to open an issue or submit a pull request! To request a new flag, please provide the equivalent Go code.

Credits

curl-to-Go is brought to you by Matt Holt (mholt6). Enjoy!

curl-to-go's People

Contributors

0x333333 avatar 0x49b avatar abdullah2993 avatar alexchao26 avatar arjunmahishi avatar bakert avatar bengadbois avatar chrsblck avatar git001 avatar ishanjain28 avatar mholt avatar moul avatar thaiphan avatar two avatar verhovsky avatar zmackie avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

curl-to-go's Issues

Idea: parse $VAR and ${VAR} from "..." strings and convert to go code

curl -H "Accept: application/json" -H "Content-Type: application/json" -H "Authorization: Token ${PIVOTAL_NETWORK_TOKEN}" -X GET https://network.pivotal.io/api/v2/products

would use https://golang.org/pkg/os/#ExpandEnv to become:

// Generated by curl-to-Go: https://mholt.github.io/curl-to-go

req, err := http.NewRequest("GET", "https://network.pivotal.io/api/v2/products", nil)
if err != nil {
    // handle err
}
req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", os.ExpandEnv("Token ${PIVOTAL_NETWORK_TOKEN}"))

resp, err := http.DefaultClient.Do(req)
if err != nil {
    // handle err
}
defer resp.Body.Close()

Perhaps the algorithm would detect $ in any string and wrap the string in os.ExpandEnv(...)?

Support on --resolve

Consider the following example:

curl -H "X-Access-Key: dgfh464f45v66773454vv666" https://domain.com --resolve 4e45-9996-65d7f49e46f2.another-domain.com:12345:145.23.143.248

RFE: Making generated example more complete

Hi Thanks for this great software.

Would you please enhance the generated go code to be almost ready-to-run ?

Goal is to have user modify variable part(actual site url and login account/password).

Support $'...' strings

Hi, I just getting blank header when I use proposed os.ExpandEnv("$Cookie"), if I try without it (ie just setting req.Header.Set("Cookie","cookies;values;") the request does not work, while curl works.

Flags -G -d works incorrectly

Are you requesting support for a new curl flag? If so, what is the flag and the equivalent Go code?

curl -G https://curl-to-go.com \
 -d "id=8a829417567d952801568d9d9e3c0b84" \
 -H "Authorization: Bearer OGE4Mjk0MTc1NjdkOTUyODAxNTY4ZDlkOWU5ZjBiODh8amF5MjdhdDVzMg=="
params := url.Values{
		"id": {"8a829417567d952801568d9d9e3c0b84"},
	}

	reqUrl := "https://curl-to-go.com?" + params.Encode()

	req, err := http.NewRequest(http.MethodGet, reqUrl, nil)
	if err != nil {
		// handle err
	}

	req.Header.Set("Authorization", "Bearer OGFjN2E0Yzc4MTZmYjJmNjAxODE2ZmRmMmFjMzAwYTJ8NVF4ZmtDcWZqSA==")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		// handle err
	}
	defer resp.Body.Close()

curl -k parameter

hi,

thanks for your work!
when I try this I need curl one self-signed https web, my curl command need -k to ignore security check , after some digging,I add some code , then golang code works, kindly consider this.

same discussion on https://stackoverflow.com/questions/12122159/golang-how-to-do-a-https-request-with-bad-certificate

code like

tr := &http.Transport{
        TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
    }
    client := &http.Client{Transport: tr}
    _, err := client.Get("https://golang.org/")

regards, hua

Suggest closing http response body when not nil

This project looks really useful! Seems that sometimes using net/http package can be prone to subtle bugs when closing the response body so thought that maybe it would be useful to generate snippets of code which prevent this.

Currently output displayed is like...

// Generated by curl-to-Go: https://mholt.github.io/curl-to-go
resp, err := http.Get("http://www.google.com")
if err != nil {
    // handle err
}
defer resp.Body.Close()

But considering that on redirection failure both variables will be non-nil so there can be a leak

How about maybe changing output to something like below?

// Generated by curl-to-Go: https://mholt.github.io/curl-to-go
resp, err := http.Get("http://www.google.com")
if resp != nil {
        defer resp.Body.Close()
}
if err != nil {
        // handle err
}

Thanks!

--data-binary should do POST not GET

--data-binary

(HTTP) This posts data exactly as specified with no extra processing whatsoever.

If you start the data with the letter @, the rest should be a filename. Data is posted in a similar manner as -d, --data does, except that newlines and carriage returns are preserved and conversions are never done.

If this option is used several times, the ones following the first will append data as described in -d, --data.

Parse the URL

It would be nice to explode the URL into a native net/url structure too.

Add checks for http status code

I think it is better to add in the generated sample code a check (even if commented) for HTTP status code (just as a hint). example:

if resp.StatusCode != http.StatusOK {
	// handle status code not 200
}

BTW, I spent long time not sure what is the error until I realized at the end that, the status code check is not there 😄

Bug: newlines not working

Hi,

Your latest update has a bug where new lines (using ) are not working. Even some of your examples don't work anymore.

curl --digest not working

Are you requesting support for a new curl flag? If so, what is the flag and the equivalent Go code?

curl --user "{PUBLIC-KEY}:{PRIVATE-KEY}" --digest \
 --header "Accept: application/json" \
 --include \
 --request GET "https://{OPSMANAGER-HOST}:{PORT}/api/public/v1.0/groups/{PROJECT-ID}/hosts?pretty=true"
import (
	"bytes"
	"crypto/md5"
	"crypto/rand"
	"crypto/sha256"
	"errors"
	"fmt"
	"hash"
	"io"
	"io/ioutil"
	"net/http"
	"strings"
)

const (
	MsgAuth   string = "auth"
	AlgMD5    string = "MD5"
	AlgSha256 string = "SHA-256"
)

var (
	ErrNilTransport      = errors.New("transport is nil")
	ErrBadChallenge      = errors.New("challenge is bad")
	ErrAlgNotImplemented = errors.New("alg not implemented")
)



func DoRequest() (err error) {
	body := bytes.NewBufferString(data)
	req, err := http.NewRequest("GET","https://{OPSMANAGER-HOST}:{PORT}/api/public/v1.0/groups/{PROJECT-ID}/hosts?pretty=true",nil)
	if err != nil {
		return err
	}
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	client, err := NewTransport("{PUBLIC-KEY}","{PRIVATE-KEY}").Client()
	if err != nil {
		return err
	}
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	bytesResp, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	fmt.Println(string(bytesResp))
	return
}

// Transport is an implementation of http.RoundTripper that takes care of http
// digest authentication.
type Transport struct {
	Username  string
	Password  string
	Transport http.RoundTripper
}

// NewTransport creates a new digest transport using the http.DefaultTransport.
func NewTransport(username, password string) *Transport {
	t := &Transport{
		Username: username,
		Password: password,
	}
	t.Transport = http.DefaultTransport
	return t
}

type challenge struct {
	Realm     string
	Domain    string
	Nonce     string
	Opaque    string
	Stale     string
	Algorithm string
	Qop       string
}

func parseChallenge(input string) (*challenge, error) {
	const ws = " \n\r\t"
	const qs = `"`
	s := strings.Trim(input, ws)
	if !strings.HasPrefix(s, "Digest ") {
		return nil, ErrBadChallenge
	}
	s = strings.Trim(s[7:], ws)
	sl := strings.Split(s, ", ")
	c := &challenge{
		Algorithm: AlgMD5,
	}
	var r []string
	for i := range sl {
		r = strings.SplitN(sl[i], "=", 2)
		switch r[0] {
		case "realm":
			c.Realm = strings.Trim(r[1], qs)
		case "domain":
			c.Domain = strings.Trim(r[1], qs)
		case "nonce":
			c.Nonce = strings.Trim(r[1], qs)
		case "opaque":
			c.Opaque = strings.Trim(r[1], qs)
		case "stale":
			c.Stale = strings.Trim(r[1], qs)
		case "algorithm":
			c.Algorithm = strings.Trim(r[1], qs)
		case "qop":
			c.Qop = strings.Trim(r[1], qs)
		default:
			return nil, ErrBadChallenge
		}
	}
	return c, nil
}

type credentials struct {
	Username   string
	Realm      string
	Nonce      string
	DigestURI  string
	Algorithm  string
	Cnonce     string
	Opaque     string
	MessageQop string
	NonceCount int
	method     string
	password   string
	impl       hashingFunc
}

type hashingFunc func() hash.Hash

func h(data string, f hashingFunc) (string, error) {
	hf := f()
	if _, err := io.WriteString(hf, data); err != nil {
		return "", err
	}
	return fmt.Sprintf("%x", hf.Sum(nil)), nil
}

func kd(secret, data string, f hashingFunc) (string, error) {
	return h(fmt.Sprintf("%s:%s", secret, data), f)
}

func (c *credentials) ha1() (string, error) {
	return h(fmt.Sprintf("%s:%s:%s", c.Username, c.Realm, c.password), c.impl)
}

func (c *credentials) ha2() (string, error) {
	return h(fmt.Sprintf("%s:%s", c.method, c.DigestURI), c.impl)
}

func (c *credentials) resp(cnonce string) (resp string, err error) {
	var ha1 string
	var ha2 string
	c.NonceCount++
	if c.MessageQop == MsgAuth {
		if cnonce != "" {
			c.Cnonce = cnonce
		} else {
			b := make([]byte, 8)
			_, err = io.ReadFull(rand.Reader, b)
			if err != nil {
				return "", err
			}
			c.Cnonce = fmt.Sprintf("%x", b)[:16]
		}
		if ha1, err = c.ha1(); err != nil {
			return "", err
		}
		if ha2, err = c.ha2(); err != nil {
			return "", err
		}
		return kd(ha1, fmt.Sprintf("%s:%08x:%s:%s:%s", c.Nonce, c.NonceCount, c.Cnonce, c.MessageQop, ha2), c.impl)
	} else if c.MessageQop == "" {
		if ha1, err = c.ha1(); err != nil {
			return "", err
		}
		if ha2, err = c.ha2(); err != nil {
			return "", err
		}
		return kd(ha1, fmt.Sprintf("%s:%s", c.Nonce, ha2), c.impl)
	}
	return "", ErrAlgNotImplemented
}

func (c *credentials) authorize() (string, error) {
	// Note that this is only implemented for MD5 and NOT MD5-sess.
	// MD5-sess is rarely supported and those that do are a big mess.
	if c.Algorithm != AlgMD5 && c.Algorithm != AlgSha256 {
		return "", ErrAlgNotImplemented
	}
	// Note that this is NOT implemented for "qop=auth-int".  Similarly the
	// auth-int server side implementations that do exist are a mess.
	if c.MessageQop != MsgAuth && c.MessageQop != "" {
		return "", ErrAlgNotImplemented
	}
	resp, err := c.resp("")
	if err != nil {
		return "", ErrAlgNotImplemented
	}
	sl := []string{fmt.Sprintf(`username="%s"`, c.Username)}
	sl = append(sl, fmt.Sprintf(`realm="%s"`, c.Realm),
		fmt.Sprintf(`nonce="%s"`, c.Nonce),
		fmt.Sprintf(`uri="%s"`, c.DigestURI),
		fmt.Sprintf(`response="%s"`, resp))
	if c.Algorithm != "" {
		sl = append(sl, fmt.Sprintf(`algorithm="%s"`, c.Algorithm))
	}
	if c.Opaque != "" {
		sl = append(sl, fmt.Sprintf(`opaque="%s"`, c.Opaque))
	}
	if c.MessageQop != "" {
		sl = append(sl, fmt.Sprintf("qop=%s", c.MessageQop),
			fmt.Sprintf("nc=%08x", c.NonceCount),
			fmt.Sprintf(`cnonce="%s"`, c.Cnonce))
	}
	return fmt.Sprintf("Digest %s", strings.Join(sl, ", ")), nil
}

func (t *Transport) newCredentials(req *http.Request, c *challenge) (*credentials, error) {
	cred := &credentials{
		Username:   t.Username,
		Realm:      c.Realm,
		Nonce:      c.Nonce,
		DigestURI:  req.URL.RequestURI(),
		Algorithm:  c.Algorithm,
		Opaque:     c.Opaque,
		MessageQop: c.Qop, // "auth" must be a single value
		NonceCount: 0,
		method:     req.Method,
		password:   t.Password,
	}
	switch c.Algorithm {
	case AlgMD5:
		cred.impl = md5.New
	case AlgSha256:
		cred.impl = sha256.New
	default:
		return nil, ErrAlgNotImplemented
	}

	return cred, nil
}

// RoundTrip makes a request expecting a 401 response that will require digest
// authentication.  It creates the credentials it needs and makes a follow-up
// request.
func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
	if t.Transport == nil {
		return nil, ErrNilTransport
	}

	// Copy the request so we don't modify the input.
	origReq := new(http.Request)
	*origReq = *req
	origReq.Header = make(http.Header, len(req.Header))
	for k, s := range req.Header {
		origReq.Header[k] = s
	}

	// We'll need the request body twice. In some cases we can use GetBody
	// to obtain a fresh reader for the second request, which we do right
	// before the RoundTrip(origReq) call. If GetBody is unavailable, read
	// the body into a memory buffer and use it for both requests.
	if req.Body != nil && req.GetBody == nil {
		body, err := ioutil.ReadAll(req.Body)
		if err != nil {
			return nil, err
		}
		req.Body = ioutil.NopCloser(bytes.NewBuffer(body))
		origReq.Body = ioutil.NopCloser(bytes.NewBuffer(body))
	}
	// Make a request to get the 401 that contains the challenge.
	challenge, resp, err := t.fetchChallenge(req)
	if challenge == "" || err != nil {
		return resp, err
	}

	c, err := parseChallenge(challenge)
	if err != nil {
		return nil, err
	}

	// Form credentials based on the challenge.
	cr, err := t.newCredentials(origReq, c)
	if err != nil {
		return nil, err
	}
	auth, err := cr.authorize()
	if err != nil {
		return nil, err
	}

	// Obtain a fresh body.
	if req.Body != nil && req.GetBody != nil {
		origReq.Body, err = req.GetBody()
		if err != nil {
			return nil, err
		}
	}

	// Make authenticated request.
	origReq.Header.Set("Authorization", auth)
	return t.Transport.RoundTrip(origReq)
}

func (t *Transport) fetchChallenge(req *http.Request) (string, *http.Response, error) {
	resp, err := t.Transport.RoundTrip(req)
	if err != nil {
		return "", resp, err
	}
	if resp.StatusCode != http.StatusUnauthorized {
		return "", resp, nil
	}

	// We'll no longer use the initial response, so close it
	defer func() {
		// Ensure the response body is fully read and closed
		// before we reconnect, so that we reuse the same TCP connection.
		// Close the previous response's body. But read at least some of
		// the body so if it's small the underlying TCP connection will be
		// re-used. No need to check for errors: if it fails, the Transport
		// won't reuse it anyway.
		const maxBodySlurpSize = 2 << 10
		if resp.ContentLength == -1 || resp.ContentLength <= maxBodySlurpSize {
			_, _ = io.CopyN(ioutil.Discard, resp.Body, maxBodySlurpSize)
		}

		resp.Body.Close()
	}()
	return resp.Header.Get("WWW-Authenticate"), resp, nil
}

// Client returns an HTTP client that uses the digest transport.
func (t *Transport) Client() (*http.Client, error) {
	if t.Transport == nil {
		return nil, ErrNilTransport
	}
	return &http.Client{Transport: t}, nil
}

--data-urlencode flag does not work

curl --location --request POST 'https://test.test/pest' \
--header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:97.0) Gecko/20100101 Firefox/97.0' \
--data-urlencode 'test=1' \
--data-urlencode 'lang=ru_RU'```

go generated code : 

```go
req, err := http.NewRequest("POST", "https://test.test/pest", nil)
if err != nil {
	// handle err
}
req.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:97.0) Gecko/20100101 Firefox/97.0")

resp, err := http.DefaultClient.Do(req)
if err != nil {
	// handle err
}
defer resp.Body.Close()

The code is wrong

Are you requesting support for a new curl flag? If so, what is the flag and the equivalent Go code?
The code is wrong

#curl --resolve www.aqzt.com:80:127.0.0.1 http://www.aqzt.com
// Generated by curl-to-Go: https://mholt.github.io/curl-to-go
resp, err := http.Get("http://www.aqzt.com")
if err != nil {
	// handle err
}
defer resp.Body.Close()

Can I use --data-urlencode ?

As of now, I cannot convert --data-urlencode. Is this doable? If not, can you pls take it as a feature request? This is my curl command.

$ curl --user 'admin:password' -X POST "https://my-url" -d token=XXXX-XXX \
--data-urlencode json='{"parameter": [{"name":"ACCOUNT", "value":"111111"}]}'

Thanks.

PS: This is duplicate of sethgrid/gencurl#3

can we get a list of ignored options?

when porting stuff with curl-to-to, it would be useful to see a list of options it ignored, then it would be much easier to spot options that needs to be ported manually

Include required import

While obvious to a lot of developers, it doesn't mention it requires "net/http".

Not sure if that's best in the generated Gocode or up in the description, but I think it's worth having somewhere on the page.

Handling the -F option of Curl

Are you requesting support for a new curl flag? If so, what is the flag and the equivalent Go code?

# (curl –X POST https://ssomesite.com/convert \
-F “media[file_data]=@/tmp/Example.wav;type=audio/x-wav” \
-F “account_did=5555555555” \
-F “api_key=a28f48da8da33402daef356abc567abfedc” \
-F “media[external_id]=123456789” \
-F “media[sender_id]=444-555-6666” \
-F “media[sender_name]=Mark Smith” \
-F “media[receiver_id]=333-555-1212” \
-F “media[receiver_name]=James Jones” \
-F “media[external_id]=4aef5432” \
-F “media[external_data]=Free-form text relative to your use case.”
// (no idea

I am looking at trying to make a complex request (like the above), and with the curl request (see above), code it up using the Go's net/http package.

Now, my main concern is that I am relatively new to the net/http package. It looks and feels pretty powerful, so I suspect this could be done. Your little curl-to-go program, and the example code have fired the imagination. I think I might be able to supply a -F option to code, but I need a nudge in the right direction.

If you were to code up (in go) the conversion, how would you (from a high-level perspective) do it? A little point in the right direction can get me started pretty quickly.

The curl above results in this sequence: (trace from curl):
== Info: About to connect() to eps-4voice.nuancemobility.net port 443 (#0)
== Info: Trying 8.39.192.14... == Info: connected
== Info: Connected to eps-4voice.nuancemobility.net (8.39.192.14) port 443 (#0)
== Info: Initializing NSS with certpath: sql:/etc/pki/nssdb
== Info: warning: ignoring value of ssl.verifyhost
== Info: skipping SSL peer certificate verification
== Info: NSS: client certificate not found (nickname not specified)
== Info: SSL connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
== Info: Server certificate:
== Info: subject: CN=*.nuancemobility.net,OU=BOS,O=Nuance Communications Inc.,L=Burlington,ST=Massachusetts,C=US
== Info: start date: Jul 10 00:00:00 2020 GMT
== Info: expire date: Jul 11 12:00:00 2022 GMT
== Info: common name: *.nuancemobility.net
== Info: issuer: CN=DigiCert Global CA G2,O=DigiCert Inc,C=US
=> Send header, 344 bytes (0x158)
0000: POST /conversions/4voice-us-voicemail HTTP/1.1
0030: User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7
0070: NSS/3.44 zlib/1.2.3 libidn/1.18 libssh2/1.4.2
00a0: Host: eps-4voice.nuancemobility.net
00c5: Accept: /
00d2: Content-Length: 202234
00ea: Expect: 100-continue
0100: Content-Type: multipart/form-data; boundary=--------------------
0140: --------744dab5b632c
0156:
<= Recv header, 23 bytes (0x17)
0000: HTTP/1.1 100 Continue
=> Send data, 187 bytes (0xbb)
0000: ------------------------------744dab5b632c
002c: Content-Disposition: form-data; name="media[file_data]"; filenam
006c: e="Example.wav"
009e: Content-Type: audio/x-wav
00b9:
=> Send data, 16383 bytes (0x3fff)
0000: RIFF$...WAVEfmt ........@....>......data.............. .........
0040: ............. .......(.........................................
0080: ................................................................
00c0: ................................................................
0100: ......0............. ............. .......0.....................
... (15 16k blocks of info snipped out...)
1080: ....D...............T...................t.............$.........
10c0: ............|$|.|,|&..............D.....D.<.............D...D.d.
1100: ..............<.......$.4...............
=> Send data, 1043 bytes (0x413)
0000:
0002: ------------------------------744dab5b632c
002e: Content-Disposition: form-data; name="account_did"
0062:
0064: 5555555555
0070: ------------------------------744dab5b632c
009c: Content-Disposition: form-data; name="api_key"
00cc:
00ce: a28f48da8da33402daef356abc567abfedc
00f8: ------------------------------744dab5b632c
0124: Content-Disposition: form-data; name="media[sender_id]"
015d:
015f: 444-555-6666
0164: ------------------------------744dab5b632c
0190: Content-Disposition: form-data; name="media[sender_name]"
01cb:
01cd: Mark Smith
01dc: ------------------------------744dab5b632c
0208: Content-Disposition: form-data; name="media[receiver_id]"
0243:
0245: 333-555-1212
025b: ------------------------------744dab5b632c
0287: Content-Disposition: form-data; name="media[receiver_name]"
02c4:
02c6: James Jones
02d9: ------------------------------744dab5b632c
0305: Content-Disposition: form-data; name="media[external_id]"
0340:
0342: 4aef5432
0362: ------------------------------744dab5b632c
038e: Content-Disposition: form-data; name="media[external_data]"
03cb:
03cd: Free-form text relative to your use case.
03e5: ------------------------------744dab5b632c--

Got any words of wisdom?

curl --socks5 127.0.0.1:1080 url

curl --socks5 127.0.0.1:1080 http://xyz.com
	proxyUrl, err := url.Parse("socks5://127.0.0.1:1080")
	httpClient := &http.Client{Transport: &http.Transport{Proxy: http.ProxyURL(proxyUrl)}}
	u := "http://xyz.com"
	req, err := http.NewRequest("GET", u, nil)
	if err != nil {
		panic(err)
	}
	resp, err := httpClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}
	log.Println(string(body))

Host Headers

After some minutes of fight, I saw that if in a curl like:
(Purge for Varnish stuff)
curl -v -X PURGE -H "Host: www.xxxx.com" ....

from: *request.go
// For server requests Host specifies the host on which the
// URL is sought. Per RFC 2616, this is either the value of
// the "Host" header or the host name given in the URL itself.
// It may be of the form "host:port". For international domain
// names, Host may be in Punycode or Unicode form. Use
// golang.org/x/net/idna to convert it to either format if
// needed.
//
// For client requests Host optionally overrides the Host
// header to send. If empty, the Request.Write method uses
// the value of URL.Host. Host may contain an international
// domain name.

Bad -> req.Header.Set("Host", "www.xxxx.com")
Good -> req.Host = "www.xxxx.com"

At least in: go version go1.8.1 linux/amd64

Go's default http client follows redirection while curl does not

Hi,

The use of the default http client (resp, err := http.DefaultClient.Do(req) causes a bug: when the response returns a redirection, go's default http client follows that redirection by default, while curl does not.

The client in use here should be changed from the default client to this:

client := &http.Client{
    CheckRedirect: func(req *http.Request, via []*http.Request) error {
        return http.ErrUseLastResponse
    },
}

This will fix this incolcnsistany with curl.

Cheers

Header by default not implemented

I'm currently using etcd which brings me to use your awesome curl-to-go converter. However when trying a basic command like putting a value:
curl -L -X PUT http://127.0.0.1:2379/v2/keys/message -d value="Hello"

This generate this:

// Generated by curl-to-Go: https://mholt.github.io/curl-to-go

body := strings.NewReader(`value=Hello`)
req, err := http.NewRequest("PUT", "http://127.0.0.1:2379/v2/keys/message", body)
if err != nil {
    // handle err
}

resp, err := http.DefaultClient.Do(req)
if err != nil {
    // handle err
}
defer resp.Body.Close()

The Curl command works but this code doesn't. The reason is one of the Curl default header is not set:
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

This should be the generated code that actually works with my code:

// Generated by curl-to-Go: https://mholt.github.io/curl-to-go

body := strings.NewReader(`value=Hello`)
req, err := http.NewRequest("PUT", "http://127.0.0.1:2379/v2/keys/message", body)
if err != nil {
    // handle err
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

resp, err := http.DefaultClient.Do(req)
if err != nil {
    // handle err
}
defer resp.Body.Close()

curl -d should generate POST requests

Given

curl -d "" google.com 

the program generates:

body := strings.NewReader(`google.com`)
req, err := http.NewRequest("GET", "", body)
if err != nil {
    // handle err
}

client := http.Client{}
resp, err := client.Do(req)
if err != nil {
    // handle err
}
defer resp.Body.Close()

but curl will perform a POST request, not GET

-F form encoded values doesnt gets implemented

Are you requesting support for a new curl flag? If so, what is the flag and the equivalent Go code?

# curl -v -u admin:admin123 -X POST 'http://localhost:8081/service/rest/v1/components?repository=maven-releases' -F maven2.groupId=com.google.guava -F maven2.artifactId=guava -F maven2.version=24.0-jre -F [email protected] -F maven2.asset1.extension=jar -F [email protected] -F maven2.asset2.classifier=sources -F maven2.asset2.extension=jar

From Curl manual pages -

curl also supports the more capable
multipart/form-data type. This latter type supports things like file upload.

-F accepts parameters like -F "name=contents". If you want the contents to
be read from a file, use <@filename> as contents. When specifying a file,
you can also specify the file content type by appending ';type='
to the file name. You can also post the contents of several files in one
field. For example, the field name 'coolfiles' is used to send three files,
with different content types using the following syntax:

    curl -F "[email protected];type=image/gif,fil2.txt,fil3.html" \ 
         http://www.post.com/postit.cgi

If the content-type is not specified, curl will try to guess from the file
extension (it only knows a few), or use the previously specified type (from
an earlier file if several files are specified in a list) or else it will
use the default type 'application/octet-stream'.

Emulate a fill-in form with -F. Let's say you fill in three fields in a
form. One field is a file name which to post, one field is your name and one
field is a file description. We want to post the file we have written named
"cooltext.txt". To let curl do the posting of this data instead of your
favourite browser, you have to read the HTML source of the form page and
find the names of the input fields. In our example, the input field names
are 'file', 'yourname' and 'filedescription'.

    curl -F "[email protected]" -F "yourname=Daniel" \ 
         -F "filedescription=Cool text file with cool text inside" \ 
         http://www.post.com/postit.cgi
// (put Go code here

Use http.DefaultClient to do requests

For GET, POST and HEAD http.Get(), http.Post(), http.Head() methods are used respectively here which internally use http.DefaultClient. I guess this is more of a suggestion, but why not use http.DefaultClient to do requests made with http.NewRequest also?

So instead of:

return 'req, err := http.NewRequest("'+method+'", "'+url+'", nil)\n'+err+'client := http.Client{}\nresp, err := client.Do(req)\n'+err+deferClose;

do

return 'req, err := http.NewRequest("'+method+'", "'+url+'", nil)\n'+err+'resp, err := http.DefaultClient.Do(req)\n'+err+deferClose;

and instead of:

// create the client and execute request
go += "\nclient := http.Client{}\nresp, err := client.Do(req)\n";

do

// create the client and execute request
go += "\nresp, err := http.DefaultClient.Do(req)\n";

thanks man

Just want to say thanks man! You saved me couple of hours. God bless you

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.