blob: ea2c01fdadbf12b846b298a460675e185b0dbc2b [file] [log] [blame]
D. Can Celasun4f77ab82017-09-21 15:21:00 +02001package thrift
2
John Boiles57852792018-01-05 14:37:05 -08003import (
4 "context"
5 "fmt"
6)
7
Yuxuan 'fishy' Wangc2ddaf02021-01-22 09:37:18 -08008// ResponseMeta represents the metadata attached to the response.
9type ResponseMeta struct {
10 // The headers in the response, if any.
11 // If the underlying transport/protocol is not THeader, this will always be nil.
12 Headers THeaderMap
13}
14
John Boiles57852792018-01-05 14:37:05 -080015type TClient interface {
Yuxuan 'fishy' Wangc2ddaf02021-01-22 09:37:18 -080016 Call(ctx context.Context, method string, args, result TStruct) (ResponseMeta, error)
John Boiles57852792018-01-05 14:37:05 -080017}
D. Can Celasun4f77ab82017-09-21 15:21:00 +020018
19type TStandardClient struct {
20 seqId int32
21 iprot, oprot TProtocol
22}
23
24// TStandardClient implements TClient, and uses the standard message format for Thrift.
25// It is not safe for concurrent use.
26func NewTStandardClient(inputProtocol, outputProtocol TProtocol) *TStandardClient {
27 return &TStandardClient{
28 iprot: inputProtocol,
29 oprot: outputProtocol,
30 }
31}
32
John Boiles57852792018-01-05 14:37:05 -080033func (p *TStandardClient) Send(ctx context.Context, oprot TProtocol, seqId int32, method string, args TStruct) error {
Yuxuan 'fishy' Wang26ef9042019-08-19 00:18:22 -070034 // Set headers from context object on THeaderProtocol
35 if headerProt, ok := oprot.(*THeaderProtocol); ok {
36 headerProt.ClearWriteHeaders()
37 for _, key := range GetWriteHeaderList(ctx) {
38 if value, ok := GetHeader(ctx, key); ok {
39 headerProt.SetWriteHeader(key, value)
40 }
41 }
42 }
43
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -070044 if err := oprot.WriteMessageBegin(ctx, method, CALL, seqId); err != nil {
D. Can Celasun4f77ab82017-09-21 15:21:00 +020045 return err
46 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -070047 if err := args.Write(ctx, oprot); err != nil {
D. Can Celasun4f77ab82017-09-21 15:21:00 +020048 return err
49 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -070050 if err := oprot.WriteMessageEnd(ctx); err != nil {
D. Can Celasun4f77ab82017-09-21 15:21:00 +020051 return err
52 }
John Boiles57852792018-01-05 14:37:05 -080053 return oprot.Flush(ctx)
D. Can Celasun4f77ab82017-09-21 15:21:00 +020054}
55
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -070056func (p *TStandardClient) Recv(ctx context.Context, iprot TProtocol, seqId int32, method string, result TStruct) error {
57 rMethod, rTypeId, rSeqId, err := iprot.ReadMessageBegin(ctx)
D. Can Celasun4f77ab82017-09-21 15:21:00 +020058 if err != nil {
59 return err
60 }
61
62 if method != rMethod {
63 return NewTApplicationException(WRONG_METHOD_NAME, fmt.Sprintf("%s: wrong method name", method))
64 } else if seqId != rSeqId {
65 return NewTApplicationException(BAD_SEQUENCE_ID, fmt.Sprintf("%s: out of order sequence response", method))
66 } else if rTypeId == EXCEPTION {
67 var exception tApplicationException
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -070068 if err := exception.Read(ctx, iprot); err != nil {
D. Can Celasun4f77ab82017-09-21 15:21:00 +020069 return err
70 }
71
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -070072 if err := iprot.ReadMessageEnd(ctx); err != nil {
D. Can Celasun4f77ab82017-09-21 15:21:00 +020073 return err
74 }
75
76 return &exception
77 } else if rTypeId != REPLY {
78 return NewTApplicationException(INVALID_MESSAGE_TYPE_EXCEPTION, fmt.Sprintf("%s: invalid message type", method))
79 }
80
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -070081 if err := result.Read(ctx, iprot); err != nil {
D. Can Celasun4f77ab82017-09-21 15:21:00 +020082 return err
83 }
84
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -070085 return iprot.ReadMessageEnd(ctx)
D. Can Celasun4f77ab82017-09-21 15:21:00 +020086}
87
Yuxuan 'fishy' Wangc2ddaf02021-01-22 09:37:18 -080088func (p *TStandardClient) Call(ctx context.Context, method string, args, result TStruct) (ResponseMeta, error) {
D. Can Celasun4f77ab82017-09-21 15:21:00 +020089 p.seqId++
90 seqId := p.seqId
91
John Boiles57852792018-01-05 14:37:05 -080092 if err := p.Send(ctx, p.oprot, seqId, method, args); err != nil {
Yuxuan 'fishy' Wangc2ddaf02021-01-22 09:37:18 -080093 return ResponseMeta{}, err
D. Can Celasun4f77ab82017-09-21 15:21:00 +020094 }
95
96 // method is oneway
97 if result == nil {
Yuxuan 'fishy' Wangc2ddaf02021-01-22 09:37:18 -080098 return ResponseMeta{}, nil
D. Can Celasun4f77ab82017-09-21 15:21:00 +020099 }
100
Yuxuan 'fishy' Wangc2ddaf02021-01-22 09:37:18 -0800101 err := p.Recv(ctx, p.iprot, seqId, method, result)
102 var headers THeaderMap
103 if hp, ok := p.iprot.(*THeaderProtocol); ok {
104 headers = hp.transport.readHeaders
105 }
106 return ResponseMeta{
107 Headers: headers,
108 }, err
D. Can Celasun4f77ab82017-09-21 15:21:00 +0200109}