Skip to content

Commit 290008c

Browse files
committed
fix httpie args
1 parent ee09edb commit 290008c

File tree

12 files changed

+110
-83
lines changed

12 files changed

+110
-83
lines changed

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ initGithooks:
3939

4040
clean:
4141
@rm -rf $(BUILD_DIR)
42-
@rm -f curl2httpie
43-
@rm -f artifacts
42+
@rm -rf curl2httpie
43+
@rm -rf artifacts
4444
@mkdir artifacts
4545

4646
test:

connector/connector.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ func Convert(args []string) (cmdStringer fmt.Stringer, warningMessages []Warning
2121
switch args[0] {
2222
case "curl":
2323
return Curl2Httpie(args[1:])
24-
case "http":
25-
return Httpie2Curl(args[1:])
24+
case "http", "https":
25+
return Httpie2Curl(args)
2626
}
2727

2828
err = ErrUnknownCommandType

connector/httpie.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,11 @@ func Httpie2Curl(args []string) (cmdStringer fmt.Stringer, warningMessages []War
115115
}
116116
}
117117

118+
if httpieInstance.IsHttps &&
119+
!strings.HasPrefix(curlCmdLine.URL, "https://") &&
120+
!strings.HasPrefix(curlCmdLine.URL, "http://") {
121+
curlCmdLine.URL = "https://" + curlCmdLine.URL
122+
}
118123
cmdStringer = curlCmdLine.NewStringer(true)
119124

120125
return

connector/httpie_test.go

Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,83 +9,107 @@ func TestHttpie2Curl(t *testing.T) {
99
}{
1010
{
1111
[]string{"http", ":/foo"},
12-
`curl 'localhost/foo'`,
12+
`curl localhost/foo`,
1313
},
1414
{
1515
[]string{"http", ":3000/bar"},
16-
`curl 'localhost:3000/bar'`,
16+
`curl localhost:3000/bar`,
1717
},
1818
{
1919
[]string{"http", ":"},
20-
`curl 'localhost/'`,
20+
`curl localhost/`,
2121
},
2222
{
2323
[]string{"http", "example.org", "id==1"},
24-
`curl 'example.org?id=1'`,
24+
`curl example.org?id=1`,
2525
},
2626
{
2727
[]string{"http", "--auth", "username", "example.org", "id==1"},
28-
`curl --user 'username' 'example.org?id=1'`,
28+
`curl --user username example.org?id=1`,
2929
},
3030
{
3131
[]string{"http", "--auth", "username", "example.org", "id==1", "foo:bar"},
32-
`curl --user 'username' --header 'foo: bar' 'example.org?id=1'`,
32+
`curl --user username --header 'foo: bar' example.org?id=1`,
3333
},
3434
{
3535
[]string{"http", "--form", "--auth", "username", "example.org", "id==1", "foo:bar", "foo=bar"},
36-
`curl --user 'username' --header 'foo: bar' --data 'foo=bar' 'example.org?id=1'`,
36+
`curl --user username --header 'foo: bar' --data foo=bar example.org?id=1`,
3737
},
3838
{
3939
[]string{"http", "--auth", "username", "example.org", "id==1", "foo:bar", "foo=bar"},
40-
`curl --user 'username' --header 'foo: bar' --header 'Content-Type: application/json' --data '{"foo":"bar"}' 'example.org?id=1'`,
40+
`curl --user username --header 'foo: bar' --header 'Content-Type: application/json' --data '{"foo":"bar"}' example.org?id=1`,
4141
},
4242
{
4343
[]string{"http", "-f", "--auth", "username", "example.org", "id==1", "foo:bar", "foo=bar", "file@test_obj.json"},
44-
`curl --user 'username' --header 'foo: bar' --form 'file=@"test_obj.json"' --data 'foo=bar' 'example.org?id=1'`,
44+
`curl --user username --header 'foo: bar' --form 'file=@"test_obj.json"' --data foo=bar example.org?id=1`,
4545
},
4646
{
4747
[]string{"http", "--auth", "username", "example.org", "id==1", "foo:bar", "foo=bar", `a:={"foo": "bar"}`},
48-
`curl --user 'username' --header 'foo: bar' --header 'Content-Type: application/json' --data '{"a":{"foo":"bar"},"foo":"bar"}' 'example.org?id=1'`,
48+
`curl --user username --header 'foo: bar' --header 'Content-Type: application/json' --data '{"a":{"foo":"bar"},"foo":"bar"}' example.org?id=1`,
4949
},
5050
{
5151
[]string{"http", "--auth", "username", "POST", "example.org", "id==1", "foo:bar", "foo=bar", `a:={"foo": "bar"}`},
52-
`curl --request 'POST' --user 'username' --header 'foo: bar' --header 'Content-Type: application/json' --data '{"a":{"foo":"bar"},"foo":"bar"}' 'example.org?id=1'`,
52+
`curl --request POST --user username --header 'foo: bar' --header 'Content-Type: application/json' --data '{"a":{"foo":"bar"},"foo":"bar"}' example.org?id=1`,
5353
},
5454
{
5555
[]string{"http", "PUT", "z.cn"},
56-
`curl --request 'PUT' 'z.cn'`,
56+
`curl --request PUT z.cn`,
5757
},
5858
{
5959
[]string{"http", "z.cn"},
60-
"curl 'z.cn'",
60+
"curl z.cn",
6161
},
6262
{
6363
[]string{"http", "--auth", "username", "--auth-type", "basic", "example.org", "id==1"},
64-
`curl --user 'username' --basic 'example.org?id=1'`,
64+
`curl --user username --basic example.org?id=1`,
6565
},
6666
{
6767
[]string{"http", "--auth", "username", "--auth-type", "digest", "example.org", "id==1"},
68-
`curl --user 'username' --digest 'example.org?id=1'`,
68+
`curl --user username --digest example.org?id=1`,
6969
},
7070
{
7171
[]string{"http", "--auth", "username", "--auth-type", "digest", "--proxy", "http:http://foo.bar:3128", "example.org", "id==1"},
72-
`curl --user 'username' --digest --proxy 'http:http://foo.bar:3128' 'example.org?id=1'`,
72+
`curl --user username --digest --proxy http:http://foo.bar:3128 example.org?id=1`,
7373
},
7474
{
7575
[]string{"http", "--auth", "username", "--auth-type", "digest", "--proxy", "http:http://foo.bar:3128", "example.org", "id==1"},
76-
`curl --user 'username' --digest --proxy 'http:http://foo.bar:3128' 'example.org?id=1'`,
76+
`curl --user username --digest --proxy http:http://foo.bar:3128 example.org?id=1`,
7777
},
7878
{
7979
[]string{"http", "--auth", "username", "--auth-type", "digest", "--proxy", "http:http://foo.bar:3128", "--follow", "example.org", "id==1"},
80-
`curl --user 'username' --digest --proxy 'http:http://foo.bar:3128' --location 'example.org?id=1'`,
80+
`curl --user username --digest --proxy http:http://foo.bar:3128 --location example.org?id=1`,
8181
},
8282
{
8383
[]string{"http", "--auth", "username", "--auth-type", "digest", "--proxy", "http:http://foo.bar:3128", "--follow", "--max-redirects", "10", "example.org", "id==1"},
84-
`curl --user 'username' --digest --proxy 'http:http://foo.bar:3128' --location --max-redirs '10' 'example.org?id=1'`,
84+
`curl --user username --digest --proxy http:http://foo.bar:3128 --location --max-redirs 10 example.org?id=1`,
8585
},
8686
{
8787
[]string{"http", "--auth", "username", "--auth-type", "digest", "--proxy", "http:http://foo.bar:3128", "--follow", "--max-redirects", "10", "--timeout", "30", "example.org", "id==1"},
88-
`curl --user 'username' --digest --proxy 'http:http://foo.bar:3128' --location --max-redirs '10' --max-time '30' 'example.org?id=1'`,
88+
`curl --user username --digest --proxy http:http://foo.bar:3128 --location --max-redirs 10 --max-time 30 example.org?id=1`,
89+
},
90+
{
91+
[]string{"https", "--auth", "username", "--auth-type", "digest", "--proxy", "http:http://foo.bar:3128", "--follow", "--max-redirects", "10", "--timeout", "30", "example.org", "id==1"},
92+
`curl --user username --digest --proxy http:http://foo.bar:3128 --location --max-redirs 10 --max-time 30 https://example.org?id=1`,
93+
},
94+
{
95+
[]string{"https", "pie.dev"},
96+
`curl https://pie.dev`,
97+
},
98+
{
99+
[]string{"http", "pie.dev"},
100+
`curl pie.dev`,
101+
},
102+
{
103+
[]string{"https", "pie.dev", "key==mykey", "secret==mysecret"},
104+
`curl 'https://pie.dev?key=mykey&secret=mysecret'`,
105+
},
106+
{
107+
[]string{"http", "-a", "username:password", "pie.dev"},
108+
`curl --user username:password pie.dev`,
109+
},
110+
{
111+
[]string{"http", "pie.dev", "-a", "username:password"},
112+
`curl --user username:password pie.dev`,
89113
},
90114
}
91115

@@ -94,13 +118,13 @@ func TestHttpie2Curl(t *testing.T) {
94118
// want string
95119
// }{
96120
// {
97-
// []string{"http", "--auth", "username", "example.org", "id==1", "foo:bar", "foo=bar", `a:={"foo": "bar"}`},
98-
// `curl --user 'username' --header 'foo: bar' --header 'Content-Type: application/json' --data '{"a":{"foo":"bar"},"foo":"bar"}' 'example.org?id=1'`,
121+
// []string{"http", "pie.dev", "-a", "username:password"},
122+
// `curl --user username:password pie.dev`,
99123
// },
100124
// }
101125

102126
for _, c := range cases {
103-
gotStringer, warningMessages, err := Httpie2Curl(c.in[1:])
127+
gotStringer, warningMessages, err := Httpie2Curl(c.in)
104128
if len(warningMessages) > 0 {
105129
t.Logf("Httpie2Curl warning messages: %#v in: %#v", warningMessages, c.in)
106130
}

curl/cmdline.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package curl
33
import (
44
"fmt"
55
"strings"
6+
7+
"github.com/dcb9/curl2httpie/shellwords"
68
)
79

810
type CmdLine struct {
@@ -33,7 +35,8 @@ func (cmdlineStringer *CmdLineStringer) String() string {
3335
if len(cmdlineStringer.Options) > 0 {
3436
parts = append(parts, strings.Join(options, " "))
3537
}
36-
parts = append(parts, fmt.Sprintf("'%s'", cmdlineStringer.URL))
38+
39+
parts = append(parts, shellwords.AddQuoteIfNeeded(cmdlineStringer.URL))
3740

3841
return strings.Join(parts, " ")
3942
}

curl/curl.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"fmt"
55
"io/ioutil"
66
"strings"
7+
8+
"github.com/dcb9/curl2httpie/shellwords"
79
)
810

911
type Tag string
@@ -32,10 +34,10 @@ func (o *Option) String(useLongName bool) string {
3234

3335
if o.HasArg {
3436
if useLongName {
35-
return fmt.Sprintf(`--%s '%s'`, o.Long, arg)
37+
return fmt.Sprintf(`--%s %s`, o.Long, shellwords.AddQuoteIfNeeded(arg))
3638
}
3739

38-
return fmt.Sprintf(`-%s '%s'`, string(o.Short), arg)
40+
return fmt.Sprintf(`-%s %s`, string(o.Short), shellwords.AddQuoteIfNeeded(arg))
3941
}
4042

4143
if useLongName {

httpie/cmdline.go

Lines changed: 11 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,15 @@ import (
66
"io/ioutil"
77
"net/http"
88
"strings"
9+
10+
"github.com/dcb9/curl2httpie/shellwords"
911
)
1012

1113
type CmdLine struct {
1214
Flags []*Flag
1315
Method *Method
1416
URL string
17+
IsHttps bool
1518
Items []*Item
1619
HasBody bool
1720
ContentType string
@@ -34,23 +37,6 @@ func (cl *CmdLine) AddItem(i *Item) {
3437
cl.Items = append(cl.Items, i)
3538
}
3639

37-
func needQuote(s string) bool {
38-
return -1 != strings.IndexFunc(s, func(r rune) bool {
39-
switch r {
40-
case '&', '@', '#', '[', ']', '{', '}', ' ', '(', ')', '*':
41-
return true
42-
}
43-
return false
44-
})
45-
}
46-
47-
func addQuoteIfNeeded(s string) string {
48-
if needQuote(s) {
49-
return fmt.Sprintf("'%s'", s)
50-
}
51-
return fmt.Sprintf("%s", s)
52-
}
53-
5440
func (cl *CmdLine) String() string {
5541
// slice
5642
s := make([]string, 0, len(cl.Flags)+len(cl.Items)+3) // http method url
@@ -86,7 +72,7 @@ func (cl *CmdLine) String() string {
8672
s = append(s, "--"+cl.ContentType)
8773
}
8874

89-
s = append(s, cl.Method.String(), addQuoteIfNeeded(cl.URL))
75+
s = append(s, cl.Method.String(), shellwords.AddQuoteIfNeeded(cl.URL))
9076

9177
for _, v := range cl.Items {
9278
s = append(s, v.String())
@@ -114,51 +100,30 @@ func NewCmdLine() *CmdLine {
114100

115101
func NewCmdLineByArgs(args []string) (*CmdLine, error) {
116102
cmdLine := NewCmdLine()
103+
if args[0] == "https" {
104+
cmdLine.IsHttps = true
105+
}
106+
args = args[1:]
117107
if len(args) == 1 {
118108
cmdLine.URL = args[0]
119109
return cmdLine, nil
120110
}
121111

122112
var err error
123-
cmdLine.Flags, err = getFlagsByArgs(args)
113+
var pureArgs []string
114+
cmdLine.Flags, pureArgs, err = removeFlags(args)
124115
if err != nil {
125116
return nil, fmt.Errorf("NewCmdLineByArgs: %w", err)
126117
}
127118

128-
cmdLine.Method, cmdLine.URL, cmdLine.Items, err = getMethodURLAndItems(args)
119+
cmdLine.Method, cmdLine.URL, cmdLine.Items, err = getMethodURLAndItems(pureArgs)
129120
return cmdLine, nil
130121
}
131122

132123
func getMethodURLAndItems(args []string) (method *Method, url string, items []*Item, err error) {
133124
method = NewMethod("")
134125

135-
var lastFlagIndex int
136-
foundFlag := false
137-
for i := len(args) - 1; i >= 0; i-- {
138-
if strings.HasPrefix(args[i], "-") {
139-
lastFlagIndex = i
140-
foundFlag = true
141-
break
142-
}
143-
}
144-
145126
possibleMethodIndex := 0
146-
if foundFlag {
147-
var flags []*Flag
148-
flags, err = getFlagsByArgs(args[lastFlagIndex:])
149-
if err != nil {
150-
return
151-
}
152-
if len(flags) < 1 {
153-
err = fmt.Errorf("invalid flags")
154-
return
155-
}
156-
if flags[0].HasArg {
157-
possibleMethodIndex = lastFlagIndex + 2
158-
} else {
159-
possibleMethodIndex = lastFlagIndex + 1
160-
}
161-
}
162127

163128
urlIndex := possibleMethodIndex
164129
possibleMethod := strings.ToUpper(args[possibleMethodIndex])

httpie/cmdline_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ func TestNewCmdLineByArgs(t *testing.T) {
129129
}
130130

131131
for _, c := range cases {
132-
got, err := NewCmdLineByArgs(c.in[1:])
132+
got, err := NewCmdLineByArgs(c.in)
133133
if err != nil {
134134
t.Fatalf("NewCmdLineByArgs error: %s in: %#v", err.Error(), c.in)
135135
}

httpie/flag.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package httpie
33
import (
44
"fmt"
55

6+
"github.com/dcb9/curl2httpie/shellwords"
67
flag "github.com/spf13/pflag"
78
)
89

@@ -30,7 +31,7 @@ func (f *Flag) String() string {
3031
if f.Separator == "" {
3132
f.Separator = " " // Use whitespace as default separator
3233
}
33-
arg = fmt.Sprintf(`%s%s`, f.Separator, addQuoteIfNeeded(f.Arg))
34+
arg = fmt.Sprintf(`%s%s`, f.Separator, shellwords.AddQuoteIfNeeded(f.Arg))
3435
}
3536

3637
return fmt.Sprintf("--%s%s", f.Long, arg)
@@ -119,7 +120,7 @@ var AllFlags = []*Flag{
119120
CertKeyFlag,
120121
}
121122

122-
func getFlagsByArgs(args []string) ([]*Flag, error) {
123+
func removeFlags(args []string) ([]*Flag, []string, error) {
123124
CommandLine := flag.NewFlagSet("httpie", flag.ContinueOnError)
124125
boolValues := make([]*bool, len(AllFlags))
125126
stringValues := make([]*string, len(AllFlags))
@@ -140,7 +141,7 @@ func getFlagsByArgs(args []string) ([]*Flag, error) {
140141
}
141142
err := CommandLine.Parse(args)
142143
if err != nil {
143-
return nil, fmt.Errorf("GetFlagsByArgs: %w", err)
144+
return nil, nil, fmt.Errorf("GetFlagsByArgs: %w", err)
144145
}
145146
flags := make([]*Flag, 0, len(args))
146147
for i, f := range AllFlags {
@@ -155,5 +156,6 @@ func getFlagsByArgs(args []string) ([]*Flag, error) {
155156
}
156157
}
157158
}
158-
return flags, nil
159+
160+
return flags, CommandLine.Args(), nil
159161
}

httpie/item.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package httpie
22

33
import (
44
"fmt"
5+
6+
"github.com/dcb9/curl2httpie/shellwords"
57
)
68

79
const (
@@ -19,7 +21,7 @@ type Item struct {
1921
}
2022

2123
func (i *Item) String() string {
22-
if needQuote(i.V) {
24+
if shellwords.NeedQuote(i.V) {
2325
return fmt.Sprintf(`'%s%s%s'`, i.K, i.S, i.V)
2426
}
2527
return fmt.Sprintf(`%s%s%s`, i.K, i.S, i.V)

0 commit comments

Comments
 (0)