Skip to content
Merged

V0.11 #429

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
605ec3d
improve resolving references ($id, $anchor, $ref, $defs)
marle3003 Jan 7, 2025
204e709
refactor json schema ref
marle3003 Jan 8, 2025
df86906
refactor json $anchor using scope
marle3003 Jan 8, 2025
21d5d2c
Bump golang.org/x/net from 0.33.0 to 0.34.0
dependabot[bot] Jan 10, 2025
91e2470
Bump @rushstack/eslint-patch from 1.10.4 to 1.10.5 in /webui
dependabot[bot] Jan 10, 2025
3130176
Merge pull request #425 from marle3003/dependabot/go_modules/v0.11/go…
github-actions[bot] Jan 10, 2025
34c123d
add support JSON schema dynamicRef and dynamicAnchor
marle3003 Jan 10, 2025
728e321
Merge remote-tracking branch 'origin/v0.11' into v0.11
marle3003 Jan 10, 2025
10a3c04
Merge branch 'v0.11' into dependabot/npm_and_yarn/webui/v0.11/rushsta…
marle3003 Jan 10, 2025
853ceef
Merge pull request #428 from marle3003/dependabot/npm_and_yarn/webui/…
github-actions[bot] Jan 10, 2025
45063a6
Bump typescript from 5.7.2 to 5.7.3 in /webui
dependabot[bot] Jan 10, 2025
088bb7b
Merge pull request #426 from marle3003/dependabot/npm_and_yarn/webui/…
github-actions[bot] Jan 10, 2025
fb1875c
Bump ace-builds from 1.37.1 to 1.37.4 in /webui
dependabot[bot] Jan 10, 2025
54d1d07
Merge pull request #427 from marle3003/dependabot/npm_and_yarn/webui/…
github-actions[bot] Jan 10, 2025
9427ac1
refactor json $anchor using scope
marle3003 Jan 10, 2025
8ea78a0
add test for default response
marle3003 Jan 10, 2025
ed01315
add LDIF support
marle3003 Jan 12, 2025
82f3ef7
fix http file server for jpg image
marle3003 Jan 12, 2025
79aa4f8
fix reading LDIF files on Windows
marle3003 Jan 13, 2025
ceffcb1
fix paging LDAP does not work with a map
marle3003 Jan 13, 2025
eddd73d
update docs
marle3003 Jan 13, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,443 changes: 945 additions & 498 deletions .idea/workspace.xml

Large diffs are not rendered by default.

46 changes: 31 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,28 +36,39 @@ Its core feature are:
- **Multiple Provider support**: File, HTTP, GIT, NPM to gather configurations and scripts.
- **Dashboard** to see what's going on.

 
<p align="center">
<a href="https://www.buymeacoffee.com/mokapi" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Buy Me A Coffee" style="height: 41px !important;width: 174px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" ></a>
<p align="center">

## Example

<img src="webui/public/everythingcode.png" alt="Mokapi Web UI" title="Mokapi Web UI" />
## Usage

## Web UI
Windows
```shell
chcco install mokapi
mokapi --providers-http-url https://petstore31.swagger.io/api/v31/openapi.json
```

<img src="webui.png" alt="Mokapi Web UI" title="Mokapi Web UI" />
MacOS
```shell
brew tap marle3003/tap
brew install mokapi
mokapi --providers-http-url https://petstore31.swagger.io/api/v31/openapi.json
```

## Usage
Docker
```shell
docker run --env 'MOKAPI_Providers_Http_URL'='https://petstore31.swagger.io/api/v31/openapi.json' -p 80:80 -p 8080:8080 mokapi/mokapi:latest
```

Run a request
```shell
docker run --env 'MOKAPI_Services_Swagger-Petstore_Config_Url'='https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.0/petstore.yaml' \
--env 'MOKAPI_Services_Swagger-Petstore_Http_Servers[0]_Url'='http://:80' \
-p 80:80 -p 8080:8080 \
mokapi/mokapi:latest
curl http://localhost/api/v31/pet/2 -H 'Accept: application/json'
```

## Example

<img src="webui/public/control-mock-api-everything.png" alt="Mokapi Web UI" title="Mokapi Web UI" />

## Dashboard

<img src="webui.png" alt="Mokapi Web UI" title="Mokapi Web UI" />

## Documentation

- [Get Started](https://mokapi.io/docs/guides/get-started/welcome)
Expand All @@ -68,3 +79,8 @@ docker run --env 'MOKAPI_Services_Swagger-Petstore_Config_Url'='https://raw.gith
- [Javascript API](https://mokapi.io/docs/javascript-api)
- [Examples & Tutorials](https://mokapi.io/docs/examples)
- [Blogs](https://mokapi.io/docs/blogs)

&nbsp;
<p align="center">
<a href="https://www.buymeacoffee.com/mokapi" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Buy Me A Coffee" style="height: 41px !important;width: 174px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" ></a>
<p align="center">
12 changes: 11 additions & 1 deletion api/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
if isAsset(r.URL.Path) {
r.URL.Path = "/assets/" + filepath.Base(r.URL.Path)
} else if filepath.Ext(r.URL.Path) == ".svg" || filepath.Ext(r.URL.Path) == ".png" {
} else if isImage(r.URL.Path) {
// don't change url
} else {
if len(h.path) > 0 || len(h.base) > 0 {
Expand Down Expand Up @@ -213,3 +213,13 @@ func writeJsonBody(w http.ResponseWriter, i interface{}) {
func isAsset(path string) bool {
return strings.Contains(path, "/assets/")
}

func isImage(path string) bool {
str := filepath.Ext(path)
switch str {
case ".jpg", ".jpeg", ".png", ".svg":
return true
default:
return false
}
}
48 changes: 13 additions & 35 deletions api/handler_fileserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,6 @@ func TestHandler_FileServer(t *testing.T) {
try.HasHeader("Content-Type", "application/json"),
try.HasBody(`{"version":"","buildTime":""}`))
},
fileServer: http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
if request.URL.Path != "/index.html" {
writer.WriteHeader(404)
}
}),
},
{
name: "request web app",
Expand All @@ -55,11 +50,6 @@ func TestHandler_FileServer(t *testing.T) {
h,
try.HasStatusCode(200))
},
fileServer: http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
if request.URL.Path != "/index.html" {
writer.WriteHeader(404)
}
}),
},
{
name: "request web app",
Expand All @@ -73,11 +63,6 @@ func TestHandler_FileServer(t *testing.T) {
h,
try.HasStatusCode(200), try.BodyContains(`<base href="/mokapi/dashboard/" />`))
},
fileServer: http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
if request.URL.Path != "/index.html" {
writer.WriteHeader(404)
}
}),
},
{
name: "request asset",
Expand All @@ -97,11 +82,6 @@ func TestHandler_FileServer(t *testing.T) {
h,
try.HasStatusCode(200))
},
fileServer: http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
if request.URL.Path != "/assets/index.js" {
writer.WriteHeader(404)
}
}),
},
{
name: "request svg",
Expand All @@ -115,11 +95,6 @@ func TestHandler_FileServer(t *testing.T) {
h,
try.HasStatusCode(200))
},
fileServer: http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
if request.URL.Path != "/logo.svg" {
writer.WriteHeader(404)
}
}),
},
{
name: "request png",
Expand All @@ -133,11 +108,19 @@ func TestHandler_FileServer(t *testing.T) {
h,
try.HasStatusCode(200))
},
fileServer: http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
if request.URL.Path != "/mail.png" {
writer.WriteHeader(404)
}
}),
},
{
name: "request jpg",
config: static.Api{Path: "/mokapi/dashboard", Dashboard: true},
fn: func(t *testing.T, h http.Handler) {
try.Handler(t,
http.MethodGet,
"http://foo.api/mokapi/dashboard/petstore-rest-api-endpoints.jpg",
nil,
"",
h,
try.HasStatusCode(200))
},
},
{
name: "url rewrite (proxy)",
Expand All @@ -152,11 +135,6 @@ func TestHandler_FileServer(t *testing.T) {
try.HasStatusCode(200),
try.BodyContains(`<base href="/foo/mokapi/dashboard/" />`))
},
fileServer: http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
if request.URL.Path != "/index.html" {
writer.WriteHeader(404)
}
}),
},
}

Expand Down
2 changes: 1 addition & 1 deletion api/handler_kafka_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
schematest2 "mokapi/providers/openapi/schema/schematest"
"mokapi/runtime"
"mokapi/runtime/monitor"
"mokapi/schema/json/schematest"
"mokapi/schema/json/schema/schematest"
"mokapi/try"
"net/http"
"testing"
Expand Down
8 changes: 4 additions & 4 deletions api/handler_schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ func (h *handler) getExampleData(w http.ResponseWriter, r *http.Request) {
case *schema.Ref:
data, err = getRandomByOpenApi(re.Name, s, ct)
case *avro.Schema:
data, err = getRandomByJson(re.Name, &jsonSchema.Ref{Value: s.Convert()}, ct)
data, err = getRandomByJson(re.Name, s.Convert(), ct)
default:
data, err = getRandomByJson(re.Name, s.(*jsonSchema.Ref), ct)
data, err = getRandomByJson(re.Name, s.(*jsonSchema.Schema), ct)
}

if err != nil {
Expand All @@ -103,7 +103,7 @@ func getRandomByOpenApi(name string, r *schema.Ref, ct media.ContentType) ([]byt
return r.Marshal(data, ct)
}

func getRandomByJson(name string, r *jsonSchema.Ref, ct media.ContentType) ([]byte, error) {
func getRandomByJson(name string, r *jsonSchema.Schema, ct media.ContentType) ([]byte, error) {
data, err := generator.New(&generator.Request{
Path: generator.Path{
&generator.PathElement{Name: name, Schema: r},
Expand Down Expand Up @@ -215,7 +215,7 @@ func unmarshal(raw json.RawMessage, format string) (interface{}, error) {
err := json.Unmarshal(raw, &a)
return a, err
default:
var r *jsonSchema.Ref
var r *jsonSchema.Schema
err := json.Unmarshal(raw, &r)
return r, err
}
Expand Down
21 changes: 10 additions & 11 deletions api/handler_schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"mokapi/runtime"
"mokapi/runtime/monitor"
avro "mokapi/schema/avro/schema"
"mokapi/schema/json/ref"
jsonSchema "mokapi/schema/json/schema"
"mokapi/try"
"net/http"
Expand Down Expand Up @@ -260,8 +259,8 @@ func TestSchemaInfo_UnmarshalJSON(t *testing.T) {
test: func(t *testing.T, s *schemaInfo, err error) {
require.NoError(t, err)
require.NotNil(t, s.Schema)
require.IsType(t, &jsonSchema.Ref{}, s.Schema)
require.Equal(t, "object", s.Schema.(*jsonSchema.Ref).Value.Type[0])
require.IsType(t, &jsonSchema.Schema{}, s.Schema)
require.Equal(t, "object", s.Schema.(*jsonSchema.Schema).Type[0])
},
},
{
Expand All @@ -271,8 +270,8 @@ func TestSchemaInfo_UnmarshalJSON(t *testing.T) {
require.NoError(t, err)
require.Equal(t, "foo", s.Format)
require.NotNil(t, s.Schema)
require.IsType(t, &jsonSchema.Ref{}, s.Schema)
require.Equal(t, "object", s.Schema.(*jsonSchema.Ref).Value.Type[0])
require.IsType(t, &jsonSchema.Schema{}, s.Schema)
require.Equal(t, "object", s.Schema.(*jsonSchema.Schema).Type[0])
},
},
}
Expand Down Expand Up @@ -314,21 +313,21 @@ func TestSchemaInfo_MarshalJSON(t *testing.T) {
},
{
name: "json schema only ref",
s: &schemaInfo{Schema: &jsonSchema.Ref{Reference: ref.Reference{Ref: "foo/bar"}}},
s: &schemaInfo{Schema: &jsonSchema.Schema{Ref: "foo/bar"}},
test: func(t *testing.T, s string, err error) {
require.NoError(t, err)
require.Equal(t, `{"schema":{"ref":"foo/bar"}}`, s)
require.Equal(t, `{"schema":{"$ref":"foo/bar"}}`, s)
},
},
{
name: "json schema ref and value",
s: &schemaInfo{Schema: &jsonSchema.Ref{
Reference: ref.Reference{Ref: "foo/bar"},
Value: &jsonSchema.Schema{Type: jsonSchema.Types{"string"}},
s: &schemaInfo{Schema: &jsonSchema.Schema{
Ref: "foo/bar",
Type: jsonSchema.Types{"string"},
}},
test: func(t *testing.T, s string, err error) {
require.NoError(t, err)
require.Equal(t, `{"schema":{"ref":"foo/bar","type":"string"}}`, s)
require.Equal(t, `{"schema":{"$ref":"foo/bar","type":"string"}}`, s)
},
},
{
Expand Down
4 changes: 2 additions & 2 deletions api/handler_schema_validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func (h *handler) validate(w http.ResponseWriter, r *http.Request) {
case *schema.Ref:
err = parseByOpenApi([]byte(valReq.Data), s, ct)
default:
err = parseByJson([]byte(valReq.Data), s.(*jsonSchema.Ref), ct)
err = parseByJson([]byte(valReq.Data), s.(*jsonSchema.Schema), ct)
}

if err != nil {
Expand Down Expand Up @@ -94,7 +94,7 @@ func parseByOpenApi(data []byte, s *schema.Ref, ct media.ContentType) error {
return err
}

func parseByJson(data []byte, s *jsonSchema.Ref, ct media.ContentType) error {
func parseByJson(data []byte, s *jsonSchema.Schema, ct media.ContentType) error {
v, err := encoding.Decode(data, encoding.WithContentType(ct))
if err != nil {
return err
Expand Down
2 changes: 1 addition & 1 deletion config/dynamic/asyncApi/asyncapitest/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func WithSchemas(name string, s *schema.Schema) ConfigOptions {
c.Components.Schemas = map[string]*asyncapi3.SchemaRef{}
}
c.Components.Schemas[name] = &asyncapi3.SchemaRef{
Value: &asyncapi3.MultiSchemaFormat{Schema: &schema.Ref{Value: s}},
Value: &asyncapi3.MultiSchemaFormat{Schema: s},
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions config/dynamic/asyncApi/asyncapitest/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func NewMessage(opts ...MessageOptions) *asyncApi.Message {

func WithPayload(s *schema.Schema) MessageOptions {
return func(m *asyncApi.Message) {
m.Payload = &asyncapi3.SchemaRef{Value: &asyncapi3.MultiSchemaFormat{Schema: &schema.Ref{Value: s}}}
m.Payload = &asyncapi3.SchemaRef{Value: &asyncapi3.MultiSchemaFormat{Schema: s}}
}
}

Expand All @@ -30,7 +30,7 @@ func WithContentType(s string) MessageOptions {

func WithKey(s *schema.Schema) MessageOptions {
return func(m *asyncApi.Message) {
m.Bindings.Kafka.Key = &asyncapi3.SchemaRef{Value: &asyncapi3.MultiSchemaFormat{Schema: &schema.Ref{Value: s}}}
m.Bindings.Kafka.Key = &asyncapi3.SchemaRef{Value: &asyncapi3.MultiSchemaFormat{Schema: s}}
}
}

Expand Down
12 changes: 6 additions & 6 deletions config/dynamic/asyncApi/convert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ func TestConfig_Convert(t *testing.T) {

// traits
require.Len(t, msg.Traits, 1)
require.IsType(t, &schema.Ref{}, msg.Traits[0].Value.Headers.Value.Schema)
headers := msg.Traits[0].Value.Headers.Value.Schema.(*schema.Ref)
require.Equal(t, float64(100), *headers.Value.Properties.Get("my-app-header").Value.Maximum)
require.IsType(t, &schema.Schema{}, msg.Traits[0].Value.Headers.Value.Schema)
headers := msg.Traits[0].Value.Headers.Value.Schema.(*schema.Schema)
require.Equal(t, float64(100), *headers.Properties.Get("my-app-header").Maximum)

// payload
payload := msg.Payload.Value
require.IsType(t, &schema.Ref{}, payload.Schema)
s := payload.Schema.(*schema.Ref)
require.Equal(t, "object", s.Value.Type[0])
require.IsType(t, &schema.Schema{}, payload.Schema)
s := payload.Schema.(*schema.Schema)
require.Equal(t, "object", s.Type[0])
}
11 changes: 5 additions & 6 deletions config/dynamic/asyncApi/parsing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"mokapi/config/dynamic"
"mokapi/config/dynamic/asyncApi"
"mokapi/providers/asyncapi3"
"mokapi/schema/json/ref"
"mokapi/schema/json/schema"
"net/url"
"testing"
Expand Down Expand Up @@ -396,17 +395,17 @@ func TestSchema(t *testing.T) {
t.Run("reference inside", func(t *testing.T) {
target := &schema.Schema{}
schemas := map[string]*asyncapi3.SchemaRef{}
schemas["foo"] = &asyncapi3.SchemaRef{Value: &asyncapi3.MultiSchemaFormat{Schema: &schema.Ref{Value: target}}}
schemas["foo"] = &asyncapi3.SchemaRef{Value: &asyncapi3.MultiSchemaFormat{Schema: target}}
config.Components = &asyncApi.Components{Schemas: schemas}
message.Payload = &asyncapi3.SchemaRef{Reference: dynamic.Reference{Ref: "#/components/schemas/foo"}}
reader := &testReader{readFunc: func(cfg *dynamic.Config) error { return nil }}

err := config.Parse(&dynamic.Config{Info: dynamic.ConfigInfo{Url: &url.URL{}}, Data: config}, reader)
require.NoError(t, err)
require.Equal(t, target, message.Payload.Value.Schema.(*schema.Ref).Value)
require.Equal(t, target, message.Payload.Value.Schema.(*schema.Schema))
})
t.Run("file reference direct", func(t *testing.T) {
target := &schema.Ref{Value: &schema.Schema{}}
target := &schema.Schema{}
message.Payload = &asyncapi3.SchemaRef{Reference: dynamic.Reference{Ref: "foo.yml"}}
reader := &testReader{readFunc: func(cfg *dynamic.Config) error {
cfg.Data = target
Expand All @@ -419,7 +418,7 @@ func TestSchema(t *testing.T) {
})
t.Run("modify file reference direct", func(t *testing.T) {
target := &schema.Schema{}
message.Payload = &asyncapi3.SchemaRef{Value: &asyncapi3.MultiSchemaFormat{Schema: &schema.Ref{Reference: ref.Reference{Ref: "foo.yml"}}}}
message.Payload = &asyncapi3.SchemaRef{Value: &asyncapi3.MultiSchemaFormat{Schema: &schema.Schema{Ref: "foo.yml"}}}
var fooConfig *dynamic.Config
reader := &testReader{readFunc: func(file *dynamic.Config) error {
file.Data = &schema.Schema{}
Expand All @@ -435,6 +434,6 @@ func TestSchema(t *testing.T) {
err = fooConfig.Data.(dynamic.Parser).Parse(fooConfig, reader)

require.NoError(t, err)
require.Equal(t, target, message.Payload.Value.Schema.(*schema.Ref).Value)
require.Equal(t, target, message.Payload.Value.Schema.(*schema.Schema))
})
}
Loading
Loading