package main import ( "bufio" "fmt" "io/ioutil" "net" "net/url" "os" "strconv" "strings" ) // SpartanURL parses u and calls SpartanParsedURL with the parsed url func SpartanURL(u, input string) bool { parsed, err := url.Parse(u) if parsed.Host == "" { parsed, err = url.Parse("spartan://" + u) } if err != nil { fmt.Println("invalid url") return false } if parsed.Scheme != "spartan" { fmt.Println("Unsupported scheme") } return SpartanParsedURL(*parsed, input) } // SpartanParsedURL fetches u and displays the page func SpartanParsedURL(u url.URL, input string) bool { host := u.Host if u.Port() == "" { host += ":300" } // Connect to server 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 %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 { 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: fmt.Println(u.Host + meta) SpartanURL("spartan://" + u.Host + meta, "") case 4: fmt.Println("Error: " + meta) case 5: fmt.Println("Server error: " + meta) } return true } func Usage() { fmt.Fprintln(os.Stderr, ` Usage: sparte [--help] [URL] [-i INPUT] [-f FILE] --help usage -i send INPUT to URL -f send contents of FILE as input to UR `) return } func main() { args := os.Args[1:] if len(args) == 0 { Usage() return } url := args[0] input := "" for i, arg := range args { if arg == "--help" { Usage() return } if arg == "-i" || arg == "-f" { if len(args) < i+2 || (i==0 && len(args) < i+3) { fmt.Println("input arument or URL missing") return } url = args[i-1] if arg == "-i" { input = args[i+1] break } // arg must be -f inputBytes, err := ioutil.ReadFile(args[i+1]) if err != nil { fmt.Fprintln(os.Stderr, "Error reading file") os.Exit(1) } input = string(inputBytes) break // ignoring other args if any } } SpartanURL(url, input) }