github.com/storacha/go-ucanto@v0.7.2/transport/car/codec.go (about) 1 package car 2 3 import ( 4 "net/http" 5 "strings" 6 7 "github.com/storacha/go-ucanto/core/message" 8 "github.com/storacha/go-ucanto/transport" 9 "github.com/storacha/go-ucanto/transport/car/request" 10 "github.com/storacha/go-ucanto/transport/car/response" 11 thttp "github.com/storacha/go-ucanto/transport/http" 12 ) 13 14 type carOutbound struct{} 15 16 func (oc *carOutbound) Encode(msg message.AgentMessage) (transport.HTTPRequest, error) { 17 return request.Encode(msg) 18 } 19 20 func (oc *carOutbound) Decode(res transport.HTTPResponse) (message.AgentMessage, error) { 21 return response.Decode(res) 22 } 23 24 var _ transport.OutboundCodec = (*carOutbound)(nil) 25 26 func NewOutboundCodec() transport.OutboundCodec { 27 return &carOutbound{} 28 } 29 30 type carInboundAcceptCodec struct{} 31 32 func (cic *carInboundAcceptCodec) Encoder() transport.ResponseEncoder { 33 return cic 34 } 35 36 func (cic *carInboundAcceptCodec) Decoder() transport.RequestDecoder { 37 return cic 38 } 39 40 func (cic *carInboundAcceptCodec) Encode(msg message.AgentMessage) (transport.HTTPResponse, error) { 41 return response.Encode(msg) 42 } 43 44 func (cic *carInboundAcceptCodec) Decode(req transport.HTTPRequest) (message.AgentMessage, error) { 45 return request.Decode(req) 46 } 47 48 type carInbound struct { 49 codec transport.InboundAcceptCodec 50 } 51 52 func (ic *carInbound) Accept(req transport.HTTPRequest) (transport.InboundAcceptCodec, transport.HTTPError) { 53 // TODO: select a decoder - we only support 1 ATM 54 contentType := req.Headers().Get("Content-Type") 55 if contentType != request.ContentType { 56 headers := http.Header{} 57 headers.Set("Accept", contentType) 58 return nil, thttp.NewHTTPError( 59 "The server cannot process the request because the payload format is not supported. Please check the content-type header and try again with a supported media type.", 60 http.StatusUnsupportedMediaType, 61 headers, 62 ) 63 } 64 65 // TODO: select an encoder by desired preference (q=) - we only support 1 ATM 66 accept := req.Headers().Get("Accept") 67 if accept == "" { 68 accept = "*/*" 69 } 70 if accept != "*/*" && !strings.Contains(accept, contentType) { 71 headers := http.Header{} 72 headers.Set("Accept", contentType) 73 return nil, thttp.NewHTTPError( 74 "The requested resource cannot be served in the requested content type. Please specify a supported content type using the Accept header.", 75 http.StatusNotAcceptable, 76 headers, 77 ) 78 } 79 80 return ic.codec, nil 81 } 82 83 var _ transport.InboundCodec = (*carInbound)(nil) 84 85 func NewInboundCodec() transport.InboundCodec { 86 return &carInbound{codec: &carInboundAcceptCodec{}} 87 }