{"id":16152493,"url":"https://github.com/prashanth-sams/client-api","last_synced_at":"2025-03-18T19:31:22.854Z","repository":{"id":62555762,"uuid":"209296683","full_name":"prashanth-sams/client-api","owner":"prashanth-sams","description":"HTTP REST API client for testing APIs based on the ruby’s RSpec framework that binds a complete api automation framework setup within itself","archived":false,"fork":false,"pushed_at":"2020-02-26T10:00:08.000Z","size":491,"stargazers_count":20,"open_issues_count":27,"forks_count":5,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-28T11:49:38.637Z","etag":null,"topics":["api","api-automation","api-client","api-test","api-test-framework","api-testing-framework","automation","datatype","json-response","rest","rest-api","restful","restful-api","ruby","schema","testing"],"latest_commit_sha":null,"homepage":"https://rubygems.org/gems/client-api","language":"Ruby","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/prashanth-sams.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-09-18T11:55:51.000Z","updated_at":"2023-11-01T20:43:19.000Z","dependencies_parsed_at":"2022-11-03T05:45:30.660Z","dependency_job_id":null,"html_url":"https://github.com/prashanth-sams/client-api","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prashanth-sams%2Fclient-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prashanth-sams%2Fclient-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prashanth-sams%2Fclient-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prashanth-sams%2Fclient-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/prashanth-sams","download_url":"https://codeload.github.com/prashanth-sams/client-api/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243945561,"owners_count":20372897,"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":["api","api-automation","api-client","api-test","api-test-framework","api-testing-framework","automation","datatype","json-response","rest","rest-api","restful","restful-api","ruby","schema","testing"],"created_at":"2024-10-10T01:07:26.473Z","updated_at":"2025-03-18T19:31:22.540Z","avatar_url":"https://github.com/prashanth-sams.png","language":"Ruby","readme":"# ClientApi\n\n[![Gem Version](https://badge.fury.io/rb/client-api.svg)](http://badge.fury.io/rb/client-api)\n[![Build Status](https://travis-ci.org/prashanth-sams/client-api.svg?branch=master)](https://travis-ci.org/prashanth-sams/client-api)\n\u003e HTTP REST API client for testing application APIs based on the ruby’s RSpec framework that binds a complete api automation framework setup within itself \n\n### Features\n- [x] Custom Header, URL, and Timeout support\n- [x] URL query string customization\n- [x] Datatype and key-pair value validation\n- [x] Single key-pair response validation\n- [x] Multi key-pair response validation\n- [x] JSON response schema validation\n- [x] JSON response content validation\n- [x] JSON response size validation\n- [x] JSON response is empty? validation\n- [x] JSON response has specific key? validation\n- [x] JSON response array-list sorting validation (descending, ascending)\n- [x] Response headers validation\n- [x] JSON template as body and schema\n- [x] Support to store JSON responses of each tests for the current run\n- [x] Logs support for debug\n- [x] Custom logs remover\n- [x] Auto-handle SSL for http(s) schemes\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'client-api'\n```\n\nAnd then execute:\n```bash\n$ bundle\n```\n\nOr install it yourself as:\n```bash\n$ gem install client-api\n```   \n\nImport the library in your env file\n```ruby\nrequire 'client-api'\n```\n\n## #Usage outline\n\nAdd this config snippet in the `spec_helper.rb` file:\n```ruby\nClientApi.configure do |config|\n  # all these configs are optional; comment out the config if not required\n  config.base_url = 'https://reqres.in'\n  config.headers = {'Content-Type' =\u003e 'application/json', 'Accept' =\u003e 'application/json'}\n  config.basic_auth = {'Username' =\u003e 'ahamilton@apigee.com', 'Password' =\u003e 'myp@ssw0rd'}\n  config.json_output = {'Dirname' =\u003e './output', 'Filename' =\u003e 'test'}\n  config.time_out = 10  # in secs\n  config.logger = {'Dirname' =\u003e './logs', 'Filename' =\u003e 'test', 'StoreFilesCount' =\u003e 2}\n  \n  # add this snippet only if the logger is enabled\n  config.before(:each) do |scenario|\n    ClientApi::Request.new(scenario)\n  end\nend\n```\nCreate `client-api` object with custom variable\n```ruby\napi = ClientApi::Api.new\n```\n\nRSpec test scenarios look like,\n```ruby\nit \"GET request\" do\n  api = ClientApi::Api.new\n  \n  api.get('/api/users')\n  expect(api.status).to eq(200)\n  expect(api.code).to eq(200)\n  expect(api.message).to eq('OK')\nend\n\nit \"POST request\" do\n  api.post('/api/users', {\"name\": \"prashanth sams\"})\n  expect(api.status).to eq(201)\nend\n\nit \"DELETE request\" do\n  api.delete('/api/users/3')\n  expect(api.status).to eq(204)\nend\n\nit \"PUT request\" do\n  api.put('/api/users/2', {\"data\":{\"email\":\"prashanth@mail.com\",\"first_name\":\"Prashanth\",\"last_name\":\"Sams\"}})\n  expect(api.status).to eq(200)\nend\n\nit \"PATCH request\" do\n  api.patch('/api/users/2', {\"data\":{\"email\":\"prashanth@mail.com\",\"first_name\":\"Prashanth\",\"last_name\":\"Sams\"}})\n  expect(api.status).to eq(200)\nend\n\n# For exceptional cases with body in the GET/DELETE request\nit \"GET request with JSON body\" do\n  api.get_with_body('/api/users', { \"count\": 2 })\n  expect(api.status).to eq(200)\nend\n\nit \"DELETE request with JSON body\" do\n  api.delete_with_body('/api/users', { \"count\": 2 })\n  expect(api.status).to eq(200)\nend\n\n# Customize URL query string as a filter\nit \"Custom URL query string\" do\n  api.get(\n      {\n          :url =\u003e '/location?',\n          :query =\u003e {\n              'sort': 'name',\n              'fields[count]': '50',\n              'fields[path_prefix]': '6',\n              'filter[name]': 'Los Angels'\n          }\n      }\n  )\nend\n\n# For POST request with multi-form as body\nit \"POST request with multi-form as body\" do\n  api.post('/api/upload',\n     payload(\n         'type' =\u003e 'multipart/form-data',\n         'data' =\u003e {\n             'file': './data/request/upload.png'\n         }\n     )\n  )\n\n  expect(api.code).to eq(200)\nend\n```\n\n## Validation shortcuts\n\n#### Default validation\n\n\u003e key features\n- datatype validation\n- key-pair value validation\n- value size validation\n- is value empty validation\n- key exist or key not-exist validation\n- single key-pair validation\n- multi key-pair validation\n\n\u003e what to know? \n- operator field is optional when `\"operator\": \"==\"`\n- exception is handled for the invalid key (say, `key: 'post-\u003e0-\u003ename'`), if the `has_key` field is not added in the validation \n\n\u003ctable\u003e\n    \u003ctr\u003e\n        \u003cth\u003e\n            General Syntax\n        \u003c/th\u003e\n        \u003cth\u003e\n            Syntax | Model 2\n        \u003c/th\u003e\n        \u003cth\u003e\n            Syntax | Model 3\n        \u003c/th\u003e\n        \u003cth\u003e\n            Syntax | Model 4\n        \u003c/th\u003e\n        \u003cth\u003e\n            Syntax | Model 5\n        \u003c/th\u003e\n        \u003cth\u003e\n            Syntax | Model 6\n        \u003c/th\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n            \u003cpre\u003e\nvalidate(\n    api.body,\n    {\n        key: '',\n        operator: '', \n        value: '', \n        type: ''\n    }\n)\n            \u003c/pre\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e\n            \u003cpre\u003e\nvalidate(\n    api.body,\n    {\n        key: '', \n        size: 0\n    }\n)\n            \u003c/pre\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e\n            \u003cpre\u003e\nvalidate(\n    api.body,\n    {\n        key: '', \n        empty: true\n    }\n)\n            \u003c/pre\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e\n            \u003cpre\u003e\nvalidate(\n    api.body,\n    {\n        key: '', \n        has_key: true\n    }\n)\n            \u003c/pre\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e\n            \u003cpre\u003e\nvalidate(\n    api.body,\n    {\n        key: '',\n        operator: '', \n        value: '', \n        type: '', \n        size: 2,\n        empty: true,\n        has_key: false\n    }\n)\n            \u003c/pre\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e\n            \u003cpre\u003e\nvalidate(\n    api.body,\n    {\n        key: '', \n        type: ''\n    },\n    {\n        key: '', \n        operator: '', \n        value: ''\n    }\n)\n            \u003c/pre\u003e\n        \u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\n#### JSON response content validation\n\n\u003e key benefits\n- the most recommended validation for fixed / static JSON responses\n- validates each JSON content value\n\n\u003e what to know?\n- replace `null` with `nil` in the expected json (whenever applicable); cos, ruby don't know what is `null`\n\n\n\u003ctable\u003e\n    \u003ctr\u003e\n        \u003cth\u003e\n            General Syntax\n        \u003c/th\u003e\n        \u003cth\u003e\n            Syntax | Model 2\n        \u003c/th\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n            \u003cpre\u003e\nvalidate_json(\n    {\n        \"data\":\n            {\n                \"id\": 2,\n                \"first_name\": \"Prashanth\",\n                \"last_name\": \"Sams\",\n            }\n    },\n    {\n        \"data\":\n            {\n                \"id\": 2,\n                \"first_name\": \"Prashanth\",\n                \"last_name\": \"Sams\",\n            }\n    }\n)\n            \u003c/pre\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e\n            \u003cpre\u003e\nvalidate_json(\n    api.body,\n    {\n        \"data\":\n            {\n                \"id\": 2,\n                \"first_name\": \"Prashanth\",\n                \"last_name\": \"Sams\",\n                \"link\": nil\n            }\n    }\n)\n            \u003c/pre\u003e\n        \u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\n#### JSON response sorting validation\n\n\u003e key benefits\n- validates an array of response key-pair values with ascending or descending soring algorithm. For more details, check `sort_spec.rb`\n\n\u003ctable\u003e\n    \u003ctr\u003e\n        \u003cth\u003e\n            General Syntax\n        \u003c/th\u003e\n        \u003cth\u003e\n            Syntax | Model 2\n        \u003c/th\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n            \u003cpre\u003e\nvalidate_list(\n  api.body,\n  {\n      \"key\": \"posts\",\n      \"unit\": \"id\",\n      \"sort\": \"ascending\"\n  }\n)\n            \u003c/pre\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e\n            \u003cpre\u003e\nvalidate_list(\n  api.body,\n  {\n      \"key\": \"posts\",\n      \"unit\": \"id\",\n      \"sort\": \"descending\"\n  }\n)\n            \u003c/pre\u003e\n        \u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\n#### JSON response headers validation\n\n\u003e key benefits\n- validates any response headers\n\n\u003ctable\u003e\n    \u003ctr\u003e\n        \u003cth\u003e\n            General Syntax\n        \u003c/th\u003e\n        \u003cth\u003e\n            Syntax | Model 2\n        \u003c/th\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n            \u003cpre\u003e\nvalidate_headers(\n    api.response_headers,\n    {\n       key: '',\n       operator: '',\n       value: ''\n    }\n)\n            \u003c/pre\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e\n            \u003cpre\u003e\nvalidate_headers(\n    api.response_headers,\n    {\n       key: \"connection\",\n       operator: \"!=\",\n       value: \"open\"\n    },{\n       key: \"vary\",\n       operator: \"==\",\n       value: \"Origin, Accept-Encoding\"\n    }\n)\n            \u003c/pre\u003e\n        \u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\n## #General usage\n\nUsing `json` template as body\n```ruby\nit \"JSON template as body\" do\n  api.post('/api/users', payload(\"./data/request/post.json\"))\n  expect(api.status).to eq(201)\nend\n```\nAdd custom header\n```ruby\nit \"GET request with custom header\" do\n  api.get('/api/users', {'Content-Type' =\u003e 'application/json', 'Accept' =\u003e 'application/json'})\n  expect(api.status).to eq(200)\nend\n\nit \"PATCH request with custom header\" do\n  api.patch('/api/users/2', {\"data\":{\"email\":\"prashanth@mail.com\",\"first_name\":\"Prashanth\",\"last_name\":\"Sams\"}}, {'Content-Type' =\u003e 'application/json', 'Accept' =\u003e 'application/json'})\n  expect(api.status).to eq(200)\nend\n```\nFull url support\n```ruby\nit \"full url\", :post do\n  api.post('https://api.enterprise.apigee.com/v1/organizations/ahamilton-eval',{},{'Authorization' =\u003e 'Basic YWhhbWlsdG9uQGFwaWdlZS5jb206bXlwYXNzdzByZAo'})\n  expect(api.status).to eq(403)\nend\n```\nBasic Authentication \n```ruby\nClientApi.configure do |config|\n  ...\n  config.basic_auth = {'Username' =\u003e 'ahamilton@apigee.com', 'Password' =\u003e 'myp@ssw0rd'}\nend\n```\nCustom Timeout in secs \n```ruby\nClientApi.configure do |config|\n  ...\n  config.time_out = 10 # in secs\nend\n```\nOutput as `json` template \n```ruby\nClientApi.configure do |config|\n  ...\n  config.json_output = {'Dirname' =\u003e './output', 'Filename' =\u003e 'sample'}\nend\n```\n\u003cimg src=\"https://i.imgur.com/tQ46LgF.png\" height=\"230\" width=\"750\"\u003e\n\n## Logs\n\u003e Logs are optional in this library; you can do so through config in `spec_helper.rb`. The param,`StoreFilesCount` will keep the custom files as logs; you can remove it, if not needed.\n\n```ruby\nClientApi.configure do |config|\n  ...\n  config.logger = {'Dirname' =\u003e './logs', 'Filename' =\u003e 'test', 'StoreFilesCount' =\u003e 5}\n  \n  config.before(:each) do |scenario|\n    ClientApi::Request.new(scenario)\n  end\nend\n``` \n\n\u003cimg src=\"https://i.imgur.com/6k5lLrD.png\" height=\"165\" width=\"750\"\u003e\n\n## #Validation | more info.\n\n\u003e Single key-pair value JSON response validator\n\nValidates JSON response `value`, `datatype`, `size`, `is value empty?`, and `key exist?` \n```ruby\nvalidate(\n    api.body,\n    {\n        \"key\": \"name\",\n        \"value\": \"prashanth sams\",\n        \"operator\": \"==\",\n        \"type\": 'string'\n    }\n)\n``` \n\u003e Multi key-pair values response validator\n\nValidates more than one key-pair values\n```ruby\nvalidate(\n    api.body,\n    {\n        \"key\": \"name\",\n        \"value\": \"prashanth sams\",\n        \"type\": 'string'\n    },\n    {\n        \"key\": \"event\",\n        \"operator\": \"eql?\",\n        \"type\": 'boolean'\n    },\n    {\n         \"key\": \"posts-\u003e1-\u003eenabled\",\n         \"value\": false,\n         \"operator\": \"!=\",\n         \"type\": 'boolean'\n    },\n    {\n        \"key\": \"profile-\u003ename-\u003eid\",\n        \"value\": 2,\n        \"operator\": \"==\",\n        \"type\": 'integer'\n    },\n    {\n        \"key\": \"profile-\u003ename-\u003eid\",\n        \"value\": 2,\n        \"operator\": \"\u003c\",\n        \"type\": 'integer'\n    },\n    {\n        \"key\": \"profile-\u003ename-\u003eid\",\n        \"operator\": \"\u003e=\",\n        \"value\": 2,\n    },\n    {\n        \"key\": \"post1-\u003e0-\u003ename\",\n        \"operator\": \"contains\",\n        \"value\": \"Sams\"\n    },\n    {\n        \"key\": \"post2-\u003e0-\u003eid\",\n        \"operator\": \"include\",\n        \"value\": 34,\n        \"type\": 'integer'\n    },\n    {\n        \"key\": \"post1-\u003e0-\u003eavailable\",\n        \"value\": true,\n        \"operator\": \"not contains\",\n        \"type\": \"boolean\"\n    }\n)\n```\n\u003e JSON response size validator\n\nValidates the total size of the JSON array\n```ruby\nvalidate(\n    api.body,\n    {\n        \"key\": \"name\",\n        \"size\": 2\n    },\n    {\n        \"key\": \"name\",\n        \"operator\": \"==\",\n        \"value\": \"Sams\",\n        \"type\": \"string\",\n        \"has_key\": true,\n        \"empty\": false,\n        \"size\": 2\n    }\n)\n```\n\u003e JSON response value empty? validator\n\nValidates if the key has empty value or not\n```ruby\nvalidate(\n    api.body,\n    {\n        \"key\": \"0-\u003ename\",\n        \"empty\": false\n    },\n    {\n        \"key\": \"name\",\n        \"operator\": \"==\",\n        \"value\": \"Sams\",\n        \"type\": \"string\",\n        \"size\": 2,\n        \"has_key\": true,\n        \"empty\": false\n    }\n)\n```\n\u003e JSON response has specific key? validator\n\nValidates if the key exist or not\n```ruby\nvalidate(\n    api.body,\n    {\n        \"key\": \"0-\u003ename\",\n        \"has_key\": true\n    },\n    {\n        \"key\": \"name\",\n        \"operator\": \"==\",\n        \"value\": \"\",\n        \"type\": \"string\",\n        \"size\": 2,\n        \"empty\": true,\n        \"has_key\": true\n    }\n)\n```\n\n###### Operator\n| Type  |  options |\n| ---      | ---         |\n| Equal | `=`, `==`, `eql`, `eql?`, `equal`, `equal?`         |\n| Not Equal | `!`, `!=`, `!eql`, `!eql?`, `not eql`, `not equal`, `!equal?`         |\n| Greater than | `\u003e`, `\u003e=`, `greater than`, `greater than or equal to`         |\n| Less than | `\u003c`, `\u003c=`, `less than`, `less than or equal to`, `lesser than`, `lesser than or equal to`         |\n| Contains | `contains`, `has`, `contains?`, `has?`, `include`, `include?`         |\n| Not Contains | `not contains`, `!contains`, `not include`, `!include`         |\n\n###### Datatype\n| Type  |  options |\n| ---      | ---         |\n| String | `string`, `str`         |\n| Integer | `integer`, `int`         |\n| Symbol | `symbol`, `sym`         |\n| Boolean | `boolean`, `bool`         |\n| Array | `array`, `arr`         |\n| Object | `object`, `obj`         |\n| Float | `float`         |\n| Hash | `hash`         |\n| Complex | `complex`         |\n| Rational | `rational`         |\n| Fixnum | `fixnum`         |\n| Falseclass | `falseclass`, `false`         |\n| Trueclass | `trueclass`, `true`         |\n| Bignum | `bignum`         |\n\n#### JSON response schema validation\n```ruby\nvalidate_schema(\n  schema_from_json('./data/schema/get_user_schema.json'),\n  {\n    \"data\":\n        {\n            \"id\": 2,\n            \"email\": \"janet.weaver@reqres.in\",\n            \"firstd_name\": \"Janet\",\n            \"last_name\": \"Weaver\",\n            \"avatar\": \"https://s3.amazonaws.com/uifaces/faces/twitter/josephstein/128.jpg\"\n        }\n  }\n)\n```\n```ruby\nvalidate_schema(\n    {\n        \"required\": [\n            \"data\"\n        ],\n        \"type\": \"object\",\n        \"properties\": {\n            \"data\": {\n                \"type\": \"object\",\n                \"required\": [\n                    \"id\", \"email\", \"first_name\", \"last_name\", \"avatar\"\n                ],\n                \"properties\": {\n                    \"id\": {\n                        \"type\": \"integer\"\n                    },\n                    \"email\": {\n                        \"type\": \"string\"\n                    },\n                    \"first_name\": {\n                        \"type\": \"string\"\n                    },\n                    \"last_name\": {\n                        \"type\": \"string\"\n                    },\n                    \"avatar\": {\n                        \"type\": \"string\"\n                    }\n                }\n            }\n        }\n    },\n  {\n    \"data\":\n        {\n            \"id\": 2,\n            \"email\": \"janet.weaver@reqres.in\",\n            \"first_name\": \"Janet\",\n            \"last_name\": \"Weaver\",\n            \"avatar\": \"https://s3.amazonaws.com/uifaces/faces/twitter/josephstein/128.jpg\"\n        }\n  }\n)\n```\n```ruby\nvalidate_schema(\n    schema_from_json('./data/schema/get_user_schema.json'),\n    api.body\n)\n```\n\n#### JSON response content validation\n\u003e json response content value validation as a structure\n```ruby\nactual_body = {\n    \"posts\":\n        {\n            \"prashanth\": {\n                \"id\": 1,\n                \"title\": \"Post 1\"\n            },\n            \"sams\": {\n                \"id\": 2,\n                \"title\": \"Post 2\"\n            }\n        },\n    \"profile\":\n        {\n            \"id\": 44,\n            \"title\": \"Post 44\"\n        }\n}\n\nvalidate_json( actual_body,\n{\n    \"posts\":\n        {\n            \"prashanth\": {\n                \"id\": 1,\n                \"title\": \"Post 1\"\n            },\n            \"sams\": {\n                \"id\": 2\n            }\n        },\n    \"profile\":\n        {\n            \"title\": \"Post 44\"\n        }\n})\n```\n```ruby\nvalidate_json( api.body,\n  {\n      \"posts\": [\n          {\n              \"id\": 2,\n              \"title\": \"Post 2\"\n          }\n      ],\n      \"profile\": {\n          \"name\": \"typicode\"\n      }\n  }\n)\n```\n\n#### Response headers validation\n```ruby\nvalidate_headers(\n  api.response_headers,\n  {\n    key: \"connection\",\n    operator: \"!=\",\n    value: \"open\"\n  },\n  {\n    key: \"vary\",\n    operator: \"==\",\n    value: \"Origin, Accept-Encoding\"\n  }\n)\n```\n\n#### Is there a demo available for this gem?\nYes, you can use this demo as an example, https://github.com/prashanth-sams/client-api\n```\nrake spec\n```","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprashanth-sams%2Fclient-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprashanth-sams%2Fclient-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprashanth-sams%2Fclient-api/lists"}