Repository: joke2k/faker

Issue:
Idea: Add Http status codes
* Faker version: 22.2.0
* OS: all

Feature suggestion : add http status code to `providers.internet` as a random integer between 100 and 599

source: https://www.rfc-editor.org/rfc/rfc9110#name-status-codes


Idea: Add Http status codes
* Faker version: 22.2.0
* OS: all

Feature suggestion : add http status code to `providers.internet` as a random integer between 100 and 599

source: https://www.rfc-editor.org/rfc/rfc9110#name-status-codes




Discussion:
> as a random integer between 100 and 599

we can already generate a "random integer between 100 and 599" with `.pyint(100, 599)`.

But I think what you mean is returning a random choice from a set of specific codes, eg:: something from [this list](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes).

Feel free to submit a Pull Request, I'll be happy to review it :)
Hello, thanks for looking at this! 
I think many users of this library would not be certain that a status code can be any integer specifically from 100 to 599 (I had to look it up) so this functionality could be useful. I think limiting it to a specific list would exclude legitimate values.

This text from the rfc says that client code MUST handle the class of non-standard codes in that range - I could specify in the docstring that it includes non-standard codes: 
_HTTP status codes are extensible. A client is not required to understand the meaning of all registered status codes, though such understanding is obviously desirable. However, a client MUST understand the class of any status code, as indicated by the first digit, and treat an unrecognized status code as being equivalent to the x00 status code of that class._
The official register lists codes as "unassigned" but not "invalid" https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
Are you thinking of basically aliasing `.pyint(100, 599)`? something like this?

```python
def http_status_code(self):
    return self.pyint(100, 599)
```

or we could let user choose, something like:

```python
def http_status_code(self, unassigned=True):
    if unassigned is True:
        return self.pyint(100, 599)
    else:
        return self.random_choice(some_list)
```

Yes I was thinking of the former but the latter, optionally limiting it to a list of assigned codes is nice.
> as a random integer between 100 and 599

we can already generate a "random integer between 100 and 599" with `.pyint(100, 599)`.

But I think what you mean is returning a random choice from a set of specific codes, eg:: something from [this list](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes).

Feel free to submit a Pull Request, I'll be happy to review it :)
Hello, thanks for looking at this! 
I think many users of this library would not be certain that a status code can be any integer specifically from 100 to 599 (I had to look it up) so this functionality could be useful. I think limiting it to a specific list would exclude legitimate values.

This text from the rfc says that client code MUST handle the class of non-standard codes in that range - I could specify in the docstring that it includes non-standard codes: 
_HTTP status codes are extensible. A client is not required to understand the meaning of all registered status codes, though such understanding is obviously desirable. However, a client MUST understand the class of any status code, as indicated by the first digit, and treat an unrecognized status code as being equivalent to the x00 status code of that class._
The official register lists codes as "unassigned" but not "invalid" https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
Are you thinking of basically aliasing `.pyint(100, 599)`? something like this?

```python
def http_status_code(self):
    return self.pyint(100, 599)
```

or we could let user choose, something like:

```python
def http_status_code(self, unassigned=True):
    if unassigned is True:
        return self.pyint(100, 599)
    else:
        return self.random_choice(some_list)
```

Yes I was thinking of the former but the latter, optionally limiting it to a list of assigned codes is nice.

Resolving patch:
diff --git a/faker/providers/internet/__init__.py b/faker/providers/internet/__init__.py
--- a/faker/providers/internet/__init__.py
+++ b/faker/providers/internet/__init__.py
@@ -131,6 +131,71 @@ class Provider(BaseProvider):
         "TRACE",
         "PATCH",
     )
+    http_assigned_codes: ElementsType[int] = (
+        100,
+        101,
+        100,
+        101,
+        102,
+        103,
+        200,
+        201,
+        202,
+        203,
+        204,
+        205,
+        206,
+        207,
+        208,
+        226,
+        300,
+        301,
+        302,
+        303,
+        304,
+        305,
+        307,
+        308,
+        400,
+        401,
+        402,
+        403,
+        404,
+        405,
+        406,
+        407,
+        408,
+        409,
+        410,
+        411,
+        412,
+        413,
+        414,
+        415,
+        416,
+        417,
+        421,
+        422,
+        423,
+        424,
+        425,
+        426,
+        428,
+        429,
+        431,
+        451,
+        500,
+        501,
+        502,
+        503,
+        504,
+        505,
+        506,
+        507,
+        508,
+        510,
+        511,
+    )
 
     user_name_formats: ElementsType[str] = (
         "{{last_name}}.{{first_name}}",
@@ -308,6 +373,23 @@ def http_method(self) -> str:
 
         return self.random_element(self.http_methods)
 
+    def http_status_code(self, include_unassigned=True) -> int:
+        """Returns random HTTP status code
+        https://www.rfc-editor.org/rfc/rfc9110#name-status-codes
+        :param include_unassigned: Whether to include status codes which have
+            not yet been assigned or are unused
+
+        :return: a random three digit status code
+        :rtype: int
+
+        :example: 404
+
+        """
+        if include_unassigned:
+            return self.random_int(min=100, max=599)
+        else:
+            return self.random_element(self.http_assigned_codes)
+
     def url(self, schemes: Optional[List[str]] = None) -> str:
         """
         :param schemes: a list of strings to use as schemes, one will chosen randomly.


Test patch:
diff --git a/tests/providers/test_internet.py b/tests/providers/test_internet.py
--- a/tests/providers/test_internet.py
+++ b/tests/providers/test_internet.py
@@ -10,6 +10,7 @@
 from validators import domain as validate_domain
 from validators import email as validate_email
 
+from faker import Generator
 from faker.providers.internet import Provider as InternetProvider
 from faker.providers.internet.az_AZ import Provider as AzAzInternetProvider
 from faker.providers.internet.en_GB import Provider as EnGbInternetProvider
@@ -339,6 +340,15 @@ def test_http_method(self, faker, num_samples):
 
         assert expected_methods == sorted(got_methods)
 
+    def test_http_status_code(self, faker, num_samples):
+        provider = InternetProvider(faker)
+        status_code = provider.http_status_code()
+        assert isinstance(status_code, int)
+        assert 100 <= status_code <= 599
+        status_code = provider.http_status_code(include_unassigned=False)
+        assert isinstance(status_code, int)
+        assert 100 <= status_code <= 599
+
     def test_dga(self, faker):
         assert faker.dga() != faker.dga()