Documentation
¶
Overview ¶
Package protocol provides shared AWS protocol helpers used by all service handlers: error serialisation, request IDs, ARN construction, and response writing. Nothing in this package is service-specific.
Index ¶
- Variables
- func APIV2ARN(region, apiID string) string
- func ARN(region, accountID, service, resource string) string
- func Cause(aerr *AWSError) error
- func ContextWithRequestID(ctx context.Context, id string) context.Context
- func DistributionARN(accountID, distributionID string) string
- func LambdaARN(region, accountID, functionName string) string
- func LambdaVersionARN(region, accountID, functionName string, version int) string
- func LayerARN(region, accountID, layerName string) string
- func LayerVersionARN(region, accountID, layerName string, version int) string
- func LogGroupARN(region, accountID, groupName string) string
- func LogStreamARN(region, accountID, groupName, streamName string) string
- func NewRequestID() string
- func NotImplementedEC2QueryXML(w http.ResponseWriter, r *http.Request)
- func NotImplementedJSON(w http.ResponseWriter, r *http.Request)
- func NotImplementedQueryXML(w http.ResponseWriter, r *http.Request)
- func NotImplementedXML(w http.ResponseWriter, r *http.Request)
- func QueueARN(region, accountID, queueName string) string
- func RequestIDFromContext(ctx context.Context) string
- func RestAPIARN(region, apiID string) string
- func TableARN(region, accountID, tableName string) string
- func TopicARN(region, accountID, topicName string) string
- func WriteAWSJSON(w http.ResponseWriter, r *http.Request, status int, v any, contentType string)
- func WriteEC2QueryXMLError(w http.ResponseWriter, r *http.Request, aerr *AWSError)
- func WriteEmpty(w http.ResponseWriter, r *http.Request, status int)
- func WriteJSON(w http.ResponseWriter, r *http.Request, status int, v any)
- func WriteJSONError(w http.ResponseWriter, r *http.Request, aerr *AWSError)
- func WriteQueryXML(w http.ResponseWriter, r *http.Request, status int, v any)
- func WriteQueryXMLError(w http.ResponseWriter, r *http.Request, aerr *AWSError)
- func WriteXML(w http.ResponseWriter, r *http.Request, status int, v any)
- func WriteXMLError(w http.ResponseWriter, r *http.Request, aerr *AWSError)
- type AWSError
- type ResponseMetadata
Constants ¶
This section is empty.
Variables ¶
var ( // ErrNotImplemented is returned for endpoints that exist in the routing // table but have not yet been implemented. The x-emulator-unsupported // header is added automatically by WriteXMLError / WriteJSONError. ErrNotImplemented = &AWSError{ Code: "NotImplemented", Message: "This operation is not yet emulated. Check docs/services/ for the support matrix.", HTTPStatus: http.StatusNotImplemented, } // ErrInternalError is returned when the emulator itself encounters an // unexpected failure (state backend error, serialisation failure, etc.). // Always Wrap() this with the underlying error for log context. ErrInternalError = &AWSError{ Code: "InternalError", Message: "An internal error occurred.", HTTPStatus: http.StatusInternalServerError, } // ErrServiceDisabled is returned when a request targets a service that is // known to the emulator but not enabled in the current configuration. // Callers should add the service name to OVERCAST_SERVICES to enable it. ErrServiceDisabled = &AWSError{ Code: "ServiceDisabled", Message: "This service is not enabled in this emulator. Add it to OVERCAST_SERVICES to enable it.", HTTPStatus: http.StatusServiceUnavailable, } )
Functions ¶
func APIV2ARN ¶
APIV2ARN builds an API Gateway v2 (HTTP/WebSocket) API ARN. Format: arn:aws:apigateway:{region}::/apis/{apiId}.
func ARN ¶
ARN builds an AWS ARN string. Format: arn:aws:<service>:<region>:<accountID>:<resource>
Examples:
ARN("us-east-1", "000000000000", "s3", "my-bucket")
→ "arn:aws:s3:::my-bucket" (S3 omits region and account)
ARN("us-east-1", "000000000000", "sqs", "my-queue")
→ "arn:aws:sqs:us-east-1:000000000000:my-queue"
func Cause ¶
Cause returns the underlying cause of aerr, or nil if none was set. Prefer errors.Is / errors.As over Cause for most use cases — they traverse arbitrarily deep chains. Use Cause only when you need the immediate cause.
func ContextWithRequestID ¶
ContextWithRequestID returns a new context carrying the given request ID. Called by the request-ID middleware on every incoming request.
func DistributionARN ¶
DistributionARN builds a CloudFront distribution ARN. CloudFront ARNs omit the region — this is an AWS quirk. Format: arn:aws:cloudfront::{accountID}:distribution/{distributionID}.
func LambdaVersionARN ¶
LambdaVersionARN builds a Lambda function ARN with a numeric version qualifier. Format: arn:aws:lambda:{region}:{account}:function:{name}:{version}.
func LayerARN ¶
LayerARN builds the unversioned Lambda layer ARN (no version suffix). Format: arn:aws:lambda:{region}:{account}:layer:{name}.
func LayerVersionARN ¶
LayerVersionARN builds a Lambda layer version ARN. Format: arn:aws:lambda:{region}:{account}:layer:{name}:{version}.
func LogGroupARN ¶
LogGroupARN builds a CloudWatch Logs log group ARN.
func LogStreamARN ¶
LogStreamARN builds a CloudWatch Logs log stream ARN.
func NewRequestID ¶
func NewRequestID() string
NewRequestID generates a new unique AWS-style request ID. AWS uses UUID v4 format without hyphens in some services, with hyphens in others. We always use with-hyphens — both forms are accepted by SDKs.
func NotImplementedEC2QueryXML ¶
func NotImplementedEC2QueryXML(w http.ResponseWriter, r *http.Request)
NotImplementedEC2QueryXML writes a 501 for unimplemented EC2 Query operations.
func NotImplementedJSON ¶
func NotImplementedJSON(w http.ResponseWriter, r *http.Request)
NotImplementedJSON is a convenience handler for unimplemented JSON endpoints.
func NotImplementedQueryXML ¶
func NotImplementedQueryXML(w http.ResponseWriter, r *http.Request)
NotImplementedQueryXML writes a 501 for unimplemented Query-protocol operations.
func NotImplementedXML ¶
func NotImplementedXML(w http.ResponseWriter, r *http.Request)
NotImplementedXML is a convenience handler for unimplemented S3 endpoints.
func RequestIDFromContext ¶
RequestIDFromContext retrieves the request ID stored in ctx. Returns a freshly generated ID if none was set — this is a safety net and should not happen in normal operation (the middleware always sets one).
func RestAPIARN ¶
RestAPIARN builds an API Gateway REST API ARN. API Gateway ARNs omit the account ID — this is an AWS quirk. Format: arn:aws:apigateway:{region}::/restapis/{apiId}.
func WriteAWSJSON ¶
WriteAWSJSON serialises v as JSON and writes it with the provided AWS JSON content type and request ID headers.
Pass an explicit content type per service protocol, for example:
- application/x-amz-json-1.0
- application/x-amz-json-1.1
If contentType is empty, application/x-amz-json-1.0 is used.
func WriteEC2QueryXMLError ¶
func WriteEC2QueryXMLError(w http.ResponseWriter, r *http.Request, aerr *AWSError)
WriteEC2QueryXMLError writes an EC2 Query-protocol XML error response.
func WriteEmpty ¶
func WriteEmpty(w http.ResponseWriter, r *http.Request, status int)
WriteEmpty writes a response with no body and the standard request ID header. Used for operations like DeleteObject which return 204 or an empty 200.
func WriteJSON ¶
WriteJSON serialises v as JSON and writes it with the correct Content-Type and request ID headers. Services call this for successful responses.
func WriteJSONError ¶
func WriteJSONError(w http.ResponseWriter, r *http.Request, aerr *AWSError)
WriteJSONError writes an AWS JSON-protocol error response. The cause, if any, is NOT included in the response body.
func WriteQueryXML ¶
WriteQueryXML serialises v as XML with text/xml content type. Used by Query-protocol services (SNS, STS, IAM). The request ID is set as both a response header and should be embedded in the response struct's ResponseMetadata. The request body is drained so the HTTP/1.1 connection can be reused by the SDK client.
func WriteQueryXMLError ¶
func WriteQueryXMLError(w http.ResponseWriter, r *http.Request, aerr *AWSError)
WriteQueryXMLError writes an AWS Query-protocol XML error response (SNS format).
func WriteXML ¶
WriteXML serialises v as XML and writes it with the correct Content-Type and request ID headers. Services call this for successful responses.
func WriteXMLError ¶
func WriteXMLError(w http.ResponseWriter, r *http.Request, aerr *AWSError)
WriteXMLError writes an AWS REST-XML error response (S3 format). The cause, if any, is NOT included in the response — it stays server-side for logging. The x-emulator-unsupported header is set automatically for 501.
Types ¶
type AWSError ¶
type AWSError struct {
// Code is the AWS error code string, e.g. "NoSuchBucket", "QueueDoesNotExist".
Code string
// Message is the human-readable description sent to the client.
Message string
// HTTPStatus is the HTTP status code to send, e.g. 404, 400, 500.
HTTPStatus int
// contains filtered or unexported fields
}
AWSError represents a structured AWS API error that maps to an HTTP response.
It implements the standard error interface and supports Go's error wrapping convention, equivalent to JavaScript's `new Error("msg", { cause: err })`.
Wrapping pattern — use Wrap() to attach an underlying cause while presenting a clean AWS error to callers:
// Service code:
raw, found, err := s.store.Get(ctx, ns, key)
if err != nil {
return protocol.Wrap(protocol.ErrInternalError, err)
}
// The HTTP layer sees ErrInternalError (clean AWS error code + message).
// The original err is preserved in the chain for logging and debugging:
logger.Error("state read failed", zap.Error(aerr))
// → logs both "InternalError" and the underlying storage error
Inspection pattern — anywhere in the call chain:
var aerr *protocol.AWSError
if errors.As(err, &aerr) {
// aerr.Code, aerr.HTTPStatus available
}
func AsAWSError ¶
AsAWSError extracts the first *AWSError from the error chain. Returns nil if no *AWSError is found.
This is a convenience wrapper around errors.As for the common case of checking whether an error from a helper function is an AWSError:
aerr := protocol.AsAWSError(err)
if aerr != nil {
protocol.WriteJSONError(w, r, aerr)
return
}
func ErrInvalidArgument ¶
ErrInvalidArgument returns a 400 error for malformed input.
func ErrMissingParameter ¶
ErrMissingParameter returns a 400 error for a missing required parameter.
func Wrap ¶
Wrap returns a new *AWSError with the same Code, Message, and HTTPStatus as template, but with cause attached as the underlying error.
This is the primary way to preserve error context in service code:
func (s *s3Store) getBucket(ctx context.Context, name string) (*Bucket, *AWSError) {
raw, found, err := s.store.Get(ctx, nsBuckets, name)
if err != nil {
// ErrInternalError is shown to the client.
// err (e.g. "sqlite: no such table") is preserved for logging.
return nil, protocol.Wrap(ErrInternalError, err)
}
...
}
Wrap never modifies the template — it always returns a new AWSError value.
func (*AWSError) Error ¶
Error implements the error interface. Returns the AWS error code and message; the cause is accessible via Unwrap.
func (*AWSError) Unwrap ¶
Unwrap returns the underlying cause, enabling errors.Is / errors.As to traverse the full error chain. This is the Go equivalent of error.cause in JavaScript.
// Check if a specific underlying error occurred:
if errors.Is(aerr, sql.ErrNoRows) { ... }
// Extract a specific error type from anywhere in the chain:
var pgErr *pgconn.PgError
if errors.As(aerr, &pgErr) { ... }
type ResponseMetadata ¶
type ResponseMetadata struct {
RequestID string `xml:"RequestId"`
}
ResponseMetadata is embedded in AWS Query-protocol XML responses. It carries the request ID that SDKs surface as response.ResultMetadata.
func QueryResponseMetadata ¶
func QueryResponseMetadata(r *http.Request) ResponseMetadata
QueryResponseMetadata returns a ResponseMetadata populated from the request context.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package codec defines the wire-protocol abstraction used by Overcast's typed operation dispatcher.
|
Package codec defines the wire-protocol abstraction used by Overcast's typed operation dispatcher. |
|
Package op defines the typed operation dispatcher used by Overcast's Smithy-aligned services.
|
Package op defines the typed operation dispatcher used by Overcast's Smithy-aligned services. |