Download Latest Version webrpc-gen.windows-amd64.exe (17.5 MB)
Email in envelope

Get an email when there's a new version of webrpc

Home / v0.46.0
Name Modified Size InfoDownloads / Week
Parent folder
checksums.txt 2026-08-31 1.1 kB
webrpc-gen.linux-amd64 2026-08-31 16.9 MB
webrpc-test.linux-amd64 2026-08-31 9.1 MB
webrpc-test.windows-amd64.exe 2026-08-31 9.3 MB
webrpc-test.windows-arm64.exe 2026-08-31 8.6 MB
webrpc-gen.darwin-amd64 2026-08-31 17.4 MB
webrpc-test.darwin-amd64 2026-08-31 9.2 MB
webrpc-test.darwin-arm64 2026-08-31 8.7 MB
webrpc-test.linux-arm64 2026-08-31 8.5 MB
webrpc-gen.darwin-arm64 2026-08-31 16.4 MB
webrpc-gen.linux-arm64 2026-08-31 15.7 MB
webrpc-gen.windows-amd64.exe 2026-08-31 17.5 MB
webrpc-gen.windows-arm64.exe 2026-08-31 16.1 MB
README.md 2026-08-29 5.6 kB
v0.46.0 source code.tar.gz 2026-08-29 799.4 kB
v0.46.0 source code.zip 2026-08-29 910.1 kB
Totals: 16 Items   155.2 MB 0

Go package

go get github.com/webrpc/webrpc@v0.46.0

What's Changed

Other changes

Adds a file core type to webrpc for HTTP file uploads and downloads.

Before: methods carry JSON-only payloads — there is no way to describe a file upload or download in RIDL, and generated servers accept only application/json.

After: file is a core type usable in method inputs (file, []file) and as a method's single output. Uploads travel as multipart/form-data (a json part with the non-file fields first, then one part per file); downloads stream the raw response body with Content-Type, inline Content-Disposition, and nosniff. Errors keep the standard JSON envelope. Non-file schemas generate byte-identical code.

Example RIDL

:::ridl
service ExampleService

  - UploadAvatar(UploadAvatarRequest) => (UploadAvatarResponse)
  - DownloadAvatar(DownloadAvatarRequest) => (file)

struct UploadAvatarRequest

  - userId: uint64
  - avatar: file

struct UploadAvatarResponse

  - size: uint64

struct DownloadAvatarRequest

  - userId: uint64

Go

:::go
// Server — handlers stay transport-free; generated code sets headers and streams.
func (s *Server) UploadAvatar(ctx context.Context, req *proto.UploadAvatarRequest) (*proto.UploadAvatarResponse, error) {
    defer req.Avatar.Body.Close()
    n, err := io.Copy(dst, req.Avatar.Body) // streams straight off the socket, no spooling
    return &proto.UploadAvatarResponse{Size: uint64(n)}, err
}

func (s *Server) DownloadAvatar(ctx context.Context, req *proto.DownloadAvatarRequest) (*proto.File, error) {
    f, err := os.Open(path)
    if err != nil {
        return nil, proto.ErrNotFound
    }
    return &proto.File{Name: "avatar.png", ContentType: "image/png", Size: size, Body: f}, nil
}

// Client
f, _ := os.Open("me.png")
resp, err := client.UploadAvatar(ctx, &proto.UploadAvatarRequest{UserId: 1,
    Avatar: &proto.File{Name: "me.png", ContentType: "image/png", Body: f}})

file, err := client.DownloadAvatar(ctx, &proto.DownloadAvatarRequest{UserId: 1})
defer file.Body.Close() // same convention as http.Response.Body

TypeScript / React

:::tsx
import { useEffect, useState } from 'react'
import { Example } from './client.gen'

const client = new Example('http://localhost:8080', fetch)

export function AvatarUploader({ userId }: { userId: number }) {
  const [previewUrl, setPreviewUrl] = useState<string>()

  const onChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
    for (const avatar of e.target.files ?? []) {
      await client.uploadAvatar({ userId, avatar })   // platform File, multipart, streamed
    }
    const file = await client.downloadAvatar({ userId })
    setPreviewUrl(URL.createObjectURL(await file.blob()))  // live preview (inline disposition)
  }

  useEffect(() => () => { previewUrl && URL.revokeObjectURL(previewUrl) }, [previewUrl])

  return (
    <div>
      <input type="file" multiple onChange={onChange} />
      {previewUrl && <img src={previewUrl} alt="avatar preview" />}
    </div>
  )
}

Notes

  • All seven generator targets support the type: Go and TypeScript servers + clients; JavaScript, Kotlin, Dart, and Swift clients; OpenAPI emits multipart/binary schemas. The JavaScript Express server errors clearly at generation time on file schemas.
  • Go streams end to end: uploads are never spooled to memory or disk, downloads copy reader-to-writer. With []file, bodies are read in wire order.
  • Cross-language wire tests live in tests/interop-web (TS/JS clients against Go/TS servers, byte-compared); tests/schema/test.ridl covers file round-trips through webrpc-test.
  • Body is io.ReadCloser with net/http closing conventions: generated code closes what it finishes with; the only manual close is a downloaded file on the client.

Full Changelog: https://github.com/webrpc/webrpc/compare/v0.45.0...v0.46.0

Docker

docker pull ghcr.io/webrpc/webrpc-gen:v0.46.0

Example: docker run -v $PWD:$PWD ghcr.io/webrpc/webrpc-gen:v0.46.0 -schema=$PWD/api.ridl -target=golang

Homebrew

brew tap webrpc/tap
brew install webrpc-gen

Build from source

go install -ldflags="-s -w -X github.com/webrpc/webrpc.VERSION=v0.46.0" github.com/webrpc/webrpc/cmd/webrpc-gen@v0.46.0

Download binaries

macOS: amd64, arm64 (Apple Silicon) Linux: amd64, arm64 Windows: amd64, arm64

Source: README.md, updated 2026-08-29