-
Notifications
You must be signed in to change notification settings - Fork 0
/
spartan.go
68 lines (65 loc) · 1.47 KB
/
spartan.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
package main
import (
"bufio"
"errors"
"fmt"
"net"
"net/url"
"strconv"
"strings"
)
type SpartanResponse struct {
status int
meta string // not parsed into mediaType and params yet
bodyReader *bufio.Reader
bodyReaderClosed bool
conn *net.Conn
connClosed bool
}
// SpartanParsedURL fetches u and returns a SpartanResponse
func SpartanParsedURL(u *url.URL) (res *SpartanResponse, err error) {
host := u.Host
if u.Port() == "" {
host += ":300"
}
// Connect to server
conn, err := net.Dial("tcp", host)
if err != nil {
return
}
// defer conn.Close()
// Send request
path := u.Path
if u.Path == "" {
path = "/"
}
input, err := url.QueryUnescape(u.RawQuery)
if err != nil {
return
}
conn.Write([]byte(fmt.Sprintf("%s %s %d\r\n", u.Hostname(), path, len(input))))
conn.Write([]byte(input))
// Receive and parse response header
reader := bufio.NewReader(conn)
header, err := reader.ReadString(byte('\n'))
if err != nil {
return nil, errors.New("Error reading response header")
}
// Parse header
statusParts := strings.SplitN(header, " ", 2)
status, err := strconv.Atoi(statusParts[0])
if err != nil {
err = errors.New("Invalid response header")
return
}
meta := strings.Trim(statusParts[1], "\r\n")
res = &SpartanResponse{
status: status,
meta: meta,
bodyReader: reader,
bodyReaderClosed: false, // idk
conn: &conn,
connClosed: false,
}
return
}