forked from mceloud/go-prompt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
189 lines (175 loc) · 5.3 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"net/url"
"os"
"path"
"strings"
"github.com/c-bata/go-prompt"
)
type RequestContext struct {
url *url.URL
header http.Header
client *http.Client
}
var ctx *RequestContext
// See https://github.com/eliangcs/http-prompt/blob/master/http_prompt/completion.py
var suggestions = []prompt.Suggest{
// Command
{"cd", "Change URL/path"},
{"exit", "Exit http-prompt"},
// HTTP Method
{"delete", "DELETE request"},
{"get", "GET request"},
{"patch", "GET request"},
{"post", "POST request"},
{"put", "PUT request"},
// HTTP Header
{"Accept", "Acceptable response media type"},
{"Accept-Charset", "Acceptable response charsets"},
{"Accept-Encoding", "Acceptable response content codings"},
{"Accept-Language", "Preferred natural languages in response"},
{"ALPN", "Application-layer protocol negotiation to use"},
{"Alt-Used", "Alternative host in use"},
{"Authorization", "Authentication information"},
{"Cache-Control", "Directives for caches"},
{"Connection", "Connection options"},
{"Content-Encoding", "Content codings"},
{"Content-Language", "Natural languages for content"},
{"Content-Length", "Anticipated size for payload body"},
{"Content-Location", "Where content was obtained"},
{"Content-MD5", "Base64-encoded MD5 sum of content"},
{"Content-Type", "Content media type"},
{"Cookie", "Stored cookies"},
{"Date", "Datetime when message was originated"},
{"Depth", "Applied only to resource or its members"},
{"DNT", "Do not track user"},
{"Expect", "Expected behaviors supported by server"},
{"Forwarded", "Proxies involved"},
{"From", "Sender email address"},
{"Host", "Target URI"},
{"HTTP2-Settings", "HTTP/2 connection parameters"},
{"If", "Request condition on state tokens and ETags"},
{"If-Match", "Request condition on target resource"},
{"If-Modified-Since", "Request condition on modification date"},
{"If-None-Match", "Request condition on target resource"},
{"If-Range", "Request condition on Range"},
{"If-Schedule-Tag-Match", "Request condition on Schedule-Tag"},
{"If-Unmodified-Since", "Request condition on modification date"},
{"Max-Forwards", "Max number of times forwarded by proxies"},
{"MIME-Version", "Version of MIME protocol"},
{"Origin", "Origin(s} issuing the request"},
{"Pragma", "Implementation-specific directives"},
{"Prefer", "Preferred server behaviors"},
{"Proxy-Authorization", "Proxy authorization credentials"},
{"Proxy-Connection", "Proxy connection options"},
{"Range", "Request transfer of only part of data"},
{"Referer", "Previous web page"},
{"TE", "Transfer codings willing to accept"},
{"Transfer-Encoding", "Transfer codings applied to payload body"},
{"Upgrade", "Invite server to upgrade to another protocol"},
{"User-Agent", "User agent string"},
{"Via", "Intermediate proxies"},
{"Warning", "Possible incorrectness with payload body"},
{"WWW-Authenticate", "Authentication scheme"},
{"X-Csrf-Token", "Prevent cross-site request forgery"},
{"X-CSRFToken", "Prevent cross-site request forgery"},
{"X-Forwarded-For", "Originating client IP address"},
{"X-Forwarded-Host", "Original host requested by client"},
{"X-Forwarded-Proto", "Originating protocol"},
{"X-Http-Method-Override", "Request method override"},
{"X-Requested-With", "Used to identify Ajax requests"},
{"X-XSRF-TOKEN", "Prevent cross-site request forgery"},
}
func livePrefix() (string, bool) {
if ctx.url.Path == "/" {
return "", false
}
return ctx.url.String() + "> ", true
}
func executor(in string) {
in = strings.TrimSpace(in)
var method, body string
blocks := strings.Split(in, " ")
switch blocks[0] {
case "cd":
if len(blocks) < 2 {
ctx.url.Path = "/"
} else {
ctx.url.Path = path.Join(ctx.url.Path, blocks[1])
}
return
case "get", "delete":
method = strings.ToUpper(blocks[0])
case "post", "put", "patch":
if len(blocks) < 2 {
fmt.Println("please set request body.")
return
}
body = strings.Join(blocks[1:], " ")
method = strings.ToUpper(blocks[0])
}
if method != "" {
req, err := http.NewRequest(method, ctx.url.String(), strings.NewReader(body))
if err != nil {
fmt.Println("err: " + err.Error())
return
}
req.Header = ctx.header
res, err := ctx.client.Do(req)
if err != nil {
fmt.Println("err: " + err.Error())
return
}
result, err := ioutil.ReadAll(res.Body)
if err != nil {
fmt.Println("err: " + err.Error())
return
}
fmt.Printf("%s\n", result)
ctx.header = http.Header{}
return
}
if h := strings.Split(in, ":"); len(h) == 2 {
// Handling HTTP Header
ctx.header.Add(strings.TrimSpace(h[0]), strings.Trim(h[1], ` '"`))
} else {
fmt.Println("Sorry, I don't understand.")
}
}
func completer(in prompt.Document) []prompt.Suggest {
w := in.GetWordBeforeCursor()
if w == "" {
return []prompt.Suggest{}
}
return prompt.FilterHasPrefix(suggestions, w, true)
}
func main() {
var baseURL = "http://localhost:8000/"
if len(os.Args) == 2 {
baseURL = os.Args[1]
if strings.HasSuffix(baseURL, "/") {
baseURL += "/"
}
}
u, err := url.Parse(baseURL)
if err != nil {
log.Fatal(err)
}
ctx = &RequestContext{
url: u,
header: http.Header{},
client: &http.Client{},
}
p := prompt.New(
executor,
completer,
prompt.OptionPrefix(u.String()+"> "),
prompt.OptionLivePrefix(livePrefix),
prompt.OptionTitle("http-prompt"),
)
p.Run()
}