Skip to content

v0.9.0

Compare
Choose a tag to compare
@timostamm timostamm released this 17 May 16:20
· 216 commits to main since this release
e85cf5c

What's Changed

As of this release, connect-es supports performing idempotent, side-effect free requests using HTTP GETs. This makes it easier to cache responses in the browser, on your CDN, or in proxies and other middleboxes.

Note
This functionality is only supported when using the Connect protocol—using a Connect client with a Connect server. When using any gRPC or gRPC-web client, including createGrpcTransport() and createGrpcWebTransport() from @bufbuild/connect-web or @bufbuild/connect-node, all requests will continue to be HTTP POSTs.

To opt into GET support for a given Protobuf RPC, you must mark it as being side-effect free using the MethodOptions.IdempotencyLevel option:

service ElizaService {
  rpc Say(stream SayRequest) returns (SayResponse) {
    option idempotency_level = NO_SIDE_EFFECTS;
  }
}

With this schema change, handlers will automatically support both GET and POST requests for this RPC. However, clients will continue to use POST requests by default, even when GETs are possible. To make clients use GETs for side effect free RPCs, set the useHttpGet option:

const transport = createConnectTransport({
  // ...
  useHttpGet: true
});

Another noteworthy change is the full support of timeouts, also known as deadlines in gRPC. For example, when a client provides the timeoutMs call option, a header Connect-Timeout-Ms is added to the request. The server parses this timeout, and if it takes longer than the given timeout to process the request, it should give up, and respond with the error code deadline_exceeded.

On a connect-es server, the parsed timeout is available as an AbortSignal on the context:

import type { HandlerContext } from "@bufbuild/connect";

const say = async (req: SayRequest, ctx: HandlerContext) => {

  ctx.signal.aborted; // true if timed out
  ctx.signal.reason; // an error with code deadline_exceed if timed out
  ctx.timeoutMs(); // the remaining time in milliseconds

  // raises an error with code deadline_exceed if timed out
  ctx.signal.throwIfAborted();

  // the AbortSignal can be passed to other functions
  await longRunning(ctx.signal);

  return new SayResponse({sentence: `You said: ${req.sentence}`});
};

Enhancements

  • Add client support for Connect HTTP GET requests by @jchadwick-buf in #620
  • Add server support for Connect HTTP GET requests by @jchadwick-buf in #624
  • Allow a fetch override for connect-web by @dimitropoulos in #618
  • Support timeouts in clients by @timostamm in #635
  • Support timeouts in handlers by @timostamm in #591
  • Update HandlerContext signal to trigger on other reasons than timeouts by @johynpapin in #531
  • Add a timeout getter to the HandlerContext and export createHandlerContext by @timostamm in #632
  • Add from() and findDetails() to ConnectError by @timostamm in #638
  • Always generate files when no services exist by @sjbarag in #598

Bugfixes

  • Fix UniversalHandlers resolving the response before headers are complete by @timostamm in #588
  • Improve tests for Node.js clients and fix hanging requests by @timostamm in #619
  • Indent "idempotency" in protoc-gen-connect-es by @timostamm in #626
  • Close the session on error in client transports by @timostamm in #623
  • Raise proper Connect error codes for closed streams in handlers by @timostamm in #628
  • Support client-side cancellation in the router transport by @timostamm in #637

Breaking changes

New Contributors

Full Changelog: v0.8.6...v0.9.0