Giter Site home page Giter Site logo

moclojer / moclojer Goto Github PK

View Code? Open in Web Editor NEW
89.0 2.0 9.0 601 KB

Simple and efficient HTTP mock server with specification in yaml, edn or OpenAPI

Home Page: https://docs.moclojer.com

License: MIT License

Clojure 90.62% Dockerfile 3.51% Shell 5.86%
mock clojure yaml mock-server api api-rest api-mock api-mocker openapi openapi3

moclojer's Introduction

moclojer

linter tests

moclojer -  Simple and efficient HTTP mock server with easy spec | Product Hunt

Simple and efficient HTTP mock server with specification written in yaml, edn or OpenAPI.

πŸ’Ύ Download the .jar file with the latest version of moclojer to test on your computer here.

πŸ“– See the complete documentation for moclojer here, if you want to contribute (or complement) the documentation, it is here.

YAML example

# This mock register route: GET /hello/:username
- endpoint:
    # Note: the method could be omitted because GET is the default
    method: GET
    path: /hello/:username
    response:
      # Note: the status could be omitted because 200 is the default
      status: 200
      headers:
        Content-Type: application/json
      # Note: the body will receive the value passed in the url using the
      # :username placeholder
      body: >
        {
          "hello": "{{path-params.username}}!"
        }

docker

  • image: ghcr.io/moclojer/moclojer:latest
  • port (default): 8000, if you want to change the port set the environment variable PORT
docker run -it \
  -p 8000:8000 -v $(pwd)/moclojer.yml:/app/moclojer.yml \
  ghcr.io/moclojer/moclojer:latest

we Two available versions:

  • dev: main branch docker image
  • latest: latest stable version image

manual installation

We distribute via the .jar file, you need to have Java installed on your operating system.

bash < <(curl -s https://raw.githubusercontent.com/moclojer/moclojer/main/install.sh)

If you are using Linux you maybe need sudo.

CLI Usage

  • clj -M:run [OPTIONS]
  • java -jar moclojer.jar [OPTIONS]
  • moclojer_Linux [OPTIONS]

Options

parameter description
-c, --config Config path or the CONFIG environment variable. [default: ~/.config/moclojer.yml]
-m, --mocks OpenAPI v3 mocks path or the MOCKS environment variable.
-f, --format Output and logging format. Either println or json.
-h, --help Show help information
-v, --version Show version information

sentry: set environment var SENTRY_DSN (sentry doc), automatic send backtrace to <sentry.io>

Config uses XDG_CONFIG_HOME to fetch the default moclojer configuration file, if you want to set a different directory you must use the -c or environment variable CONFIG

πŸ’» dev environment

moclojer is written in Clojure, to run the commands below we assume you have clojure installed on your operating system.

run:

clj -M:run

test:

clj -M:test

if you want to run a specific test: clj -M:test -n com.moclojer.external-body.excel-test

moclojer.jar generate:

clj -A:dev -M --report stderr -m com.moclojer.build

framework integrations

We distribute the library via Clojars.

Clojure CLI/deps.edn

com.moclojer/moclojer {:mvn/version "0.3.1"}

Leiningen/Boot

[com.moclojer/moclojer "0.3.1"]

git in deps.edn

{:deps
 {com.moclojer/moclojer {:git/url "https://github.com/moclojer/moclojer.git"
                         :git/tag "v0.3.1"
                         :git/sha "c4ca0f2cfcfbe47de6eb0c601b26106190e20793"}}}

example of use

(ns my-app.core
  (:require [com.moclojer.adapters :as adapters]
            [com.moclojer.server :as server]))

(def *router
  "create a router from a config map"
  (adapters/generate-routes
   [{:endpoint
     {:method "GET"
      :path "/example"
      :response {:status 200
                 :headers {:Content-Type "application/json"}
                 :body {:id 123}}}}]))

(defn -main
  "start the server"
  [& args]
  (server/start-server! *router))

moclojer's People

Contributors

avelino avatar dependabot[bot] avatar matheusfrancisco avatar rafaeldelboni avatar rodweb avatar souenzzo avatar vmesel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

moclojer's Issues

postman collection spec support

ref: https://schema.postman.com/collection/json/v2.1.0/draft-07/docs/index.html

{
  "info": {
    "_postman_id": "5r7ccf61-22db-4670-95c4-0d4d51ad2193",
    "name": "hello-api",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "item": [
    {
      "name": "/helloworld/foo",
      "request": {
        "method": "GET",
        "header": [
          
        ],
        "body": {
          "mode": "raw",
          "raw": ""
        },
        "url": {
          "raw": "{{url}}/helloworld/foo",
          "host": [
            "{{url}}"
          ],
          "path": [
            "helloworld",
            "foo"
          ]
        }
      },
      "response": [
        
      ]
    },
    {
      "name": "/list",
      "request": {
        "method": "GET",
        "header": [
          
        ],
        "body": {
          "mode": "raw",
          "raw": ""
        },
        "url": {
          "raw": "{{url}}/list",
          "host": [
            "{{url}}"
          ],
          "path": [
            "list"
          ]
        }
      },
      "response": [
        
      ]
    },
    {
      "name": "/add",
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "Content-Type",
            "name": "Content-Type",
            "value": "application/json",
            "type": "text"
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{\n\t\"route\": \"/foo/{id}\",\n\t\"methods\": [\"get\"],\n\t\"responses\": [\n\t\t{\n\t\t\t\"uri\": \"/foo/1\",\n\t\t\t\"method\": \"get\",\n\t\t\t\"statusCode\": 200,\n\t\t\t\"headers\": {\"Content-Type\": \"application/json\"},\n\t\t\t\"body\": {\n\t\t\t\t\"foo\": \"bar\"\n\t\t\t}\n\t\t}\t\n\t]\n}"
        },
        "url": {
          "raw": "{{url}}/add",
          "host": [
            "{{url}}"
          ],
          "path": [
            "add"
          ]
        }
      },
      "response": [
        
      ]
    }
  ]
}

Reduce maintenance complexity caused by the `OpenAPI` specification

Discussed in #111

Originally posted by avelino May 5, 2023
When I look at the moclojer code I feel that we are building it wrong, it is hard to understand (especially the openapi package).

We need to make the code simpler and more readable, the way it now increases the barrier for new contributors to get in - if I (who started the project) having trouble understanding it, imagine who is just getting here

solution

Moclojer converts the moclojer specification (yaml and edn) to openapi format and the http server is built on top of the openapi specification - that's how it works today.

The proposal would be that moclojer supports "only" the moclojer spec and who wants to use openapi we do the conversion from openapi to moclojer spec.

This way, the moclojer spec will evolve in parallel with openapi (to run on moclojer).

Fail to exit the docker container without stopping the container

Search first

  • I searched and no similar issues were found

What Happened?

You cannot exit the docker container with control c command.

Reproduce the Bug

  1. Run:
docker run -it \
  -p 8000:8000 -v $(pwd)/moclojer.yml:/app/moclojer.yml \
  ghcr.io/moclojer/moclojer:dev
  1. Try to Control-C to exit the process inside the container

moclojer config

Not applicable, we can use the default.

Expected Behavior

Exit the container

Version and environment information

moclojer version: 0.2 (commit: 0bfcda8)
os: MacOS Ventura 13.0.1 (22A400)

Are you willing to submit a PR? If you know how to fix the bug.

  • I'm willing to submit a PR (Thank you!)

Running inside docker in http server is not publicly exposed

by running moclojer in the docker image the http server is not outside docker, only inside docker

docker-compose.yml:

version: '3'

services:
  moclojer:
    image: ghcr.io/moclojer/moclojer:dev
    platform: linux/amd64
    ports:
      - 8000:8000
    volumes:
      - ./moclojer.yml:/app/moclojer.yml

moclojer.yml:

# This mock register route: GET /hello/:username
- endpoint:
    # Note: the method could be omitted because GET is the default
    method: GET
    path: /hello/:username
    response:
      # Note: the status could be omitted because 200 is the default
      status: 200
      headers:
        Content-Type: application/json
      # Note: the body will receive the value passed in the url using the
      # :username placeholder
      body: >
        {
          "hello": "{{path-params.username}}!"
        }

report by @wesleywillians

openapi: specified endpoints are not working

run:

$ CONFIG=simple-api.json MOCKS=mocks.json clj -X:run
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/Users/avelino/.m2/repository/org/slf4j/slf4j-simple/1.7.5/slf4j-simple-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/Users/avelino/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.SimpleLoggerFactory]
[main] INFO org.eclipse.jetty.util.log - Logging initialized @2806ms to org.eclipse.jetty.util.log.Slf4jLog
(-> moclojer :start-server :version "0.1")
[main] INFO moclojer.router - {:mode "openapi", :line 14}
[async-thread-macro-1] INFO moclojer.router - {:mode "openapi", :line 14}
[main] INFO org.eclipse.jetty.server.Server - jetty-9.4.44.v20210927; built: 2021-09-27T23:02:44.612Z; git: 8da83308eeca865e495e53ef315a249d63ba9332; jvm 17.0.2+0
[main] INFO org.eclipse.jetty.server.handler.ContextHandler - Started o.e.j.s.ServletContextHandler@3a4fccc7{/,null,AVAILABLE}
[main] INFO org.eclipse.jetty.server.AbstractConnector - Started ServerConnector@421d9b57{HTTP/1.1, (http/1.1, h2c)}{localhost:8000}
[main] INFO org.eclipse.jetty.server.Server - Started @3220ms
[qtp106092746-24] INFO io.pedestal.http - {:msg "GET /hello", :line 80}
[qtp106092746-18] INFO io.pedestal.http - {:msg "GET /hello", :line 80}

request via curl and browser:

$ curl -X GET -I http://127.0.0.1:8000/hello 
HTTP/1.1 501 Not Implemented
Date: Wed, 30 Mar 2022 10:32:43 GMT
Strict-Transport-Security: max-age=31536000; includeSubdomains
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-Download-Options: noopen
X-Permitted-Cross-Domain-Policies: none
Content-Security-Policy: object-src 'none'; script-src 'unsafe-inline' 'unsafe-eval' 'strict-dynamic' https: http:;
Transfer-Encoding: chunked

Screen Shot 2022-03-30 at 07 30 29

configuration files

simple-api.json:

{
  "openapi": "3.0.0",
  "info": {
    "title": "Sample API",
    "version": "1.0"
  },
  "paths": {
    "/hello": {
      "get": {
        "operationId": "greet",
        "responses": {
          "200": {
            "description": "A JSON array of user names",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "hello"
                  ],
                  "properties": {
                    "hello": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

mocks.json:

{
  "myFirstRoute": {
    "body": "{\"hello\": \"{{path-params.username}}!\"}",
    "headers": {
      "Content-Type": "application/json"
    },
    "status": 200
  }
}

GraalVM: Exception in thread "main" java.lang.ClassNotFoundException: org.yaml.snakeyaml.Yaml

The distribution of the moclojer will be done via a self-contained binary file (without depending on Java installed on the machine), for this we use GraalVM to generate the binary using native-image.

The yaml package is giving error:

❯ moclojer (main) ✘ CONFIG=moclojer.yml ./moclojer 
"(-> moclojer :start-server)"
Exception in thread "main" java.lang.ClassNotFoundException: org.yaml.snakeyaml.Yaml
        at java.lang.Class.forName(DynamicHub.java:1338)
        at clojure.lang.RT.classForName(RT.java:2212)
        at clojure.lang.RT.classForName(RT.java:2221)
        at yaml.reader$parse_string.invokeStatic(reader.clj:67)
        at yaml.reader$parse_string.doInvoke(reader.clj:53)
        at clojure.lang.RestFn.invoke(RestFn.java:439)
        at yaml.core$from_file.invokeStatic(core.clj:25)
        at yaml.core$from_file.invoke(core.clj:19)
        at yaml.core$from_file.invokeStatic(core.clj:22)
        at yaml.core$from_file.invoke(core.clj:19)
        at moclojer.core$_main.invokeStatic(core.clj:47)
        at moclojer.core$_main.doInvoke(core.clj:41)
        at clojure.lang.RestFn.invoke(RestFn.java:397)
        at clojure.lang.AFn.applyToHelper(AFn.java:152)
        at clojure.lang.RestFn.applyTo(RestFn.java:132)
        at moclojer.core.main(Unknown Source)

ref: How to build a native binary for your Clojure projects with GraalVM

native-image command:

native-image --report-unsupported-elements-at-runtime \
    -jar ./moclojer.jar \
    -H:Name=./moclojer \
    -H:Name=moclojer \
    -H:+ReportExceptionStackTraces \
    --initialize-at-build-time \
    --verbose \
    --no-fallback \
    --no-server \
    --allow-incomplete-classpath \
    -H:ReflectionConfigurationFiles=reflect-config.json \
    moclojer.core

ref: binary distribution not .jar - graalvm support

endpoint to file upload

- endpoint:
    method: POST
    path: /file-upload
    store: upload-filesystem
    interceptor: multipart
    response:
      status: 200
      headers:
        Content-Type: application/json
      body: >
        {
          "url": "https:/..."
        }

There are two variables that we need to control in this type of endpoint: store (where the file will be persisted) and interceptor (will it receive the file or in base64 format).

example:

store: upload-filesystem
interceptor: multipart

store:

  • upload-filesystem
  • upload-s3

interceptor's:

  • file-multipart
  • file-base64

ToDo:

  • moclojer spec
  • OpenAPI

babashka cli: clojure.lang.Named.getNamespace() becuase x is null

Search first

  • I searched and no similar issues were found

What Happened?

when running the clj -M:run command it gives a namespace error

clojure.lang.Named.getNamespace() becuase x is null

Reproduce the Bug

  1. run clj -M:run

moclojer config

Expected Behavior

No response

Version and environment information

moclojer version: branch main

Are you willing to submit a PR? If you know how to fix the bug.

  • I'm willing to submit a PR (Thank you!)

-c and -m flags are not working to define the config and mock files

Search first

  • I searched and no similar issues were found

What Happened?

While trying to use the -c and -m specified on README.md, you will not be able to launch the Moclojer software with mocks. It won't recognize the config file.

Reproduce the Bug

Use this docker:

FROM ghcr.io/moclojer/moclojer:latest

COPY ./mock_files/ /app/mock_files/

ENTRYPOINT ["/app/moclojer", "-c", "/app/mock_files/petstore.yaml", "-m", "/app/mock_files/pet-mocks.yml"]

With the files from a certain mock specification

moclojer config

N/A

Expected Behavior

It should be able to load the config not only from environment variables, but from the flags on the command.

Version and environment information

moclojer 0.2 (0bfcda8)
macOS Ventura 13.0.1 (22A400)

Are you willing to submit a PR? If you know how to fix the bug.

  • I'm willing to submit a PR (Thank you!)

create server with vector list base

Discussed in #170 (API mocking for "JavaScript")

Starting to support using moclojer as a framework (creating software/api in clojure using moclojer as a base)

doc/body: how the template works

write template documentation, specifying how to receive:

  • url parameter
  • query string parameter
  • ... anything that supports data

release process does not work

Search first

  • I searched and no similar issues were found

What Happened?

ref: https://github.com/moclojer/moclojer/actions/runs/4791922662/jobs/8522968317

tar: moclojer_target.tar.bz2: Cannot read: Is a directory
tar: At beginning of tape, quitting now
tar: Error is not recoverable: exiting now
Error: Process completed with exit code 2.

Reproduce the Bug

  1. create git tag with v prefix
  2. send tag to remote repository (github)

moclojer config

does not apply, it is a problem in the github action

Expected Behavior

No response

Version and environment information

does not apply, it is a problem in the github action

Are you willing to submit a PR? If you know how to fix the bug.

  • I'm willing to submit a PR (Thank you!)

Build/make dynamic pedestal router

this function is too complex, we need to rewrite simplifying the logic and splitting the implementation into smaller functions

(defn generate-pedestal-route
"generate a pedestal route from an openapi spec"
;; TODO: this function is too complex, we need to rewrite simplifying the
;; logic and splitting the implementation into smaller functions
[config]
(sequence (mapcat
(fn [[path path-item]]
(sequence
(mapcat (fn [[method operation]]
(when (contains? path-item->operation method)
(route/expand-routes
#{;; use the `host` declared in the configuration file
{:host (get operation "host" nil)}
[(openapi-path->pedestal-path path)
(keyword method)
(into []
cat
[[{:name ::add-operation
:enter (fn [ctx]
(assoc ctx
::path path
::method method
::openapi config
::path-item path-item
::operation operation))}
(body-params/body-params)]
(when (get-in operation ["requestBody" "content" "multipart/form-data"])
[(middlewares/multipart-params)])
(when-let [dir (get-in operation ["x-mockResponse" "store"])]
(.mkdirs (io/file dir))
[{:name ::save-all-multipart
:enter (fn [ctx]
(locking dir
(let [now-str (str (Instant/now))
temp-dir (loop [n 19]
(let [d (io/file dir (str "req"
(string/replace
(subs now-str
0 n)
#"[^0-9T-]"
"_")))]
(if (.exists d)
(recur (inc n))
(doto d
(.mkdirs)))))]
(doseq [[k v] (-> ctx :request :multipart-params)
:let [target (io/file temp-dir k)]]
(if (:tempfile v)
(io/copy (:tempfile v) target)
(spit target v)))))
ctx)}])
[generate-response]])
:route-name (keyword
(string/join "-" [(get operation "host" "nil")
(or (get operation "operationId")
(json-path->pointer [path method]))]))]}))))
(resolve-ref config path-item))))
(get config "paths")))

JWT authentication

Support for "closed" endpoint by authentication

  • validate http header if token is valid Authorization: Bearer <token>

Cross-Origin Resource Sharing (CORS) does not work

Search first

  • I searched and no similar issues were found

What Happened?

I was using moclojer with a localhost frontend and when my frontend hit the moclojer url from my specs I got a cross error,

image

to fix this we should add ::http/allowed-origins in the image bellow
image

I'm running this locally from branch main to develop my frontend, but not sure if we will always allowed localhost even when we build the binary or in our sass application.

Reproduce the Bug

do a request for moclojer with a frontend running on localhost:8000

moclojer config

- endpoint:
    # Note: the method could be omitted because GET is the default
    method: POST
    path: /login/auth
    response:
      # Note: the status could be omitted because 200 is the default
      status: 201
      headers:
        Content-Type: application/json
      # Note: the body will receive the value passed in the url using the
      # :username placeholder
      body: >
        {
           "user": {"email": "[email protected]", "id": "uuid"}
        }

Expected Behavior

Allow the request

Version and environment information

branch main
os: arch linux

Are you willing to submit a PR? If you know how to fix the bug.

  • I'm willing to submit a PR (Thank you!)

when the configuration file does not exist it gives an error

it is important to handle the error when the configuration file is not located, to avoid exposing the problem to the user

[main] INFO org.eclipse.jetty.util.log - Logging initialized @4198ms to org.eclipse.jetty.util.log.Slf4jLog
(-> moclojer :start-server :version "0.1")                                                                   
[main] INFO moclojer.router - {:mode "moclojer", :line 19}                                                   
Exception in thread "main" java.io.FileNotFoundException: /app/moclojer.yml (Is a directory)  

Proposal: use OpenAPI to describe the routes

This project currently use a custom YAML format to describe the routes.

It would be nice if it uses as a base for this YAML config file, the OpenAPI format.

Some possible benefits for this move:

  • Developer familiarity: developers already know OpenAPI format
  • Tooling: we can generate auto-docs from it.

Here how the first example endpoint can be represented.

paths:
  /hello-world:
    get:
      ## Your new mockResponse attribute
      mockResponse:
        status: 200
        headers:
          Content-Type: application/json
        body: >
        {
          "hello": "Hello, World!"
        }
      ## Other OpenAPI v3 attributes, that may be used to check if the request is valid
      ## or just use to show an autodoc webpage.
      tags:
        - hello
        - world
      parameters:
        - name: username
          in: path
          description: Username of the user to send hello
          required: false
          schema:
            type: string

Pending tasks:

  • Check if mockResponse is a name allowed to extension in openAPI spec

Future work:

  • Allow situations where openapi-spec.yaml already exists, and we just want to add mock to this spec. In OpenAPI, each operation can have a unique OperationID. We can use it and provide an extra file, operationId->mock.yaml, allowing to generate mocks to a existing openapi spec.

binary distribution: graalvm support (native-image)

Search first

  • I searched and no similar issues were found

What Happened?

We have a problem generating binaries with graalvm/native-image with the implementation of issue #152 in PR #153 - it's a simple implementation and graalvm has stopped working and we can't identify the real reason why it's not generating the binary (working correctly).

the "feature" (binary distribution) has been removed, but it is an important feature for the long-term "success" of the product, so we need to implement it in the future.

related: #154

Reproduce the Bug

... it's not an execution bug, so I'm not describing it step by step

moclojer config

Expected Behavior

No response

Version and environment information

#153

Are you willing to submit a PR? If you know how to fix the bug.

  • I'm willing to submit a PR (Thank you!)

Version from Moclojer is hardcoded on dev/moclojer/build.clj

Search first

  • I searched and no similar issues were found

What Happened?

The version is hardcoded, we should be able to have it updated on a release.

Reproduce the Bug

Check the dev/moclojer/build.clj file

moclojer config

Not applicable

Expected Behavior

0.2 should be the version

Version and environment information

N/A

Are you willing to submit a PR? If you know how to fix the bug.

  • I'm willing to submit a PR (Thank you!)

action/release: Zipped Artifact Downloads

πŸ€” Pattern 'moclojer_Linux' does not match any files.
[12](https://github.com/moclojer/moclojer/runs/8177200669?check_suite_focus=true#step:7:13)
πŸ€” Pattern 'moclojer_macOS' does not match any files.
[13](https://github.com/moclojer/moclojer/runs/8177200669?check_suite_focus=true#step:7:14)
πŸ€” Pattern 'moclojer.jar' does not match any files.
[14](https://github.com/moclojer/moclojer/runs/8177200669?check_suite_focus=true#step:7:15)
πŸ‘©β€πŸ­ Creating new GitHub release for tag v0.1.1...
[15](https://github.com/moclojer/moclojer/runs/8177200669?check_suite_focus=true#step:7:16)
πŸ€” moclojer_Linux,moclojer_macOS,moclojer.jar not include valid file.
[16](https://github.com/moclojer/moclojer/runs/8177200669?check_suite_focus=true#step:7:17)
πŸŽ‰ Release ready at https://github.com/moclojer/moclojer/releases/tag/v0.1.1

ref

Total size of all the files uploaded is 20037109 bytes
[28](https://github.com/moclojer/moclojer/runs/8177104167?check_suite_focus=true#step:6:29)
File upload process has finished. Finalizing the artifact upload
[29](https://github.com/moclojer/moclojer/runs/8177104167?check_suite_focus=true#step:6:30)
Artifact has been finalized. All files have been successfully uploaded!
[30](https://github.com/moclojer/moclojer/runs/8177104167?check_suite_focus=true#step:6:31)

[31](https://github.com/moclojer/moclojer/runs/8177104167?check_suite_focus=true#step:6:32)
The raw size of all the files that were specified for upload is 26968106 bytes
[32](https://github.com/moclojer/moclojer/runs/8177104167?check_suite_focus=true#step:6:33)
The size of all the files that were uploaded is 20037109 bytes. This takes into account any gzip compression used to reduce the upload size, time and storage
[33](https://github.com/moclojer/moclojer/runs/8177104167?check_suite_focus=true#step:6:34)

[34](https://github.com/moclojer/moclojer/runs/8177104167?check_suite_focus=true#step:6:35)
Note: The size of downloaded zips can differ significantly from the reported size. For more information see: https://github.com/actions/upload-artifact#zipped-artifact-downloads

ref

Zipped Artifact Downloads

Bruno uses plain-text files organized in related folders, in order to declare an API client tester.

Discussed in #186

Originally posted by matheusfrancisco December 4, 2023
Bruno uses plain-text files organized in related folders, in order to declare an API client tester.

schema: https://bruno-docs.vercel.app/bru-language-tag-reference.html
real use case: https://github.com/usebruno/github-rest-api-collection/tree/main

The root folder needs a json file with the content as follows:

{
  "version": "1",
  "name": "<<the name of my rest api>>",
  "type": "collection"
}

every subsequent file can contain the following:

meta

info about the request

meta {
  name: Get users,
  type: http
  seq: 1
}

A method

which can be any of get, post, put, delete, options, trace, connect and head.

[get/post/put/delete/options/trace/connect/head] {
  url: https://api.github.com/users/usebruno
}

Query Params

optional

query {
  something: hello
  anotherThing: bye
  aThirdThing: hi again
}

Head Params

optional

headers {
  content-type: application/json
  Authorization: Bearer topsecret
}

Body

optional

The body can be of any type within text, xml, form-encoded, json, multipart-form, graphql, pre-request and post-request

body:text {
  This is a text body
}

cc: @J0sueTM

tests: reuse server object

In order to simplify the contribution and reduce the cognitive load for writing tests, we can reduce the number of duplicate lines of service-fn by moving it to a library to help with testing.

A large part of moclojer's tests are end-to-end (usability) tests. We "turn on" the mock server and send a request to the configured endpoint, validating that the return from the endpoint is as expected.

(let [service-fn (-> {::http/routes (router/smart-router
{::router/config (yaml/from-file "test/moclojer/resources/moclojer.yml")})}
http/default-interceptors
http/dev-interceptors
http/create-servlet
::http/service-fn)]

namespace proposal: moclojer.helpers-test

Add Command-line interface

Add 3 arguments to the main function would be nice:

  • --help -h
  • --config -c
  • --mock -m

There are some tools to help this like docopt.clj

This would make moclojer even more like a cli tool, wdyt?

API Blueprint specification support

There is a specification called API Blueprint created by Apiary (and bought by Oracle).

Specification
Examples

There is a mock server project written in Java that implements the Blueprint API specification

Simple example:

FORMAT: 1A

# The Simplest API
This is one of the simplest APIs written in the **API Blueprint**. One plain
resource combined with a method and that's it! We will explain what is going on
in the next installment - 
[Resource and Actions](02.%20Resource%20and%20Actions.md).

**Note:** As we progress through the examples, do not also forget to view the
[Raw](https://raw.github.com/apiaryio/api-blueprint/master/examples/01.%20Simplest%20API.md)
code to see what is really going on in the API Blueprint, as opposed to just
seeing the output of the Github Markdown parser.

Also please keep in mind that every single example in this course is a **real
API Blueprint** and as such you can **parse** it with the 
[API Blueprint parser](https://github.com/apiaryio/drafter) or one of its
[bindings](https://github.com/apiaryio/drafter#bindings).

## API Blueprint
+ [This: Raw API Blueprint](https://raw.github.com/apiaryio/api-blueprint/master/examples/01.%20Simplest%20API.md)
+ [Next: Resource and Actions](02.%20Resource%20and%20Actions.md)

# GET /message
+ Response 200 (text/plain)

        Hello World!

`extend-body.path`: dynamic path support based on request

**How do I load a dynamic file based on the endpoint parameter (URI)?

Today there is no support for making the file path dynamic.

use case

Is there an intense list of PokΓ©mon (or anything):

  • kabuto
  • marowak
  • cubone
  • armaldo
- endpoint:
    method: GET
    path: /pokemon/:name
    response:
      status: 200
      headers:
        Content-Type: application/json
      external-body:
        provider: json
        path: https://pokeapi.co/api/v2/pokemon/{{path-params.name}}

URI's:

  • GET /pokemon/kabuto
  • GET /pokemon/marowak
  • GET /pokemon/cubone
  • GET /pokemon/armaldo

support for multiple domains in the specification (configuration)

- endpoint:
    host: moclojer.com
    method: GET
    path: /multihost
    response:
      status: 200
      headers:
        Content-Type: application/json
      body: >
        {
          "domain": "moclojer.com"
        }

- endpoint:
    host: sub.moclojer.com
    method: GET
    path: /multihost-sub
    response:
      status: 200
      headers:
        Content-Type: application/json
      body: >
        {
          "domain": "sub.moclojer.com"
        }

OpenAPI: class java.lang.Integer cannot be cast to class java.lang.CharSequence

test using yml: OpenAPI-Specification/examples/v3.0/petstore.yaml

backtrace:

❯ moclojer (main) ✘ CONFIG="OpenAPI-Specification/examples/v3.0/petstore.yaml" MOCKS="moclojer.yml" clojure -X:run
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/Users/avelino/.m2/repository/org/slf4j/slf4j-simple/1.7.5/slf4j-simple-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/Users/avelino/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.SimpleLoggerFactory]
[main] INFO org.eclipse.jetty.util.log - Logging initialized @2692ms to org.eclipse.jetty.util.log.Slf4jLog
"(moclojer :start-server)"
Execution error (ClassCastException) at moclojer.openapi/json-pointer->path (openapi.clj:30).
class java.lang.Integer cannot be cast to class java.lang.CharSequence (java.lang.Integer and java.lang.CharSequence are in module java.base of loader 'bootstrap')

Full report at:
/var/folders/zy/hl55b1r15qs7pq6dtflqf5k80000gn/T/clojure-13562412897444537512.edn

include file in body endpoint return

Discussed in #159

Originally posted by avelino October 20, 2023
Specifying large returns in the same moclojer configuration file (.yaml or any format) is "boring" and makes the specification file difficult to read.

Why not support the file inclusion tag for the body?

- endpoint:
    method: GET
    path: /external-body-text
    response:
      status: 200
      headers:
        Content-Type: application/json
      external-body:
        provider: text
        path: test/moclojer/resources/text-plan.json

using the specification external-body created for xlsx support #152

Wacth services functions is not working.

Search first

  • I searched and no similar issues were found

What Happened?

We are running moclojer from branch: main and when we edited the yml file the service didn't change.

Looking at the code we didn't see this log https://github.com/moclojer/moclojer/blob/main/src/moclojer/core.clj#L90.

Reproduce the Bug

  1. Run the server with a yml
  2. Edit the yml, add new endpoint
  3. try to get the endpoint will show not found

moclojer config

# This mock register route: GET /hello/:username
- endpoint:
    # Note: the method could be omitted because GET is the default
    method: GET
    path: /hello/:username
    response:
      # Note: the status could be omitted because 200 is the default
      status: 200
      headers:
        Content-Type: application/json
      # Note: the body will receive the value passed in the url using the
      # :username placeholder
      body: >
        {
          "hello": "{{path-params.username}}!"
        }

Expected Behavior

When I change the config yaml.
I would like not to have to restart the server.

Version and environment information

moclojer: branch main

Are you willing to submit a PR? If you know how to fix the bug.

  • I'm willing to submit a PR (Thank you!)

dynamic endpoint support

path: /hi/:username

When receiving a parameter in the URL it must pass it to the template, being possible to use the parameter in the return body

yml example:

- endpoint:
    method: GET
    path: /hi/:username
    response:
      status: 200
      headers:
        Content-Type: application/json
      body: >
        {
          "username": "{{username}}"
        }

recommendation

For template rendering we can use Selmer, it keeps up to date and has a friendly syntax.

Example of use:

(parser/render "{{username}}" {:username "moclojer"})

endpoint with `xlsx` content

support excel document (xlsx) content on endpoint return

discussed in #116

table:

name langs
avelino clojure, go
chicao clojure, python

response (expected):

[{"name": "avelino", "langs": "clojure, go"},
{"name": "chicao","langs": "clojure, python"}]
- endpoint:
    method: GET
    path: /xlsx
    response:
      status: 200
      headers:
        Content-Type: application/json
      external-body:
        provider: xlsx
        path: test/moclojer/resources/lerolero.xlsx
        sheet-name: test

Improve build pipeline (jar and native-image)

The build process is slow (it takes a long time), the configuration files (github action) are extensive and confusing.

We need to simplify the files and design a more user-friendly solution – do we need the .jar dependency to generate native-image? It's probably best to generate the .jar again!

in the printscreen below generating the jar took 36s and uploading the artifact was at 67% taking +9min

Screenshot 2023-10-15 at 11 22 37

related: #25

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.