{"id":37097691,"url":"https://github.com/depado/platypus","last_synced_at":"2026-01-14T12:00:10.410Z","repository":{"id":65193387,"uuid":"187605339","full_name":"depado/platypus","owner":"depado","description":"Very simple and customizable mock/echo server ","archived":false,"fork":false,"pushed_at":"2025-12-19T13:14:26.000Z","size":864,"stargazers_count":16,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-12-21T16:30:18.414Z","etag":null,"topics":["echo-server","go","golang","http","mock","mock-server"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/depado.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2019-05-20T09:01:55.000Z","updated_at":"2025-12-19T13:13:50.000Z","dependencies_parsed_at":"2025-12-05T06:02:08.339Z","dependency_job_id":null,"html_url":"https://github.com/depado/platypus","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/depado/platypus","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/depado%2Fplatypus","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/depado%2Fplatypus/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/depado%2Fplatypus/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/depado%2Fplatypus/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/depado","download_url":"https://codeload.github.com/depado/platypus/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/depado%2Fplatypus/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28419272,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T10:47:48.104Z","status":"ssl_error","status_checked_at":"2026-01-14T10:46:19.031Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["echo-server","go","golang","http","mock","mock-server"],"created_at":"2026-01-14T12:00:09.697Z","updated_at":"2026-01-14T12:00:10.394Z","avatar_url":"https://github.com/depado.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003ePlatypus\u003c/h1\u003e\n\u003ch2 align=\"center\"\u003e\n  \u003cimg src=\"img/platypus.jpg\" alt=\"mascot\" height=\"350px\"\u003e\n\n  [![forthebadge](https://forthebadge.com/images/badges/made-with-go.svg)](https://forthebadge.com)[![forthebadge](https://forthebadge.com/images/badges/built-with-love.svg)](https://forthebadge.com)[![forthebadge](https://forthebadge.com/images/badges/uses-badges.svg)](https://forthebadge.com)\n\n  ![Go Version](https://img.shields.io/badge/Go%20Version-latest-brightgreen.svg)\n  [![Go Report Card](https://goreportcard.com/badge/github.com/depado/platypus)](https://goreportcard.com/report/github.com/depado/platypus)\n  [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/depado/platypus/blob/master/LICENSE)\n  [![Say Thanks!](https://img.shields.io/badge/Say%20Thanks-!-1EAEDB.svg)](https://saythanks.io/to/Depado)\n\n  Very simple mock server that doesn't do much\n\u003c/h2\u003e\n\n\u003e That external API you're relying on is supposed to send back a duck.\n\u003e Unfortunately sometimes things don't go as expected and you're dealing with a\n\u003e platypus instead. It's ok.\n\n## Introduction\n\nPlatypus is a very simple mock server to abstract external services. It supports\nCORS which is disabled by default but fully configurable.\n\n## Install\n\n### From source\n\nYou can install platypus by using directly the go command line:\n\n```bash\n$ go install github.com/depado/platypus\n```\n\nOr if you wish to have the version information and such:\n\n```\n$ git clone git@github.com:Depado/platypus.git\n$ make install\n```\n\n### Binary release\n\nYou can also download the latest release for your system on the\n[release page](https://github.com/depado/platypus/releases).\n\n### Docker image\n\nYou can run platypus directly using docker using the packages found\n[on this page](https://github.com/depado/platypus/pkgs/container/platypus).\n\nExample:\n\n```bash\ndocker run -it --rm -v (pwd):/data ghcr.io/depado/platypus:latest --mock mocks/gerrit.yml\n```\n\n## Usage\n\n\u003ch2 align=\"center\"\u003e\n  \u003cimg src=\"img/screenshot.png\" alt=\"screenshot\" height=\"400px\"\u003e\n\u003c/h2\u003e\n\n```\nPlatypus is a very simple mock server\n\nUsage:\n  platypus [flags]\n  platypus [command]\n\nAvailable Commands:\n  help        Help about any command\n  version     Show build and version\n\nFlags:\n      --conf string                   configuration file to use\n  -h, --help                          help for platypus\n      --log.format string             one of text or json (default \"text\")\n      --log.level string              one of debug, info, warn, error or fatal (default \"info\")\n      --log.line                      enable filename and line in logs\n      --mock string                   file to mock from (default \"mock.yml\")\n      --server.cors.all               defines that all origins are allowed\n      --server.cors.enable            enable CORS\n      --server.cors.expose strings    array of exposed headers\n      --server.cors.headers strings   array of allowed headers (default [Origin,Authorization,Content-Type])\n      --server.cors.methods strings   array of allowed method when cors is enabled (default [GET,PUT,POST,DELETE,OPTION,PATCH])\n      --server.cors.origins strings   array of allowed origins (overwritten if all is active)\n      --server.host string            host on which the server should listen (default \"127.0.0.1\")\n      --server.mode string            server mode can be either 'debug', 'test' or 'release' (default \"release\")\n      --server.port int               port on which the server should listen (default 8080)\n\nUse \"platypus [command] --help\" for more information about a command.\n```\n\nWhen starting up, platypus will display the endpoints with the associated\nmethod(s) as well as the response information (type of response, code, name,\netc)\n\n## Configuration\n\n### mock.yml\n\nTo define how platypus should behave you should create a `mock.yml` file where\nyou're going to start platypus. Alternatively you can place the yaml file\nanywhere and name it as you like if you provide the `--mock \u003cpath\u003e` flag when\nstarting platypus.\n\nThis file contains the various definitions of your endpoints like so:\n\n```yaml\n---\nendpoints:\n- path: /hello/world\n  get:\n    responses:\n    - code: 200\n      body: |\n        {\"hello\": \"world\"}\n\n- path: /with/parameter/:param\n  get:\n    responses:\n    - code: 200\n      body: |\n        {\"hello\": \"world\"}\n```\n\nEach endpoint is defined by a string which can accept query params in the\nsame form as [gin](https://github.com/gin-gonic/gin). Then you can define the\nHTTP methods it should handle (`get`, `post`, `put`, `patch`, `delete`, `head`,\n`options`). Each of these method can have a specific behavior.\n\n## Methods\n\nEach method associated to an endpoint can be customized to add validation\nbehavior or to output more information when it gets called.\n\n```yaml\nendpoints:\n- path: /hello/world\n  get:\n    dump: [headers,body,host]\n    validate:\n      headers:\n        present: [Authorization]\n        absent: [Forbidden, X-Forbidden]\n        match:\n          X-Exact-Value: \"exact value\"\n      body:\n        contains: \"interesting value\"\n   responses:\n    - code: 200\n      body: |\n        {\"hello\": \"world\"}\n```\n\n### Dump\n\n`dump` defines what should be shown in the terminal when a request calls this\nspecific endpoint. Values can be `header`, `body`, `host`, `proto` or any\ncombination of these. The special option `all` can also be used to group all\nthese.\n\n\u003ch2 align=\"center\"\u003e\n  \u003cimg src=\"img/dump.png\" alt=\"screenshot\" height=\"400px\"\u003e\n\u003c/h2\u003e\n\n### Validate\n\nThe `validate` key can be used to validate incoming requests to match special\nrules. This is especially useful to quickly see whether or not a request is\nsupposed to fail with the non-mocked API. This is entirely optional as it may\nnot be the desired behavior anyway.\n\n- `headers`\n  - `present`: List of headers the incoming request must have\n  - `absent`: List of headers the incoming request must not have\n  - `match`: Header/Value pairs the incoming request must have\n- `body`\n  - `contains`:\n\n\n\n### Responses\n\nEvery method in a path can have multiple responses. These responses are sent\nin a random manner when the endpoint is called. This allows to simulate\nunexpected behaviors on the mock side. If you wish you can add a `ratio` keyword\nwhich will tell platypus how often this response should be sent back. For\nexample the following example will send back a `500` error 1% of the time:\n\n```yaml\nendpoints:\n- path: /failure/maybe\n  get:\n    responses:\n    - code: 200\n    - code: 500\n      ratio: 1\n```\n\nThe ratio keyword is a percentage. If no ratio is provided, then the odds are\ndistributed equally between all the possible responses. So if there's only one\nresponse provided, it will always be sent.\n\nNote that the above yaml is equivalent to this one:\n\n```yaml\nendpoints:\n- path: /failure/maybe\n  get:\n    responses:\n    - code: 200\n      ratio: 99\n    - code: 500\n      ratio: 1\n```\n\n### Headers\n\nAn additional field `headers` can be added to a specific method.\nThis header will then be considered as mandatory and, if absent from the request,\nthe endpoint will return a `400 Bad Request` with a specific JSON output.\n\nNote that this check will happen before picking up the response, so it will\nalways return this error before returning any other response.\n\nHeaders in the responses can be defined directly in the response like so:\n\n```yaml\nendpoints:\n- path: /failure/maybe\n  get:\n    responses:\n    - code: 200\n      headers:\n      - name: Content-Type\n        value: application/json; charset=utf-8\n    - code: 500\n      ratio: 1\n```\n\nTo make things simpler regarding headers, a specific key `preset` can be used.\nThe `json` preset will set the `Content-Type` header with the correct value. So\nthe example above can be rewritten like so:\n\n```yaml\nendpoints:\n- path: /failure/maybe\n  get:\n    responses:\n    - code: 200\n      preset: json\n    - code: 500\n      ratio: 1\n```\n\n### Empty method endpoint\n\nIf a method is defined within an endpoint but doesn't have responses or anything\nattached, then a `200` will be sent back. This can be achieved like so:\n\n```yaml\n- path: /maybe\n  post: {}\n  patch: {}\n  get:\n    responses:\n    - code: 200\n      preset: json\n    - code: 500\n      ratio: 1\n```\n\nWhen starting up, platypus will be able to generate two simple endpoints for the\nPOST and PATCH methods. Both will simply return a `200` and return.\n\n## Attributions\n\nPlatypus drawing by\n[rawpixel](https://www.rawpixel.com/image/562293/duck-billed-platypus-shade-drawing)\nunder the [CC0 license](https://creativecommons.org/publicdomain/zero/1.0/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdepado%2Fplatypus","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdepado%2Fplatypus","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdepado%2Fplatypus/lists"}