Repository: cli/cli (Go)

Issue:
GH API `method` argument is case-sensitive
### Describe the bug

When `gh api` is used with the `--method` argument, the method provided must be in all uppercase letters. Using any other case results in the call returning HTML and a 403 status. This limitation is not mentioned in the documentation. Because the value must always be uppercase, it is recommended that the CLI automatically update the provided method verb to be uppercase.

The web server's behavior is consistent with RFC 9110 section 9.1:

> The method token is case-sensitive because it might be used as a gateway to object-based systems with case-sensitive method names. By convention, standardized methods are defined in all-uppercase US-ASCII letters.

### Steps to reproduce the behavior

1. Type `gh api --method get /orgs/<ORG>/repos`, replacing `<ORG>` with an appropriate name
2. Observe the response is HTML
3. Type `gh api --method GET /orgs/<ORG>/repos`, replacing `<ORG>` with an appropriate name
4. Observe that the response is JSON, as expected

### Expected vs actual behavior

Observed: The method is being sent as-is to the server. The server is case-sensitive, expecting an uppercase method.   
Expected: CLI tools will typically automatically convert the method to uppercase if that is a requirement of the server (or warn the user that they used an unsupported verb). For example, if a user provides a `get` method, the CLI sends it as `GET` to match the supported server values.

### Logs

```text
<!DOCTYPE html>
<html>
  <head>
    <meta content="origin" name="referrer">
    <title>Forbidden &middot; GitHub</title>
    <style type="text/css" media="screen">
      body {
        background-color: #f1f1f1;
        margin: 0;
      }
      body,
      input,
      button {
        font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
      }
      .container { margin: 30px auto 40px auto; width: 800px; text-align: center; }
      a { color: #4183c4; text-decoration: none; font-weight: bold; }
      a:hover { text-decoration: underline; }
      h1, h2, h3 { color: #666; }
      ul { list-style: none; padding: 25px 0; }
      li {
        display: inline;
        margin: 10px 50px 10px 0px;
      }
      .logo { display: inline-block; margin-top: 35px; }
      .logo-img-2x { display: none; }
      @media
      only screen and (-webkit-min-device-pixel-ratio: 2),
      only screen and (   min--moz-device-pixel-ratio: 2),
      only screen and (     -o-min-device-pixel-ratio: 2/1),
      only screen and (        min-device-pixel-ratio: 2),
      only screen and (                min-resolution: 192dpi),
      only screen and (                min-resolution: 2dppx) {
        .logo-img-1x { display: none; }
        .logo-img-2x { display: inline-block; }
      }
    </style>
  </head>
  <body>

    <div class="container">
      <h1>Access to this site has been restricted.</h1>

      <p>
        <br>
        If you believe this is an error,
        please contact <a href="https://support.github.com">Support</a>.
      </p>

      <div id="s">
        <a href="https://githubstatus.com">GitHub Status</a> &mdash;
        <a href="https://twitter.com/githubstatus">@githubstatus</a>
      </div>
    </div>
  </body>
</html>
gh: HTTP 403
```



Discussion:
@kenmuse Thank you for opening this issue. This makes sense to me but since I'm very new to the team I've added a discuss label before opening it up to be worked on.

You said:

> CLI tools will typically automatically convert the method to uppercase if that is a requirement of the server (or warn the user that they used an unsupported verb).

Can you point to some examples of other CLI tools that do this, for reference sake.


Thanks for reporting. `gh api` was modeled after `curl` which is a general-purpose API client. However, the aim of `gh api` is to communicate exclusively with the GitHub API. Since the GitHub API only supports the few standard HTTP methods, and expects them to be uppercase, I feel that it's fair that we either disallow lowercase method names, or automatically convert them to upper-case. I think automatic conversion would be the most user-friendly. Contributions welcome!

https://github.com/cli/cli/blob/b292dc43b25183024fb12b78459e0d940f524027/pkg/cmd/api/http.go#L53



Patch:
diff --git a/pkg/cmd/api/http.go b/pkg/cmd/api/http.go
index 652d11d8146..3d6bb240eae 100644
--- a/pkg/cmd/api/http.go
+++ b/pkg/cmd/api/http.go
@@ -50,7 +50,7 @@ func httpRequest(client *http.Client, hostname string, method string, p string,
 		return nil, fmt.Errorf("unrecognized parameters type: %v", params)
 	}
 
-	req, err := http.NewRequest(method, requestURL, body)
+	req, err := http.NewRequest(strings.ToUpper(method), requestURL, body)
 	if err != nil {
 		return nil, err
 	}


Test patch:
diff --git a/pkg/cmd/api/http_test.go b/pkg/cmd/api/http_test.go
index 11294a2e588..f63566490b5 100644
--- a/pkg/cmd/api/http_test.go
+++ b/pkg/cmd/api/http_test.go
@@ -129,6 +129,24 @@ func Test_httpRequest(t *testing.T) {
 				headers: "",
 			},
 		},
+		{
+			name: "lowercase HTTP method",
+			args: args{
+				client:  &httpClient,
+				host:    "github.com",
+				method:  "get",
+				p:       "repos/octocat/spoon-knife",
+				params:  nil,
+				headers: []string{},
+			},
+			wantErr: false,
+			want: expects{
+				method:  "GET",
+				u:       "https://api.github.com/repos/octocat/spoon-knife",
+				body:    "",
+				headers: "",
+			},
+		},
 		{
 			name: "GET with leading slash",
 			args: args{