Skip to content

Commit da60cd9

Browse files
authored
Merge pull request #650 from marle3003/develop
Develop
2 parents d6124d2 + 2b0d3a7 commit da60cd9

File tree

21 files changed

+816
-111
lines changed

21 files changed

+816
-111
lines changed

.github/actions/build-mokapi-image/action.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ runs:
1515
using: "composite"
1616
steps:
1717
- name: Build docker alpha image
18-
run: docker build --build-arg VERSION=${{ inputs.version }} -t ${{ inputs.image-name }} -f ./images/alpha.Dockerfile .
18+
run: docker build --build-arg VERSION=${{ inputs.version }} -t ${{ inputs.image-name }} -t mokapi/mokapi:alpha -f ./images/alpha.Dockerfile .
1919
shell: bash
2020
- name: Save Image to file
21-
run: docker save ${{ inputs.image-name }} > /tmp/mokapi.tar
21+
run: docker save -o /tmp/mokapi.tar ${{ inputs.image-name }} mokapi/mokapi:alpha
2222
shell: bash
2323
- name: Upload image
2424
uses: actions/upload-artifact@v4

.github/actions/publish-docker-image/action.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ runs:
3030
with:
3131
username: ${{ inputs.docker-username }}
3232
password: ${{ inputs.docker-password }}
33-
- name: Push image to Docker
33+
- name: Push image mokapi/mokapi:v-alpha to Docker
3434
run: docker push ${{ inputs.image-name }}
35+
shell: bash
36+
- name: Push image mokapi/mokapi:alpha to Docker
37+
run: docker push mokapi/mokapi:alpha
3538
shell: bash

acceptance/mail_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@ package acceptance
33
import (
44
"crypto/tls"
55
"encoding/json"
6+
"fmt"
67
"github.com/stretchr/testify/require"
78
"mokapi/config/static"
89
"mokapi/server/cert"
910
"mokapi/smtp/smtptest"
1011
"mokapi/try"
1112
"net"
13+
"net/http"
1214
"os"
1315
"path"
1416
"testing"
@@ -25,6 +27,7 @@ func (suite *MailSuite) SetupSuite() {
2527
cfg.Certificates.Static = []static.Certificate{
2628
{Cert: "./mail/mail.mokapi.local.pem"},
2729
}
30+
cfg.Api.Search.Enabled = true
2831
suite.initCmd(cfg)
2932
}
3033

@@ -151,6 +154,21 @@ func (suite *MailSuite) TestSendMail() {
151154
//require.NoError(suite.T(), err)
152155
}
153156

157+
func (suite *MailSuite) TestSearch() {
158+
try.GetRequest(suite.T(), fmt.Sprintf("http://127.0.0.1:%v/api/search/query?q=Mokapi%%20MailServer", suite.cfg.Api.Port),
159+
nil,
160+
try.HasStatusCode(http.StatusOK),
161+
try.AssertBody(func(t *testing.T, body string) {
162+
var data map[string]any
163+
err := json.Unmarshal([]byte(body), &data)
164+
require.NoError(t, err)
165+
require.NotNil(t, data)
166+
167+
require.Equal(t, float64(5), data["total"])
168+
}),
169+
)
170+
}
171+
154172
func (suite *MailSuite) TestSendMail_OldFormat() {
155173
err := smtptest.SendMail("[email protected]",
156174

api/handler_kafka.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ func (h *handler) handleKafka(w http.ResponseWriter, r *http.Request) {
340340
if errors.Is(err, store.TopicNotFound) || errors.Is(err, store.PartitionNotFound) {
341341
http.Error(w, err.Error(), http.StatusNotFound)
342342
} else {
343-
http.Error(w, err.Error(), http.StatusBadRequest)
343+
http.Error(w, err.Error(), http.StatusInternalServerError)
344344
}
345345
return
346346
}

api/handler_kafka_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,7 @@ func TestHandler_KafkaAPI(t *testing.T) {
656656

657657
c := store.NewClient(app.Kafka.Get("foo").Store, app.Monitor.Kafka)
658658
ct := media.ParseContentType("application/json")
659-
c.Write("topic-1", []store.Record{
659+
_, _ = c.Write("topic-1", []store.Record{
660660
{
661661
Key: "foo",
662662
Value: map[string]interface{}{"value": "bar"},
@@ -673,7 +673,7 @@ func TestHandler_KafkaAPI(t *testing.T) {
673673
"",
674674
api,
675675
try.HasStatusCode(http.StatusOK),
676-
try.HasBody(`[{"Key":"foo","Value":{"value":"bar"},"Headers":null,"Partition":0}]`),
676+
try.HasBody(`[{"offset":0,"key":"foo","value":{"value":"bar"},"partition":0}]`),
677677
)
678678
},
679679
},
@@ -695,7 +695,7 @@ func TestHandler_KafkaAPI(t *testing.T) {
695695

696696
c := store.NewClient(app.Kafka.Get("foo").Store, app.Monitor.Kafka)
697697
ct := media.ParseContentType("application/json")
698-
c.Write("topic-1", []store.Record{
698+
_, _ = c.Write("topic-1", []store.Record{
699699
{
700700
Key: "foo",
701701
Value: map[string]interface{}{"value": "bar"},
@@ -712,7 +712,7 @@ func TestHandler_KafkaAPI(t *testing.T) {
712712
"",
713713
api,
714714
try.HasStatusCode(http.StatusOK),
715-
try.HasBody(`{"Key":"foo","Value":{"value":"bar"},"Headers":null,"Partition":0}`),
715+
try.HasBody(`{"offset":0,"key":"foo","value":{"value":"bar"},"partition":0}`),
716716
)
717717
},
718718
},

engine/kafka.go

Lines changed: 6 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,15 @@ func (c *KafkaClient) Produce(args *common.KafkaProduceArgs) (*common.KafkaProdu
7878
}
7979
}
8080

81+
var headers []store.RecordHeader
82+
for hk, hv := range r.Headers {
83+
headers = append(headers, store.RecordHeader{Name: hk, Value: hv})
84+
}
85+
8186
rec, err := client.Write(t.Name, []store.Record{{
8287
Key: r.Key,
8388
Value: value,
84-
Headers: r.Headers,
89+
Headers: headers,
8590
Partition: r.Partition,
8691
}}, ct)
8792
if err != nil {
@@ -210,60 +215,6 @@ func createValue(r *asyncapi3.SchemaRef) (value interface{}, err error) {
210215
return
211216
}
212217

213-
func marshal(value interface{}, r *asyncapi3.SchemaRef, contentType string) ([]byte, error) {
214-
var s asyncapi3.Schema
215-
if r != nil && r.Value != nil && r.Value.Schema != nil {
216-
s = r.Value.Schema
217-
} else {
218-
s = &schema.Schema{}
219-
}
220-
221-
switch v := s.(type) {
222-
case *schema.Schema:
223-
return encoding.NewEncoder(v).Write(value, media.ParseContentType(contentType))
224-
case *openapi.Schema:
225-
return v.Marshal(value, media.ParseContentType(contentType))
226-
case *avro.Schema:
227-
jsSchema := v.Convert()
228-
return encoding.NewEncoder(jsSchema).Write(value, media.ParseContentType(contentType))
229-
default:
230-
return nil, fmt.Errorf("schema format not supported: %v", r.Value.Format)
231-
}
232-
}
233-
234-
func marshalKey(key interface{}, r *asyncapi3.SchemaRef) ([]byte, error) {
235-
var s asyncapi3.Schema
236-
if r != nil && r.Value != nil && r.Value.Schema != nil {
237-
s = r.Value.Schema
238-
} else {
239-
s = &schema.Schema{}
240-
}
241-
242-
switch v := s.(type) {
243-
case *schema.Schema:
244-
if v.IsObject() || v.IsArray() {
245-
return encoding.NewEncoder(v).Write(key, media.ParseContentType("application/json"))
246-
} else {
247-
return []byte(fmt.Sprintf("%v", key)), nil
248-
}
249-
case *openapi.Schema:
250-
if v.Type.IsObject() || v.Type.IsArray() {
251-
return v.Marshal(key, media.ParseContentType("application/json"))
252-
} else {
253-
return []byte(fmt.Sprintf("%v", key)), nil
254-
}
255-
case *avro.Schema:
256-
jsSchema := v.Convert()
257-
if jsSchema.IsObject() || jsSchema.IsArray() {
258-
return encoding.NewEncoder(jsSchema).Write(key, media.ParseContentType("application/json"))
259-
} else {
260-
return []byte(fmt.Sprintf("%v", key)), nil
261-
}
262-
default:
263-
return nil, fmt.Errorf("schema format not supported: %v", r.Value.Format)
264-
}
265-
}
266-
267218
func selectMessage(value any, topic *asyncapi3.Channel, cfg *asyncapi3.Config) (*asyncapi3.Message, error) {
268219
noOperationDefined := true
269220

examples/mokapi/kafka.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,8 +436,22 @@ components:
436436
Record:
437437
type: object
438438
properties:
439+
offset:
440+
type: integer
439441
key: {}
440442
value: {}
443+
headers:
444+
type: array
445+
items:
446+
type: object
447+
properties:
448+
name:
449+
type: string
450+
value:
451+
type: string
452+
partition:
453+
type: integer
454+
441455
ProducedRecord:
442456
type: object
443457
properties:

kafka/pagebuffer.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ type bytesReader struct {
1616
}
1717

1818
func NewBytes(b []byte) Bytes {
19+
if len(b) == 0 {
20+
return nil
21+
}
1922
r := new(bytesReader)
2023
r.Reset(b)
2124
return r

providers/asyncapi3/kafka/store/client.go

Lines changed: 64 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,24 @@ var TopicNotFound = errors.New("topic not found")
1818
var PartitionNotFound = errors.New("partition not found")
1919

2020
type Record struct {
21-
Key any
22-
Value any
23-
Headers map[string]string
24-
Partition int
21+
Offset int64 `json:"offset"`
22+
Key any `json:"key"`
23+
Value any `json:"value"`
24+
Headers []RecordHeader `json:"headers,omitempty"`
25+
Partition int `json:"partition"`
26+
}
27+
28+
type RecordHeader struct {
29+
Name string `json:"name"`
30+
Value string `json:"value"`
2531
}
2632

2733
type RecordResult struct {
2834
Partition int
2935
Offset int64
3036
Key []byte
3137
Value []byte
38+
Headers []RecordHeader
3239
Error string
3340
}
3441

@@ -76,10 +83,10 @@ func (c *Client) Write(topic string, records []Record, ct *media.ContentType) ([
7683
Key: kafka.NewBytes(key),
7784
Value: kafka.NewBytes(value),
7885
}
79-
for name, val := range r.Headers {
86+
for _, h := range r.Headers {
8087
rec.Headers = append(rec.Headers, kafka.RecordHeader{
81-
Key: name,
82-
Value: []byte(val),
88+
Key: h.Name,
89+
Value: []byte(h.Value),
8390
})
8491
}
8592
b := kafka.RecordBatch{Records: []*kafka.Record{rec}}
@@ -98,12 +105,19 @@ func (c *Client) Write(topic string, records []Record, ct *media.ContentType) ([
98105
Error: res[0].BatchIndexErrorMessage,
99106
})
100107
} else {
101-
result = append(result, RecordResult{
108+
rr := RecordResult{
102109
Offset: offset,
103110
Key: kafka.Read(b.Records[0].Key),
104111
Value: kafka.Read(b.Records[0].Value),
105112
Partition: p.Index,
106-
})
113+
}
114+
for _, h := range b.Records[0].Headers {
115+
rr.Headers = append(rr.Headers, RecordHeader{
116+
Name: h.Key,
117+
Value: string(h.Value),
118+
})
119+
}
120+
result = append(result, rr)
107121
c.store.UpdateMetrics(c.monitor, t, p, b)
108122
}
109123
}
@@ -133,36 +147,50 @@ func (c *Client) Read(topic string, partition int, offset int64, ct *media.Conte
133147
}
134148

135149
records := []Record{}
136-
switch ct.Key() {
137-
case "application/vnd.mokapi.kafka.binary+json":
138-
for _, r := range b.Records {
139-
var bKey []byte
140-
base64.StdEncoding.Encode(bKey, kafka.Read(r.Key))
141-
var bValue []byte
142-
base64.StdEncoding.Encode(bValue, kafka.Read(r.Value))
143-
records = append(records, Record{
144-
Key: string(bKey),
145-
Value: string(bValue),
146-
})
150+
var getValue func(value []byte) (any, error)
151+
switch {
152+
case ct.Key() == "application/vnd.mokapi.kafka.binary+json":
153+
getValue = func(value []byte) (any, error) {
154+
return base64.StdEncoding.EncodeToString(value), nil
147155
}
148-
case "application/json", "":
149-
for _, r := range b.Records {
150-
key := string(kafka.Read(r.Key))
156+
case ct.Key() == "application/json", ct.IsAny():
157+
getValue = func(value []byte) (any, error) {
151158
var val any
152-
err := json.Unmarshal(kafka.Read(r.Value), &val)
159+
err := json.Unmarshal(value, &val)
153160
if err != nil {
154161
return nil, fmt.Errorf("parse record value as JSON failed: %v", err)
155162
}
156-
157-
records = append(records, Record{
158-
Key: key,
159-
Value: val,
160-
})
163+
return val, nil
161164
}
165+
162166
default:
163167
return nil, fmt.Errorf("unknown content type: %v", ct)
164168
}
165169

170+
for _, r := range b.Records {
171+
key := string(kafka.Read(r.Key))
172+
val, err := getValue(kafka.Read(r.Value))
173+
if err != nil {
174+
return nil, err
175+
}
176+
177+
rec := Record{
178+
Offset: r.Offset,
179+
Partition: p.Index,
180+
Key: key,
181+
Value: val,
182+
}
183+
184+
for _, h := range r.Headers {
185+
rec.Headers = append(rec.Headers, RecordHeader{
186+
Name: h.Key,
187+
Value: string(h.Value),
188+
})
189+
}
190+
191+
records = append(records, rec)
192+
}
193+
166194
return records, nil
167195
}
168196

@@ -198,19 +226,24 @@ func (c *Client) parse(v any, ct *media.ContentType) ([]byte, error) {
198226
return vt, nil
199227
case string:
200228
return []byte(vt), nil
229+
default:
230+
return json.Marshal(v)
201231
}
202232
}
203-
return nil, fmt.Errorf("unknown content type: %v", ct)
204233
}
205234

206235
func (c *Client) parseKey(v any) ([]byte, error) {
236+
if v == nil {
237+
return nil, nil
238+
}
207239
switch vt := v.(type) {
208240
case []byte:
209241
return vt, nil
210242
case string:
211243
return []byte(vt), nil
244+
default:
245+
return json.Marshal(v)
212246
}
213-
return nil, fmt.Errorf("key not supported: %v", v)
214247
}
215248

216249
func (r *Record) UnmarshalJSON(b []byte) error {

0 commit comments

Comments
 (0)