From e825108b56e262f937bf37b1596c41cd50d4412e Mon Sep 17 00:00:00 2001 From: Hedy Li Date: Thu, 8 Jul 2021 20:55:48 +0800 Subject: [PATCH] initial --- client.go | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ go.mod | 3 ++ 2 files changed, 108 insertions(+) create mode 100644 client.go create mode 100644 go.mod diff --git a/client.go b/client.go new file mode 100644 index 0000000..f376f98 --- /dev/null +++ b/client.go @@ -0,0 +1,105 @@ +package main + +import ( + "os" + "bufio" + "fmt" + "io/ioutil" + "net" + "net/url" + "strconv" + "strings" +) + +// SpartanURL parses u and calls SpartanParsedURL with the parsed url +func SpartanURL(u string) bool { + // Parse URL + parsed, err := url.Parse(u) + if err != nil { + fmt.Println("invalid url") + return false + } + if parsed.Scheme == "" { + // have to parse again + // ignoring err since it shouldn't fail here if it succeeded above + parsed, _ = url.Parse("spartan://" + u) + } + if parsed.Scheme != "spartan" { + fmt.Printf("Unsupported scheme %s", parsed.Scheme) + return false + } + return SpartanParsedURL(*parsed) +} + +// SpartanParsedURL fetches u and displays the page +func SpartanParsedURL(u url.URL) bool { + host := u.Host + // Connect to server + if u.Port() == "" { + host += ":300" + } + conn, err := net.Dial("tcp", host) + if err != nil { + fmt.Println("unable to connect to " + u.Host) + fmt.Println(err.Error()) + return false + } + defer conn.Close() + // Send request + path := u.Path + if u.Path == "" { + path = "/" + } + conn.Write([]byte(fmt.Sprintf("%s %s 0\r\n", u.Hostname(), path))) + // Receive and parse response header + reader := bufio.NewReader(conn) + header, err := reader.ReadString(byte('\n')) + if err != nil { + fmt.Println("Error reading response header") + return false + } + // Parse header + statusParts := strings.SplitN(header, " ", 2) + status, err := strconv.Atoi(statusParts[0]) + if err != nil { + fmt.Println("invalid status code:" + statusParts[0]) + return false + } + meta := statusParts[1] + + // Handle status + switch status { + case 1: + fmt.Println("[INPUT]") + fmt.Println(meta) + case 2: + // TODO: handle mime type + bodyBytes, err := ioutil.ReadAll(reader) + if err != nil { + fmt.Println("Error reading body") + return false + } + body := string(bodyBytes) + fmt.Print(body) + case 3: + SpartanURL("spartan://" + u.Host + meta) + case 4: + fmt.Println("Error: " + meta) + case 5: + fmt.Println("Server error: " + meta) + } + + return true +} + +func main() { + args := os.Args + for _, arg := range args { + if arg == "--help" { + fmt.Println("Usage: [--help] [URL]") + return + } + SpartanURL(arg) + return + } +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..0d996e2 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module sparte + +go 1.15