I've often found Cache-Control: public to be of limited use in practice
because you cannot invalidate that cache by hand. (Sometimes that's fine of
course.)
While the reverse proxy cache could provide a mechanism for explicit
expiration, there may be caches between your servers and the client, a
corporate cache for example. Those other ones are out of your control.
I suggested an extension for Rack::Cache called r-maxage that got merged:
https://github.com/rtomayko/rack-cache/pull/55
With that directive you trade the benefits of caching in intermediate
proxies with more expiration control locally.