Repository: falconry/falcon
Pull request #1298 (2018-05-15 14:32:26)

feat(response): add expires property #1268
Closes: #1268

codecov[bot]: # [Codecov](https://codecov.io/gh/falconry/falcon/pull/1298?src=pr&el=h1) Report
> Merging [#1298](https://codecov.io/gh/falconry/falcon/pull/1298?src=pr&el=desc) into [master](https://codecov.io/gh/falconry/falcon/commit/16903f9fa8da2a2055f50fd6c87194e66bb78099?src=pr&el=desc) will **not change** coverage.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/falconry/falcon/pull/1298/graphs/tree.svg?src=pr&width=650&token=zOtkfNQ3h6&height=150)](https://codecov.io/gh/falconry/falcon/pull/1298?src=pr&el=tree)

```diff
@@          Coverage Diff           @@
##           master   #1298   +/-   ##
======================================
  Coverage     100%    100%           
======================================
  Files          39      39           
  Lines        2534    2536    +2     
  Branches      384     384           
======================================
+ Hits         2534    2536    +2
```


| [Impacted Files](https://codecov.io/gh/falconry/falcon/pull/1298?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [falcon/response.py](https://codecov.io/gh/falconry/falcon/pull/1298/diff?src=pr&el=tree#diff-ZmFsY29uL3Jlc3BvbnNlLnB5) | `100% <100%> (ø)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/falconry/falcon/pull/1298?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/falconry/falcon/pull/1298?src=pr&el=footer). Last update [16903f9...bd28048](https://codecov.io/gh/falconry/falcon/pull/1298?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/falcon/response.py b/falcon/response.py
index c7f909b..6819d4f 100644
--- a/falcon/response.py
+++ b/falcon/response.py
@@ -724,6 +724,15 @@ class Response(object):
         """,
         format_etag_header)
 
+    expires = header_property(
+        'Expires',
+        """Set the Expires header. Set to a ``datetime`` (UTC) instance.
+
+        Note:
+            Falcon will format the ``datetime`` as an HTTP date string.
+        """,
+        dt_to_http)
+
     last_modified = header_property(
         'Last-Modified',
         """Set the Last-Modified header. Set to a ``datetime`` (UTC) instance.


Test patch:
diff --git a/tests/test_headers.py b/tests/test_headers.py
index 8025e96..56a8e30 100644
--- a/tests/test_headers.py
+++ b/tests/test_headers.py
@@ -211,6 +211,15 @@ class ContentLengthHeaderResource(object):
         resp.body = self._body
 
 
+class ExpiresHeaderResource(object):
+
+    def __init__(self, expires):
+        self._expires = expires
+
+    def on_get(self, req, resp):
+        resp.expires = self._expires
+
+
 class TestHeaders(object):
 
     def test_content_length(self, client):
@@ -234,6 +243,13 @@ class TestHeaders(object):
 
         assert result.headers['Content-Length'] == '42'
 
+    def test_expires_header(self, client):
+        expires = datetime(2013, 1, 1, 10, 30, 30)
+        client.app.add_route('/', ExpiresHeaderResource(expires))
+        result = client.simulate_get()
+
+        assert result.headers['Expires'] == 'Tue, 01 Jan 2013 10:30:30 GMT'
+
     def test_default_value(self, client):
         resource = testing.SimpleTestResource(body=SAMPLE_BODY)
         client.app.add_route('/', resource)