package main // import "contnet.org/util/cnp-req" import ( "bytes" "flag" "fmt" "io" "os" "path" "strings" "contnet.org/lib/cnp-go" ) var prog = path.Base(os.Args[0]) func checkerr(err error) { if err != nil { fmt.Fprintf(os.Stderr, "%s: error: %s\n", prog, err) os.Exit(1) } } type requestPrinter struct { out io.Writer body io.Reader n int64 notFirst bool } func (p *requestPrinter) Read(b []byte) (int, error) { n, err := p.body.Read(b) p.n += int64(n) if n > 0 && !p.notFirst { p.out.Write([]byte("> ")) p.notFirst = true } p.out.Write(bytes.Replace(b[:n], []byte("\n"), []byte("\n> "), -1)) if err == io.EOF && p.n > 0 { p.out.Write([]byte("\n")) } return n, err } func send(r *cnp.Request, printReq, printHdr, printBody bool) { if printReq { if r.Body != nil { if _, ok := r.Header.Parameters["length"]; !ok { r.ComputeLength() } fmt.Fprint(os.Stderr, "> ") r.Header.Write(os.Stderr) r.Body = &requestPrinter{out: os.Stderr, body: io.LimitReader(r.Body, r.Length())} } else { fmt.Fprint(os.Stderr, "> ") r.Header.Write(os.Stderr) } } resp, err := cnp.Send(r) checkerr(err) defer resp.Close() if printHdr { checkerr(resp.Header.Write(os.Stdout)) } if printBody { l := resp.Length() if l > 0 { resp.Body = io.LimitReader(resp.Body, l) } _, err = io.Copy(os.Stdout, resp.Body) checkerr(err) } } func usage(f io.Writer) { fmt.Fprintf(f, "%s: usage: %s {URL|HOST/PATH} [PARAM=VALUE ...]\n", prog, prog) } func main() { printReq := flag.Bool("v", false, "print the request header and body") printHdr := flag.Bool("i", false, "print the response header") noBody := flag.Bool("I", false, "only print the response header without the body") rawParams := flag.Bool("r", false, "treat parameters as raw CNP-encoded parameters") readBody := flag.Bool("b", false, "read body data from stdin") body := flag.String("B", "", "body data") flag.Parse() if flag.NArg() < 1 { usage(os.Stderr) os.Exit(2) } var req *cnp.Request var err error if strings.HasPrefix(flag.Arg(0), "cnp:") || strings.HasPrefix(flag.Arg(0), "/") { req, err = cnp.NewRequestURL(flag.Arg(0), nil) } else { ss := strings.SplitN(flag.Arg(0), "/", 2) if len(ss) != 2 { usage(os.Stderr) os.Exit(2) } req, err = cnp.NewRequest(ss[0], "/"+ss[1], nil) } checkerr(err) req.Body = strings.NewReader(*body) if *readBody { req.Body = os.Stdin } for _, arg := range flag.Args()[1:] { ss := strings.SplitN(arg, "=", 2) if len(ss) != 2 { checkerr(fmt.Errorf("invalid parameter: %q", arg)) } if *rawParams { ss[0], err = cnp.Unescape([]byte(ss[0])) checkerr(err) ss[1], err = cnp.Unescape([]byte(ss[1])) checkerr(err) } req.SetParam(ss[0], ss[1]) } send(req, *printReq, *printHdr || *noBody, !*noBody) }