NewFormRequest creates an API request. A relative URL can be provided in urlStr, in which case it is resolved relative to the BaseURL of the Client. Relative URLs should always be specified without a preceding slash. Body is sent with Content-Type: application/x-www-form-urlencoded.
(ctx context.Context, urlStr string, body io.Reader, opts ...RequestOption)
| 828 | // Relative URLs should always be specified without a preceding slash. |
| 829 | // Body is sent with Content-Type: application/x-www-form-urlencoded. |
| 830 | func (c *Client) NewFormRequest(ctx context.Context, urlStr string, body io.Reader, opts ...RequestOption) (*http.Request, error) { |
| 831 | if !strings.HasSuffix(c.baseURL.Path, "/") { |
| 832 | return nil, fmt.Errorf("baseURL must have a trailing slash, but %q does not", c.baseURL) |
| 833 | } |
| 834 | |
| 835 | if err := checkURLPathTraversal(urlStr); err != nil { |
| 836 | return nil, err |
| 837 | } |
| 838 | |
| 839 | u, err := c.baseURL.Parse(urlStr) |
| 840 | if err != nil { |
| 841 | return nil, err |
| 842 | } |
| 843 | |
| 844 | req, err := http.NewRequestWithContext(ctx, "POST", u.String(), body) |
| 845 | if err != nil { |
| 846 | return nil, err |
| 847 | } |
| 848 | |
| 849 | req.Header.Set("Content-Type", "application/x-www-form-urlencoded") |
| 850 | req.Header.Set("Accept", mediaTypeV3) |
| 851 | if c.userAgent != "" { |
| 852 | req.Header.Set("User-Agent", c.userAgent) |
| 853 | } |
| 854 | req.Header.Set(headerAPIVersion, defaultAPIVersion) |
| 855 | |
| 856 | for _, opt := range opts { |
| 857 | opt(req) |
| 858 | } |
| 859 | |
| 860 | return req, nil |
| 861 | } |
| 862 | |
| 863 | // checkURLPathTraversal returns ErrPathForbidden if urlStr contains ".." as a |
| 864 | // path segment (e.g. "a/../b"), preventing path traversal attacks. It does not |