{"id":20768131,"url":"https://github.com/softwaremill/livestub","last_synced_at":"2025-10-30T00:33:19.016Z","repository":{"id":36952121,"uuid":"248735709","full_name":"softwaremill/livestub","owner":"softwaremill","description":"The HTTP server stub you always wanted!","archived":false,"fork":false,"pushed_at":"2025-03-19T00:25:07.000Z","size":788,"stargazers_count":55,"open_issues_count":28,"forks_count":8,"subscribers_count":25,"default_branch":"master","last_synced_at":"2025-04-02T11:47:22.768Z","etag":null,"topics":["http","http-server","mocking-server","scala","stub-server"],"latest_commit_sha":null,"homepage":"","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/softwaremill.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2020-03-20T11:10:05.000Z","updated_at":"2025-03-22T17:08:14.000Z","dependencies_parsed_at":"2024-01-08T02:05:17.451Z","dependency_job_id":"db4b76fd-340f-4599-aa4b-ab5446743183","html_url":"https://github.com/softwaremill/livestub","commit_stats":{"total_commits":601,"total_committers":7,"mean_commits":85.85714285714286,"dds":0.2778702163061564,"last_synced_commit":"1a0b6305ab728c0682b52baaf5865409bd877734"},"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softwaremill%2Flivestub","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softwaremill%2Flivestub/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softwaremill%2Flivestub/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softwaremill%2Flivestub/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/softwaremill","download_url":"https://codeload.github.com/softwaremill/livestub/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248054193,"owners_count":21039952,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["http","http-server","mocking-server","scala","stub-server"],"created_at":"2024-11-17T11:35:49.968Z","updated_at":"2025-10-30T00:33:18.950Z","avatar_url":"https://github.com/softwaremill.png","language":"Scala","readme":"# livestub\n\n[![Build Status](https://travis-ci.org/softwaremill/livestub.svg?branch=master)](https://travis-ci.org/softwaremill/livestub)\n[![Docker Pulls](https://img.shields.io/docker/pulls/softwaremill/sttp.livestub.svg)](https://hub.docker.com/r/softwaremill/sttp.livestub/)\n![Docker Image Size (latest by date)](https://img.shields.io/docker/image-size/softwaremill/sttp.livestub)\n[![Scala Steward badge](https://img.shields.io/badge/Scala_Steward-helping-brightgreen.svg?style=flat\u0026logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAQCAMAAAARSr4IAAAAVFBMVEUAAACHjojlOy5NWlrKzcYRKjGFjIbp293YycuLa3pYY2LSqql4f3pCUFTgSjNodYRmcXUsPD/NTTbjRS+2jomhgnzNc223cGvZS0HaSD0XLjbaSjElhIr+AAAAAXRSTlMAQObYZgAAAHlJREFUCNdNyosOwyAIhWHAQS1Vt7a77/3fcxxdmv0xwmckutAR1nkm4ggbyEcg/wWmlGLDAA3oL50xi6fk5ffZ3E2E3QfZDCcCN2YtbEWZt+Drc6u6rlqv7Uk0LdKqqr5rk2UCRXOk0vmQKGfc94nOJyQjouF9H/wCc9gECEYfONoAAAAASUVORK5CYII=)](https://scala-steward.org)\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.softwaremill.sttp.livestub/livestub-app_2.13/badge.svg)](https://search.maven.org/search?q=g:com.softwaremill.sttp.livestub)\n\n\nWith livestub you can easly setup http server that behaves exactly as you would like it to. That makes livestub a perfect solution for faking arbitrary services which might be very useful in development/testing.\n\n## Usage\n\n### launch\n - **coursier**\n\n    `coursier launch com.softwaremill.sttp.livestub:livestub-app_2.13:0.2.1 -- -p 7070`\n\n- **docker**\n\n    `docker run -p 7070:7070 softwaremill/sttp.livestub`\n\n- **code**\n\n```scala\nimport sttp.livestub.app.LiveStubServer\nimport sttp.livestub.app.LiveStubServer.Config\nLiveStubServer.resource(Config(port = 7070))\n```\n\n### stub\n```bash\ncurl -X POST 'localhost:7070/__set' \\\n-d '{\"when\":{\"method\":\"GET\", \"url\":\"animals/1/status\"}, \"then\": {\"statusCode\":200, \"body\":{\"status\": \"happy\"} }}'\n```\n\n### invoke\n```bash\ncurl 'localhost:7070/animals/1/status'\n{\"status\":\"happy\"}\n```\n\n### swagger\n\nSwagger is available under `/__admin/docs`\n\n### advanced stubbing\n\nLivestub supports wildcard http methods as well as wildcard path parameters.\n\nwildcard method:\n```bash\ncurl -X POST 'localhost:7070/__set' \\\n-d '{\"when\":{\"method\":\"*\", \"url\":\"dogs\"}, \"then\": {\"statusCode\":200, \"body\":{\"status\": \"OK\"} }}'\n```\n\nwildcard path param: \n```bash\ncurl -X POST 'localhost:7070/__set' \\\n-d '{\"when\":{\"method\":\"GET\", \"url\":\"dogs/*/status\"}, \"then\": {\"statusCode\":200, \"body\":{\"status\": \"happy\"} }}'\n```\n\nmultiwildcard path param: (this one catches all routes which originate from `/dogs`)\n```bash\ncurl -X POST 'localhost:7070/__set' \\\n-d '{\"when\":{\"method\":\"GET\", \"url\":\"dogs/**\"}, \"then\": {\"statusCode\":200, \"body\":{\"status\": \"cheerful\"} }}'\n```\n\nwildcard query param: (this one catches all the query parameters for `/dogs`, example: `/dogs?id=1\u0026breed=bulldog`)\n```bash\ncurl -X POST 'localhost:7070/__set' \\\n-d '{\"when\":{\"method\":\"GET\", \"url\":\"dogs?*\"}, \"then\": {\"statusCode\":200, \"body\":{\"status\": \"cheerful\"} }}'\n```\n\n### additional methods\n\nclear stubbed routes\n```bash\ncurl -X POST 'localhost:7070/__clear'\n```\n\nshow stubbed routes\n\n```bash\ncurl 'localhost:7070/__routes'\n```\n\nset many responses which will be cycled through\n```bash\ncurl -X POST 'localhost:7070/__set_many' \\\n-d '{\"when\":{\"method\":\"GET\", \"url\":\"animals/1/status\"}, \"then\": [\n    {\"statusCode\":200, \"body\":{\"status\": \"happy\"} },\n    {\"statusCode\":200, \"body\":{\"status\": \"unhappy\"} }\n  ]\n}'\n```\n\n### stubbing from code - sdk\n\n```scala\nlibraryDependencies += \"com.softwaremill.sttp.livestub\" % \"livestub-sdk\" % \"0.2.1\"\n```\n\nGiven a bunch of imports\n```scala\nimport sttp.client3.asynchttpclient.cats.AsyncHttpClientCatsBackend\nimport sttp.client3.SttpBackend\nimport sttp.livestub.sdk._\nimport sttp.livestub.api._\nimport sttp.client3.{Response =\u003e _, _}\nimport sttp.model._\nimport io.circe.Json\n```\n\nyou can stub an arbitrary request:\n```scala\nAsyncHttpClientCatsBackend[IO]().flatMap { backend: SttpBackend[IO, Any] =\u003e\n  val livestub = new LiveStubSdk[IO](uri\"http://mock:7070\", backend)\n  livestub\n    .when(RequestStubIn(MethodStub.Wildcard, \"/user/*/status\"))\n    .thenRespond(Response.emptyBody(StatusCode.Ok, List(Header(\"X-App\", \"123\"))))\n}\n```\nstub given [sttp](https://github.com/softwaremill/sttp) request:\n```scala\nAsyncHttpClientCatsBackend[IO]().flatMap { backend: SttpBackend[IO, Any] =\u003e\n  val request = basicRequest\n    .body(Map(\"name\" -\u003e \"John\", \"surname\" -\u003e \"doe\"))\n    .post(uri\"https://httpbin.org/post?signup=123\")\n\n  val livestub = new LiveStubSdk[IO](uri\"http://mock:7070\", backend)\n  livestub.when(request).thenRespond(Response(Some(Json.fromString(\"OK\")), StatusCode.Ok))\n}\n```\nor stub given [tapir](https://github.com/softwaremill/tapir) endpoint:\n```scala\nimport sttp.tapir._\n\nAsyncHttpClientCatsBackend[IO]().flatMap { backend: SttpBackend[IO, Any] =\u003e\n  val myEndpoint = endpoint.get.in(\"/status\").out(stringBody)\n\n  val livestub = new LiveStubSdk[IO](uri\"http://mock:7070\", backend)\n  livestub.when(myEndpoint)\n          .thenRespond(Response.emptyBody(StatusCode.Ok, List(Header(\"X-App\", \"123\"))))\n}\n```\n\n## OpenApi integration\n\nOpenApi specification can be provided to bootstrap livestub server with auto generated endpoints.\nFor each given path a request-response stub will be generated matching particular url. Both path parameters and required query parameters will be\nreplaced by wildcard matches. That means that neither optional query parameters, request body nor headers are going to be checked when matching\nstubbed endpoint.\n\nResponse structure will follow openapi schema. Response data will be created\nbased on openapi respective example parameters if provided, otherwise random data will be used(whenever it is possible).\n\n\n\nFor endpoints, which are defined in openapi specification but for which responses\ncouldn't be generated empty response body will be returned.\n\nUsage:\n`--openapi-spec \u003cpath_to_file\u003e`\n\nIn addition, seed value for random data generator can be passed via:\n`--seed 1234`\n\n## Development\n\nDocumentation is generated during every release from `docs-sources` directory.\nIt can be manually regenerated when needed by calling `sbt docs/mdoc`.\n\nTo release new version use `sbt release`.","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoftwaremill%2Flivestub","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsoftwaremill%2Flivestub","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoftwaremill%2Flivestub/lists"}