Get Requests and Caching
Connect supports performing idempotent, side-effect free requests using an HTTP GET-based protocol. This makes it easier to cache certain kinds of requests in the browser, on your CDN, or in proxies and other middleboxes.
If you are using clients to make query-style requests, you may want the ability
to use Connect HTTP GET request support. To opt-in for a given procedure, you
must mark it as being side-effect free using the
MethodOptions.IdempotencyLevel option:
service GreetService { rpc Greet(GreetRequest) returns (GreetResponse) { option idempotency_level = NO_SIDE_EFFECTS; }}Handlers will automatically support GET requests using this option.
GET is currently not supported in generated client code. For other clients, see their respective documentation pages:
Caching
Section titled “Caching”Using GET requests will not necessarily automatically make browsers or proxies cache your RPCs. To ensure that requests are allowed to be cached, a handler should also set the appropriate headers.
For example, you may wish to set the Cache-Control header with a max-age
directive:
Ok(Response::new(GreetResponse::default()).with_header("cache-control", "max-age=604800"))This would instruct agents and proxies that the request may be cached for up to
7 days, after which it must be re-requested. There are other
Cache-Control Response Directives that
may be useful for your application as well; for example, the private directive
would specify that the request should only be cached in private caches, such as
the user agent itself, and not CDNs or reverse proxies—this would be
appropriate, for example, for authenticated requests.
Distinguishing GET Requests
Section titled “Distinguishing GET Requests”In some cases, you might want to introduce behavior that only occurs when
handling HTTP GET requests. The RequestContext doesn’t include the HTTP
method, but Tower middleware can add it to the request’s extensions, which
are passed through to handlers. For example, with axum middleware:
use axum::extract::Request;
let app = axum::Router::new() .fallback_service(router.into_axum_service()) .layer(axum::middleware::map_request(|mut req: Request| async move { let method = req.method().clone(); req.extensions_mut().insert(method); req }));Handlers can then read the method from the RequestContext:
let mut res = Response::new(GreetResponse::default());if ctx.extensions().get::<http::Method>() == Some(&http::Method::GET) { res = res.with_header("cache-control", "max-age=604800");}