mattermost/server/public/pluginapi/grpc/proto/hooks_http.proto
Nick Misasi 5c7aecda49 feat(08-02): extend protobuf contract for response streaming + flush
Add flush field to ServeHTTPResponse for best-effort HTTP flush support.
Update ServeHTTPResponse and ServeHTTPResponseInit with comprehensive
documentation of streaming invariants, message ordering, and status
code validation rules.

Changes:
- Add flush boolean field (field 4) to ServeHTTPResponse
- Document response streaming invariants (init-once, header locking)
- Document status code validation (100-999 range, 0 defaults to 200)
- Regenerate Go and Python protobuf code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 14:34:36 -05:00

170 lines
6.4 KiB
Protocol Buffer

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
syntax = "proto3";
package mattermost.pluginapi.v1;
option go_package = "github.com/mattermost/mattermost/server/public/pluginapi/grpc/generated/go/pluginapiv1";
import "hooks_common.proto";
// ==============================================================================
// HTTP STREAMING HOOK MESSAGES
// ==============================================================================
//
// This file defines request/response messages for HTTP streaming hooks:
// - ServeHTTP: Handle HTTP requests to /plugins/{plugin_id}
// - ServeMetrics: Handle metrics endpoint requests (future)
//
// STREAMING ARCHITECTURE:
// -----------------------
// ServeHTTP uses bidirectional streaming:
// - Client (Go server) streams request body chunks to Python
// - Server (Python plugin) streams response body chunks back to Go
//
// The first message in each direction contains metadata (headers, status code).
// Subsequent messages contain body chunks. A flag indicates body completion.
//
// CHUNKING:
// ---------
// Request and response bodies are chunked at 64KB boundaries to avoid
// buffering large payloads in memory. This matches gRPC best practices.
//
// CANCELLATION:
// -------------
// HTTP client disconnects are propagated via gRPC stream context.
// The Python handler should check context.cancelled() during body iteration.
//
// ==============================================================================
// Default chunk size for body streaming (64KB)
// This constant is referenced by both Go and Python implementations.
// Go: server/public/pluginapi/grpc/server/serve_http.go
// Python: python-sdk/src/mattermost_plugin/servicers/hooks_servicer.py
// -----------------------------------------------------------------------------
// HTTP Header Message
// Supports multi-value headers (e.g., Set-Cookie)
// -----------------------------------------------------------------------------
// HTTPHeader represents a single HTTP header with potentially multiple values.
// HTTP allows multiple headers with the same key (e.g., Set-Cookie).
message HTTPHeader {
string key = 1;
repeated string values = 2;
}
// -----------------------------------------------------------------------------
// ServeHTTP Request Streaming Messages
// Direction: Go server -> Python plugin
// -----------------------------------------------------------------------------
// ServeHTTPRequest is a streaming message sent from Go to Python.
// The first message contains request metadata; subsequent messages contain body chunks.
message ServeHTTPRequest {
// Request metadata (set only in first message of stream)
ServeHTTPRequestInit init = 1;
// Body chunk (may be empty in first message or if no body)
bytes body_chunk = 2;
// Indicates this is the last body chunk.
// If true, no more body chunks will follow.
// This may be set on the first message if the request has no body.
bool body_complete = 3;
}
// ServeHTTPRequestInit contains HTTP request metadata.
// Sent as part of the first ServeHTTPRequest message.
message ServeHTTPRequestInit {
// Plugin context for this request
PluginContext plugin_context = 1;
// HTTP method (GET, POST, PUT, DELETE, etc.)
string method = 2;
// Full URL as string (e.g., "http://localhost:8065/plugins/myid/api/v1/foo?bar=baz")
string url = 3;
// Protocol version (e.g., "HTTP/1.1", "HTTP/2.0")
string proto = 4;
// Major version number (e.g., 1 for HTTP/1.1)
int32 proto_major = 5;
// Minor version number (e.g., 1 for HTTP/1.1)
int32 proto_minor = 6;
// HTTP headers (supports multi-value headers)
repeated HTTPHeader headers = 7;
// Host header value (may differ from URL host for virtual hosting)
string host = 8;
// Remote address of the client (e.g., "192.168.1.1:12345")
string remote_addr = 9;
// The original request URI as received (includes query string)
string request_uri = 10;
// Content-Length if known, -1 if unknown/chunked
int64 content_length = 11;
}
// -----------------------------------------------------------------------------
// ServeHTTP Response Streaming Messages
// Direction: Python plugin -> Go server
// -----------------------------------------------------------------------------
// ServeHTTPResponse is a streaming message sent from Python to Go.
// The first message contains response metadata; subsequent messages contain body chunks.
//
// RESPONSE STREAMING INVARIANTS:
// - Exactly one response-init must be sent (explicitly or implicitly on first body write)
// - Status code defaults to 200 if not set before first body write
// - Headers are only accepted before the first body write (locked after init)
// - Flush may be sent any time after response-init; Go ignores if underlying writer doesn't support it
// - body_complete=true signals end of response; no more messages should follow
//
// MESSAGE ORDERING:
// 1. First message: init (status + headers) with optional body_chunk
// 2. Subsequent messages: body_chunk and/or flush
// 3. Final message: body_complete=true (may include final body_chunk)
message ServeHTTPResponse {
// Response metadata (set only in first message of stream)
// MUST be present in first message. Status code range must be 100-999.
ServeHTTPResponseInit init = 1;
// Body chunk (may be empty in first message or if no body)
// Recommended max chunk size: 64KB
bytes body_chunk = 2;
// Indicates this is the last body chunk.
// If true, no more body chunks will follow.
bool body_complete = 3;
// Request an immediate flush of buffered response data to the client.
// Best-effort: Go will call http.Flusher.Flush() if the underlying
// ResponseWriter supports it; otherwise silently ignored.
// This matches Go plugin RPC behavior (see plugin/http.go).
bool flush = 4;
}
// ServeHTTPResponseInit contains HTTP response metadata.
// Sent as part of the first ServeHTTPResponse message.
//
// VALIDATION:
// - status_code must be in range 100-999 (per HTTP spec)
// - Invalid status codes cause Go to return 500 and log an error
// - status_code of 0 defaults to 200 OK
message ServeHTTPResponseInit {
// HTTP status code (e.g., 200, 404, 500)
// Must be in range 100-999. 0 defaults to 200.
// Invalid values (< 100 or > 999) will be rejected with 500 error.
int32 status_code = 1;
// HTTP response headers (supports multi-value headers)
// Headers are immutable after init is sent.
repeated HTTPHeader headers = 2;
}