http2curl.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. package http2curl
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io/ioutil"
  6. "net/http"
  7. "sort"
  8. "strings"
  9. )
  10. // CurlCommand contains exec.Command compatible slice + helpers
  11. type CurlCommand []string
  12. // append appends a string to the CurlCommand
  13. func (c *CurlCommand) append(newSlice ...string) {
  14. *c = append(*c, newSlice...)
  15. }
  16. // String returns a ready to copy/paste command
  17. func (c *CurlCommand) String() string {
  18. return strings.Join(*c, " ")
  19. }
  20. func bashEscape(str string) string {
  21. return `'` + strings.Replace(str, `'`, `'\''`, -1) + `'`
  22. }
  23. // GetCurlCommand returns a CurlCommand corresponding to an http.Request
  24. func GetCurlCommand(req *http.Request) (*CurlCommand, error) {
  25. if req.URL == nil {
  26. return nil, fmt.Errorf("getCurlCommand: invalid request, req.URL is nil")
  27. }
  28. command := CurlCommand{}
  29. command.append("curl")
  30. schema := req.URL.Scheme
  31. requestURL := req.URL.String()
  32. if schema == "" {
  33. schema = "http"
  34. if req.TLS != nil {
  35. schema = "https"
  36. }
  37. requestURL = schema + "://" + req.Host + req.URL.Path
  38. }
  39. if schema == "https" {
  40. command.append("-k")
  41. }
  42. command.append("-X", bashEscape(req.Method))
  43. if req.Body != nil {
  44. var buff bytes.Buffer
  45. _, err := buff.ReadFrom(req.Body)
  46. if err != nil {
  47. return nil, fmt.Errorf("getCurlCommand: buffer read from body error: %w", err)
  48. }
  49. // reset body for potential re-reads
  50. req.Body = ioutil.NopCloser(bytes.NewBuffer(buff.Bytes()))
  51. if len(buff.String()) > 0 {
  52. bodyEscaped := bashEscape(buff.String())
  53. command.append("-d", bodyEscaped)
  54. }
  55. }
  56. var keys []string
  57. for k := range req.Header {
  58. keys = append(keys, k)
  59. }
  60. sort.Strings(keys)
  61. for _, k := range keys {
  62. command.append("-H", bashEscape(fmt.Sprintf("%s: %s", k, strings.Join(req.Header[k], " "))))
  63. }
  64. command.append(bashEscape(requestURL))
  65. return &command, nil
  66. }