{"id":24890668,"url":"https://github.com/dosmike/restreplay","last_synced_at":"2026-05-17T15:08:12.183Z","repository":{"id":274347725,"uuid":"922634754","full_name":"DosMike/RESTReplay","owner":"DosMike","description":"Simple tool to send REST requests to a remote, in a format that looks a bit nicer than curl strings","archived":false,"fork":false,"pushed_at":"2025-07-21T20:44:02.000Z","size":91,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-22T16:42:19.166Z","etag":null,"topics":["automated-testing","automation","elasticsearch","http-file","python3","replay","rest","rest-client","rest-file","script","scripting","single-file","testing","testing-tools"],"latest_commit_sha":null,"homepage":"","language":"Python","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/DosMike.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":"2025-01-26T18:10:18.000Z","updated_at":"2025-01-31T18:56:47.000Z","dependencies_parsed_at":"2025-01-26T19:24:49.079Z","dependency_job_id":"a632badc-2f6c-4644-b301-0dbe45a126cd","html_url":"https://github.com/DosMike/RESTReplay","commit_stats":null,"previous_names":["dosmike/restreplay"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/DosMike/RESTReplay","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DosMike%2FRESTReplay","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DosMike%2FRESTReplay/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DosMike%2FRESTReplay/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DosMike%2FRESTReplay/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DosMike","download_url":"https://codeload.github.com/DosMike/RESTReplay/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DosMike%2FRESTReplay/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33143276,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-17T09:28:26.183Z","status":"ssl_error","status_checked_at":"2026-05-17T09:27:52.702Z","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":["automated-testing","automation","elasticsearch","http-file","python3","replay","rest","rest-client","rest-file","script","scripting","single-file","testing","testing-tools"],"created_at":"2025-02-01T17:17:27.332Z","updated_at":"2026-05-17T15:08:12.142Z","avatar_url":"https://github.com/DosMike.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# REST Replay\n\nTool to replay REST request in pipelines and other places.\n\nrere.py will load REST Replay files to replay, can do some basic processing with the response.\nThe replay files are not intended to house complex logic, but instead work in tandem with other languages and systems for more complex tasks.\n\n## Usage\n\n`rere.py --dry --verbose script`\n\n* `--dry` supresses requests, sets positive dummy data to response values\n* `--verbose` for debugging\n* `script` the REST Replay script to run\n\nTo create a simple script:\n* Open the dev tools in your browser\n* Make a request\n* Right click and copy request headers\n* Paste it into a text editor\n* Copy paste the request body below between two identical lines (delimiters, see below)\n* Add a line above with baseUrl scheme://netloc/\n\n```\nbaseUrl https://example.tld/\nPASTE REQUEST HEADERS\n\nPASTE REQUEST BODY\n\n# empty line above is important, if you want to use empty lines as delimiter\n# if your body contains empty lines, use anything else that doesn't look like a header, like a dot or colon or whatever\n```\n\nThese scripts are mostly compatible with .http/.rest files.\n\n## Format\n\nEmpty lines and lines starting with # are comments\n\nMeta commands start with a lowercase letter, and do not span more than one line. Request start with an upper case HTTP method.\nIndentation is stripped for commands and the first line of requests.\nThe script steps are validated as they are executed, terminating early ony syntax errors.\n\ne.g.\n```bash\nbaseUri https://localhost:9200/\ndefaultHeader Authorization: {{ env.API_KEY }}\n\nGET /index/_search\nContent-Type: application/json\n:\n{\n  query: { match: { _id: \"someid\" } }\n}\n:\n\nmode elastic\nGET /index/_search\n{\n  query: { match: { _id: \"someid\" } }\n}\n```\n\n### Requests\n\n#### .http / .rest mode\n\nRequests by default are written very similar to raw HTTP requests with the following format:\n\n```\nMETHOD URI\nHEADERS\nBODY\n```\n\nValid methods are: `GET`, `HEAD`, `POST`, `PUT`, `DELETE`, `PATCH`.\n\nIf the URI omits protocol and host part, it will be appended to the baseUri, if set. While header lines can be commented out, unless the request line itself is commented out, the body ignores comments.\n\nThe request is followed by 0 or more lines of headers, replacing over any set defaultHeader. The only forbidden header here is Content-Length, as it is replaced by the length of the body that follows.\n\nThe content body, in contrast to a raw HTTP request is delimited by any line after the headers that is not following `[\\w-]+:\\s*.+`.\nThe same delimiter is required after the request body, so Content-Length can be properly calculated, if templated or read from file.\nIf you do not have a body or know it does not contain empty lines, you can use those, although not recommended.\n\n#### elasic mode\n\nAlternatively you can switch to elastic mode, allowing you to copy paste elastic queries directly from the dev console.\n\n```\nMETHOD URL\nBODY\n```\n\nAs with http / rest mode, you probably want to specify a baseUrl to request against. Elestic mode however does not allow you to set per request headers. You can use defaultHeader instead.\n\nThe optional body in elastic mode is not explicitly delimited, but has to be a json object or array instead. The request body is complete once the smallest possible amount of lines connected parse successfully, so do not add extra characters on the closing line!\n\n### Meta Commands\n\nMeta commands are case sensitive. Before execution, every command argument in \\\u003c\u003e is ran through the templater. Words in CAPS are to be replaced, words with slashes are a choice.\n\n* baseUrl \\\u003cURL\u003e\n  \u003e The base url, can include a base path\n* envFiles PATHS\n  \u003e A list of paths, absolute or relative to the REST Replay file, delimited by colon (trimmed)\n* delimiter OPEN token CLOSE\n  \u003e Template values are delimited tokens that can be remapped here, if your format might already use that.\n  \u003e e.g. `delimiter (( token ))` to subsequentially use double parens.\n  \u003e *Default:* {{ token }}\n* timeout AMOUNT\n  \u003e How long to wait until a request times out. If a request times out, it will rewrite the responseCode and continue.\n  \u003e Amount is in seconds by default, but can be suffixed with s/sec/m/min.\n  \u003e *Default:* 3s\n* exit \\\u003cCODE\u003e\n  \u003e Abort execution and return the exit code. If CODE is not numeric, 1 is used.\n  \u003e *Default:* 0\n* defaultHeader \\\u003cNAME\u003e: \\\u003cVALUE\u003e\n  \u003e Set the default value for a given header. If value is empty, the default is unset.\n* set \\\u003cKEY\u003e: \\\u003cVALUE\u003e\n  \u003e Set values outside any namespace to the given value. Key has to consist of `[\\w-]` characters.\n* parseTemplates \\\u003cKEY\u003e\n  \u003e Force parsing templates within the template. If you have a literal value of \"{{ foo }}\" and foo is \"bar\", `parseTemplates value` would set value to \"bar\".\n* replace \\\u003cVALUE\u003e: \\\u003cSED_STRING\u003e\n  \u003e Use a sed s/// replacement expression on a template. The replacement is in-place.\n  \u003e The sed string has to start with a lowercase s, followed by a delimiter character picked by you. Immediately following the delimiter is the regular expression, and, after another separator, the replacement string. After the terminating delimiter, you can add the following flag characters:\n  \u003e * g - global, replace all occurances\n  \u003e * i - insensitive, ignore case\n  \u003e * m - multiline, ^.*$ matches the whole string instead of a line\n  \u003e * s - dotall, makes dot match line breaks\n  \u003e\n  \u003e Example: `replace key: s/search/replace/gi`\n* read PATH: \\\u003cKEY\u003e\n  \u003e Read the given file, absolute or relative to the REST Replay file, and write it's content into the template key.\n* write PATH: \\\u003cVALUE\u003e\n  \u003e At the specified path, absolute or relative to the REST Replay file, write the specified value.\n* print \\\u003cVALUE\u003e\n  \u003e Write some value to standard out / terminal\n* mode elastic/http/rest\n  \u003e In rest/http mode you have to write full HTTP requests with headers.\n  \u003e In elastic mode headers are not parsed and the optional body delimits as soon as a json object or array beginning in the next line is complete. Use defaultHeader if you need them.\n  \u003e *Default:* rest\n* cookies on/off\n  \u003e Turn cookie parsing on/off\n  \u003e *Default:* off\n* storage new/AMOUNT PATH\n  \u003e Enable persitent storage for cookies.\n  \u003e * AMOUNT is a limit on how long cookies should be stored for.\n  \u003e   This counts mtime for the storage file, not cookie age. To keep sessions in tact, this is only checked when reloading cookies from disk.\n  \u003e   Just like with timeout, in seconds by default, with optional suffix. Default duration is 300s.\n  \u003e * Writing new instead of a duration equals 0s.\n  \u003e * PATH is an optional path, absolute or relative to the REST Replay file, where to store cookies to.\n  \u003e Defaults to /tmp/restreplay.cache on linux, C:\\Users\\\\\\\u003cusername\u003e\\AppData\\Local\\Temp on windows\n  \u003e\n  \u003e *Default:* unset, cookies are not stored on disc.\n* sslContext OPTIONS/default\n  \u003e OPTIONS is a set of comma separated list of `key: value` pairs, with quoted values. Values can contain templates. These options map closely to the python [SSLContext](https://docs.python.org/3/library/ssl.html#ssl-contexts) object. All supported keys are optional. An abbreviated summary is provided for convenience. Check the linked python docs for more information. _**If unsure, leave unset**_. If you want to revert to default values, use `sslContext default` instead.\n  \u003e * cafile : path to a file of concatenated CA certificates in PEM format\n  \u003e * capath : path to a directory containing several CA certificates in PEM format\n  \u003e * certfile : path to a certificate for a cert chain\n  \u003e * keyfile : optional path to a separate private key file for the cert chain\n  \u003e * password : optional name of a template that stores the password for the private key. Will open a prompt if omited but keyfile is encrypted.\n  \u003e * mode :\n  \u003e   * NONE : just about any cert is accepted. Validation errors, such as untrusted or expired cert, are ignored and do not abort the TLS/SSL handshake\n  \u003e   * REQUIRED (default) : certificates are required from the other side of the socket connection; an SSLError will be raised if no certificate is provided, or if its validation fails. As PROTOCOL_TLS_CLIENT is set by default, this will validate hostnames.\n  \u003e   * UNCHECKED : This is like REQUIRED, but hostname checks are explicitly turned off. This mode is not sufficient to verify a certificate in client mode as it does not match hostnames.\n  \u003e * verify : (these are additive, so you have to re-add defaults if set)\n  \u003e   * CRL_UNCHECKED (default) : in this mode, certificate revocation lists (CRLs) are not checked (VERIFY_DEFAULT)\n  \u003e   * CRL_CHECK_LEAF : only the peer cert is checked but none of the intermediate CA certificates\n  \u003e   * CRL_CHECK_CHAIN : CRLs of all certificates in the peer cert chain are checked\n  \u003e   * X509_STRICT (default) : disable workarounds for broken X.509 certificates\n  \u003e   * ALLOW_PROXY_CERTS : enables proxy certificate verification\n  \u003e   * X509_TRUSTED_FIRST (default) : instructs OpenSSL to prefer trusted certificates when building the trust chain to validate a certificate\n  \u003e   * X509_PARTIAL_CHAIN (default) : instructs OpenSSL to accept intermediate CAs in the trust store to be treated as trust-anchors, in the same way as the self-signed root CA certificates\n  \u003e * protocol : (SSL2 / SSL3 are not supported)\n  \u003e   * TLS (default) : auto-negotiate the highest protocol version that both the client and server support\n  \u003e   * TLSv1.0 : selects TLS version 1.0 as the channel encryption protocol\n  \u003e   * TLSv1.1 : selects TLS version 1.1 as the channel encryption protocol\n  \u003e   * TLSv1.2 : selects TLS version 1.2 as the channel encryption protocol\n  \u003e * options : (protocol options are not supported, NO_SSLv2 | NO_SSLv3 are always set)\n  \u003e   * NO_RENEGOTIATION : disable all renegotiation in TLSv1.2 and earlier\n  \u003e   * ENABLE_MIDDLEBOX_COMPAT : send dummy Change Cipher Spec (CCS) messages in TLS 1.3 handshake to make a TLS 1.3 connection look more like a TLS 1.2 connection\n  \u003e   * NO_COMPRESSION : disable compression on the SSL channel\n  \u003e   * NO_TICKET : prevent client side from requesting a session ticket\n  \u003e   * IGNORE_UNEXPECTED_EOF : ignore unexpected shutdown of TLS connections\n  \u003e   * ENABLE_KTLS : enable the use of the kernel TLS\n  \u003e\n  \u003e example: `sslContext cafile: \"/path/to/cacert.pem\", protocol: \"TLS\", options: \"NO_RENEGOTIATION, NO_COMPRESSION\"`\n* eval \\\u003cKEY\u003e: \\\u003cEXRPESSION\u003e\n  \u003e Run a java-script one-liner and store the result to KEY.\n  \u003e This requires js2py or pythonmonkey to be installed.\n* if EXPRESSION\n  \u003e Evaluate the next command or request only if EXPRESSION holds true.\n\n### Expressions\n\nExpressions are really simple, without conjunction or disjunction (AND and OR). You can negate (NOT) and value compare. String and number literals are in JSON format, templates are safely resolved as values and dont use delimiters. Numeric comparisons are tried first, with string operations as fallback. Available comparisons are:\n\n* strings and numbers: A == B , A != B\n* numbers only: A \u003c B , A \u003c= B , A \u003e B , A \u003e= B, A in [ B .. C ]\n* strings only: empty A, A in B, A matches B\n\nIf a value can not parse as number, numeric compare expressions will return false.\n\n`A in [ B .. C ]` will be true if A is in the range of B and C (inclusive).\n\n`A matches B` tests a string A against a regex B.\n\n### Templates\n\nTemplates are simply replaced. Keys are `\\w+` with `.` as namespace separator.\n\nEnvironment variables are loaded into the `env` namespace and replaced by values in the envFiles, if specified.\nVariables set through commands do not have a namespace.\nEvery request replaces the values in the `response` namespace. The only variables in that namespace are: `body`, `code` and `headers`\n\n## Full example\n```bash\nenvFile .env\n\nread request_body.json: body\nGET https://localhost:3000/main_endpoint\nAuthorization: {{ env.API_KEY }}\n:\n{{ body }}\n:\n\nset value: {{ response.body }}\n\nif not {{ response.code }} in [ 200 .. 299 ]\n  exit 1\n\nwrite file.json: {{ value }}\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdosmike%2Frestreplay","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdosmike%2Frestreplay","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdosmike%2Frestreplay/lists"}