README
¶
Nested Resources Example
This example demonstrates complex nested resource hierarchies with multiple path parameters, following a GitHub-like pattern for organizations, teams, members, and projects.
Features Demonstrated
| Feature | Description |
|---|---|
| Single path parameter | /orgs/{org_id} |
| Two path parameters | /orgs/{org_id}/teams/{team_id} |
| Three path parameters | /orgs/{org_id}/teams/{team_id}/members/{member_id} |
| Path + query params | /orgs/{org_id}/teams?include_private=true&page=1 |
| Path + request body | POST /orgs/{org_id}/teams with JSON body |
Resource Hierarchy
Organization (Level 1)
|
+-- Team (Level 2)
|
+-- Member (Level 3)
|
+-- Project (Level 3)
Quick Start
# Generate code and run the server
make demo
# Test nested resource endpoints
make test
API Endpoints
Organizations (1 path parameter)
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/orgs |
List organizations |
| GET | /api/v1/orgs/{org_id} |
Get organization |
| POST | /api/v1/orgs |
Create organization |
Teams (2 path parameters)
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/orgs/{org_id}/teams |
List teams |
| GET | /api/v1/orgs/{org_id}/teams/{team_id} |
Get team |
| POST | /api/v1/orgs/{org_id}/teams |
Create team |
Members (3 path parameters)
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/orgs/{org_id}/teams/{team_id}/members |
List members |
| GET | /api/v1/orgs/{org_id}/teams/{team_id}/members/{member_id} |
Get member |
| POST | /api/v1/orgs/{org_id}/teams/{team_id}/members |
Add member |
| DELETE | /api/v1/orgs/{org_id}/teams/{team_id}/members/{member_id} |
Remove member |
Projects (3 path parameters)
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/orgs/{org_id}/teams/{team_id}/projects |
List projects |
| GET | /api/v1/orgs/{org_id}/teams/{team_id}/projects/{project_id} |
Get project |
| POST | /api/v1/orgs/{org_id}/teams/{team_id}/projects |
Create project |
Example Requests
Get Organization (1 path parameter)
curl -X GET http://localhost:8080/api/v1/orgs/org-abc123 \
-H "Authorization: Bearer test-token"
Get Team (2 path parameters)
curl -X GET http://localhost:8080/api/v1/orgs/org-abc123/teams/team-xyz789 \
-H "Authorization: Bearer test-token"
Get Member (3 path parameters - deepest nesting)
curl -X GET http://localhost:8080/api/v1/orgs/org-abc123/teams/team-xyz789/members/member-456 \
-H "Authorization: Bearer test-token"
List Teams with Query Parameters
curl -X GET "http://localhost:8080/api/v1/orgs/org-abc123/teams?page=1&limit=10&include_private=true" \
-H "Authorization: Bearer test-token"
Create Team (path parameter + body)
curl -X POST http://localhost:8080/api/v1/orgs/org-abc123/teams \
-H "Authorization: Bearer test-token" \
-H "Content-Type: application/json" \
-d '{
"name": "New Team",
"description": "A new team",
"private": false
}'
Add Member (2 path parameters + body)
curl -X POST http://localhost:8080/api/v1/orgs/org-abc123/teams/team-xyz789/members \
-H "Authorization: Bearer test-token" \
-H "Content-Type: application/json" \
-d '{
"user_id": "user-new123",
"role": 1
}'
Remove Member (3 path parameters)
curl -X DELETE http://localhost:8080/api/v1/orgs/org-abc123/teams/team-xyz789/members/member-456 \
-H "Authorization: Bearer test-token"
Proto Definition Pattern
Path parameters are automatically extracted from the URL and bound to request fields with matching names:
// Request with 3 path parameters
message GetTeamMemberRequest {
string org_id = 1; // Bound from {org_id} in path
string team_id = 2; // Bound from {team_id} in path
string member_id = 3; // Bound from {member_id} in path
}
// Service definition
service OrganizationService {
rpc GetTeamMember(GetTeamMemberRequest) returns (Member) {
option (sebuf.http.config) = {
path: "/orgs/{org_id}/teams/{team_id}/members/{member_id}"
method: HTTP_METHOD_GET
};
}
}
Combining Path and Query Parameters
message ListTeamMembersRequest {
// From path
string org_id = 1;
string team_id = 2;
// From query string
int32 page = 3 [(sebuf.http.query) = { name: "page" }];
int32 limit = 4 [(sebuf.http.query) = { name: "limit" }];
string role_filter = 5 [(sebuf.http.query) = { name: "role" }];
}
Generated Files
After running make generate:
api/
proto/
models/
organization.pb.go # All message types
services/
organization_service.pb.go # Service interface
organization_service_http.pb.go # HTTP handlers (12 endpoints!)
organization_service_http_binding.pb.go # Request binding
organization_service_http_config.pb.go # Server options
organization_service_http_mock.pb.go # Mock implementation
docs/
OrganizationService.openapi.yaml # OpenAPI with all nested paths
OrganizationService.openapi.json
Key Concepts
Path Parameter Binding
Path parameters like {org_id} are automatically extracted from the URL and bound to the corresponding request message field. The field name must match the path variable name.
Hierarchical Resource Ownership
The nested URL structure enforces resource ownership:
- A team belongs to an organization
- A member/project belongs to a team within an organization
This is validated by including parent IDs in each request, allowing your service to verify ownership.
REST Best Practices
This example follows REST conventions:
- Collection endpoints use plural nouns (
/orgs,/teams,/members) - Single resource endpoints include the ID (
/orgs/{org_id}) - Nested resources show parent-child relationships in the URL
- HTTP verbs match the operation (GET=read, POST=create, DELETE=remove)
Documentation
¶
There is no documentation for this package.
Click to show internal directories.
Click to hide internal directories.