{"id":15664601,"url":"https://github.com/marioruiz/nice_http","last_synced_at":"2025-04-28T16:04:33.718Z","repository":{"id":54316150,"uuid":"161800009","full_name":"MarioRuiz/nice_http","owner":"MarioRuiz","description":"NiceHttp -- simplest library for accessing and testing HTTP and REST resources. Get http logs and statistics automatically. Use hashes on your requests. Access JSON even easier.","archived":false,"fork":false,"pushed_at":"2024-03-20T15:20:09.000Z","size":316,"stargazers_count":17,"open_issues_count":2,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-28T16:04:26.232Z","etag":null,"topics":["client","hash","http","json","rest","ruby"],"latest_commit_sha":null,"homepage":"","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/MarioRuiz.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}},"created_at":"2018-12-14T15:00:46.000Z","updated_at":"2024-12-11T16:17:27.000Z","dependencies_parsed_at":"2023-02-16T00:05:38.514Z","dependency_job_id":null,"html_url":"https://github.com/MarioRuiz/nice_http","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MarioRuiz%2Fnice_http","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MarioRuiz%2Fnice_http/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MarioRuiz%2Fnice_http/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MarioRuiz%2Fnice_http/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MarioRuiz","download_url":"https://codeload.github.com/MarioRuiz/nice_http/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251342722,"owners_count":21574244,"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":["client","hash","http","json","rest","ruby"],"created_at":"2024-10-03T13:43:29.430Z","updated_at":"2025-04-28T16:04:33.681Z","avatar_url":"https://github.com/MarioRuiz.png","language":"Ruby","readme":"# NiceHttp\n\n[![Gem Version](https://badge.fury.io/rb/nice_http.svg)](https://rubygems.org/gems/nice_http)\n[![Build Status](https://travis-ci.com/MarioRuiz/nice_http.svg?branch=master)](https://github.com/MarioRuiz/nice_http)\n[![Coverage Status](https://coveralls.io/repos/github/MarioRuiz/nice_http/badge.svg?branch=master)](https://coveralls.io/github/MarioRuiz/nice_http?branch=master)\n![Gem](https://img.shields.io/gem/dt/nice_http)\n![GitHub commit activity](https://img.shields.io/github/commit-activity/y/MarioRuiz/nice_http)\n![GitHub last commit](https://img.shields.io/github/last-commit/MarioRuiz/nice_http)\n![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/MarioRuiz/nice_http)\n\nNiceHttp the simplest library for accessing and testing HTTP and REST resources.\n\nManage different hosts on the fly. Easily get the value you want from the JSON strings. Use hashes on your requests. Get automatically statistics of your http communication and all the logs with the requests and responses.\n\nAlso you can use mock responses by using :mock_response key on the request hash and enable the use_mocks option on NiceHttp.\n\nNiceHttp will take care of the redirections and the cookies, and for security tests you will be able to modify the cookies or disable and control the redirections by yourself.\n\nNiceHttp is able to use hashes as requests data and uses the Request Hash structure: https://github.com/MarioRuiz/Request-Hash\n\n**On the next link you have a full example using nice_http and RSpec to test REST APIs, Uber API and Reqres API: https://github.com/MarioRuiz/api-testing-example**\n\nTo be able to generate random requests take a look at the documentation for nice_hash gem: https://github.com/MarioRuiz/nice_hash\n\nExample that creates 1000 good random and unique requests to register an user and test that the validation of the fields are correct by the user was able to be registered. Send 800 requests where just one field is wrong and verify the user was not able to be created: https://gist.github.com/MarioRuiz/824d7a462b62fd85f02c1a09455deefb\n\n# Table of Contents\n\n- [Installation](#Installation)\n- [A very simple first example](#A-very-simple-first-example)\n- [Create a connection](#Create-a-connection)\n- [Creating requests](#Creating-requests)\n- [Responses](#Responses)\n    - [Async Responses](#Async-Responses)\n- [Special settings](#Special-settings)\n- [Authentication requests](#Authentication-requests)\n    - [Basic Authentication](#Basic-Authentication)\n    - [OpenID](#OpenID)\n    - [OAuth2](#OAuth2)\n    - [JWT Token](#JWT-Token)\n    - [lambda on headers](#lambda-on-headers)\n- [Http logs](#Http-logs)\n    - [Multithreading](#Multithreading)\n- [Http stats](#Http-stats)\n- [Tips](#Tips)\n    - [Download a file](#Download-a-file)\n    - [Send multipart content](#Send-multipart-content)\n    - [Send x-www-form-urlencoded](#Send-x-www-form-urlencoded)\n- [Contributing](#Contributing)\n- [License](#License)\n\n## Installation\n\nInstall it yourself as:\n\n    $ gem install nice_http\n\n\n## A very simple first example\n\n```ruby\nrequire 'nice_http'\n\nhttp = NiceHttp.new('https://reqres.in')\n\nresp = http.get(\"/api/users?page=2\")\n\npp resp.code\npp resp.data.json\n\nresp = http.get(\"/api/users/2\")\n\npp resp.data.json(:first_name, :last_name)\n\nresp = http.post( {\n    path: \"/api/users\",\n    data: { name: \"morpheus\", job: \"leader\" } \n} )\n\npp resp.data.json\n```\n\n## Create a connection\n\nThe simplest way is just by supplying the value as an argument:\n\n```ruby\n\n# as an url\nhttp1 = NiceHttp.new(\"https://example.com\")\n\n# as parameters\nhttp2 = NiceHttp.new( host: \"reqres.in\", port: 443, ssl: true )\n\n# as a hash\nhttp3 = NiceHttp.new my_reqres_server\n\n\n```\n\n\nYou can specify all the defaults you will be using when creating connections by using the NiceHttp methods, in this example, http1 and http2 will be connecting to reqres.in with the default parameters and http3 to example.com:\n\n```ruby\n\n# default parameters\nNiceHttp.host = 'reqres.in'\nNiceHttp.ssl = true\nNiceHttp.port = 443\nNiceHttp.debug = false\nNiceHttp.log = \"./my_logs.log\"\nNiceHttp.headers = {\"api-key\": \"the api key\"}\nNiceHttp.values_for = { region: 'europe', customerId: 334 }\n\nhttp1 = NiceHttp.new()\n\nhttp2 = NiceHttp.new()\n\nhttp3 = NiceHttp.new(\"https://example.com\")\n\n```\n\nIf you prefer to supply a hash to change the default settings for NiceHttp:\n\n```ruby\nNiceHttp.defaults = {\n    host: 'reqres.in',\n    ssl: true,\n    port: 443,\n    timeout: 15, #seconds\n    debug: false,\n    log: \"./my_logs.log\",\n    headers: {\"api-key\": \"the api key\"}\n}\n```\n\nTo add a fixed path that would be added automatically to all your requests just before the specified request path, you can do it by adding it to `host`:\n\n```ruby\nhttp = NiceHttp.new('https://v2.namsor.com/NamSorAPIv2/')\n\nresp = http.get('/api2/json/gender/Peter/Moon')\n# The get request path will be: /NamSorAPIv2/api2/json/gender/Peter/Moon on server v2.namsor.com\n\nresp = http.get('/api2/json/gender/Love/Sun?ret=true')\n# The get request path will be: /NamSorAPIv2/api2/json/gender/Love/Sun on server v2.namsor.com\n```\n\n## Creating requests\n\nYou can use hash requests to simplify the management of your requests, for example creating a file specifying all the requests for your Customers API.\n\nThe keys you can use:\n\n*path*: relative or absolute path, for example: \"/api2/customers/update.do\"\n\n*headers*: specific headers for the request. It will include a hash with the values.\n\n*data*: the data to be sent for example a JSON string. In case of supplying a Hash, Nice Http will assume that is a JSON and will convert it to a JSON string before sending the request and will add to the headers: 'Content-Type': 'application/json'\n\n*mock_response*: In case of use_mocks=true then NiceHttp will return this response\n\n\nLet's guess you have a file with this data for your requests on */requests/example.rb*:\n\n```ruby\n\nmodule Requests\n\n  module Example\n    \n    # simple get request example\n    def self.list_of_users()\n        {\n            path: \"/api/users?page=2\"\n        }\n    end\n\n    # post request example using a request hash that will be converted automatically to a json string\n    def self.create_user_hash()\n        {\n            path: \"/api/users\",\n            data: { \n                name: \"morpheus\",\n                job: \"leader\"\n                }\n        }\n    end\n\n    # post request example using a JSON string\n    def self.create_user_raw()\n        {\n            path: \"/api/users\",\n            headers: {\"Content-Type\": \"application/json\"},\n            data: '{\"name\": \"morpheus\",\"job\": \"leader\"}'\n        }\n    end\n\n  end\n\nend\n\n```\n\n\nThen in your code you can require this request file and use it like this:\n\n```ruby\n\nresp = http.get Requests::Example.list_of_users \n\npp resp.code\n\nresp = http.post Requests::Example.create_user_hash\n\npp resp.data.json\n\n\nresp = http.post Requests::Example.create_user_raw\n\npp resp.data.json(:job)\n\n\n```\n\n\nIn case you want to modify the request before sending it, for example just changing one field but the rest will be the same, you can supply a new key :values_for in the request hash that will contain a hash with the keys to be changed and NiceHttp will perform the necessary changes at any level:\n\n```ruby\n\nreq = Requests::Example.create_user_hash\nreq.values_for = {job: \"developer\"}\n\nresp = http.post req\n\npp resp.data.json\n#response: {:name=\u003e\"morpheus\", :job=\u003e\"developer\", :id=\u003e\"192\", :createdAt=\u003e\"2018-12-14T14:41:54.371Z\"}\n\n```\n\nIf the request hash contains a key :method with one of these possible values: :get, :head, :delete, :post or :patch, then it is possible to use the `send_request` method and pass just the request hash:\n\n```ruby\n     req= {\n            path: \"/api/users\",\n            method: :post,\n            data: { \n                name: \"morpheus\",\n                job: \"leader\"\n            }\n          }\n     resp = @http.send_request req\n```\n\nYou can always access to the last request as a Hash object by: `NiceHttp.request`\n\nIf you want to change the value of all headers using the value of the request on runtime, use `lambda`, `NiceHttp.requests` and `NiceHttp.request`:\n\n```ruby\nNiceHttp.requests = {\n  headers: {\n    Referer: lambda { \"http://myserver.com\" + NiceHttp.request.path }\n  }\n}\n```\n\nYou can use `NiceHttp.requests` to specify certain `headers`, `path` parameters or `data` or `values_for` that will apply on all requests sent.\n```ruby\nNiceHttp.requests = {\n  path: 'api-version=2022-12-09\u0026testing=true',\n  data: {\n    properties: {\n      language: 'eng-us'\n    }\n  }\n}\n```\n\nLambdas can be used also on data and values_for to change the payloads in real-time. In case the lambda returns 'nil' the key won't be added to the request.  \n```ruby\nNiceHttp.requests = {\n    data: {\n      zones: lambda { ENV['ZONES'] if NiceHttp.request[:method] == 'PUT' and NiceHttp.request[:path].match?(/^\\/api\\/users\\/\\d+/)}\n    },\n    values_for: {\n      region: lambda { 'Europe' if NiceHttp.request[:name] == 'Users.add' }\n    }\n  }\n```\n\n## Responses\n\nThe response will include at least the keys:\n\n*code*: the http code response, for example: 200\n\n*message*: the http message response, for example: \"OK\"\n\n*data*: the data response structure. In case of json we can get it as a hash by using: `resp.data.json`. Also you can filter the json structure and get what you want: `resp.data.json(:loginname, :address)`\n\nAlso interesting keys would be: *time_elapsed_total*, *time_elapsed* and many more available  \n\n### Async responses\n\nIn case a 202 response and set the async settings, it will wait until the operation finishes and will return the result:\n\n```ruby\nNiceHttp.async_wait_seconds = 10\nNiceHttp.async_header = 'location'\nNiceHttp.async_completed = 'percComplete'\nNiceHttp.async_resource = 'resourceName'\nNiceHttp.async_status = 'status'\n\nhttp = NiceHttp.new('https://exampleSinatra.tcblues.repl.co')\n\nresponse = http.get '/async'\npp response # =\u003e\n{ :code=\u003e\"202\",\n  :message=\u003e\"Accepted\",\n  :location=\u003e\"https://exampleSinatra.tcblues.repl.co/operation/667\",\n  :data=\u003e\"{\\\"result\\\":\\\"this is an async operation id: 667\\\"}\",\n  :async=\u003e\n    { :seconds=\u003e4,\n      :data=\u003e\n        \"{'percComplete':100,'resourceName':'/resource/766','status':'Done','operationId':'667'}\",\n      :status=\u003e\"Done\",\n      :resource=\u003e{:data=\u003e\"{'resourceId':'766','lolo':'lala'}\"}\n    }\n  # plus other keys\n}\n\np response.code # 202\np response.location # \"https://exampleSinatra.tcblues.repl.co/operation/667\"\np response.data.json # {:result=\u003e\"this is an async operation id: 667\"} \np response.async.data.json # {:percComplete=\u003e100, :resourceName=\u003e\"/resource/766\", :status=\u003e\"Done\",:operationId=\u003e667}\np response.async.status # Done\np response.async.seconds # 4\np response.async.resource.data.json # {:resourceId=\u003e\"766\", :lolo=\u003e\"lala\"}\n```\n\n\n## Special settings\n\n*debug*: (true or false) it will set the connecition on debug mode so you will be able to see the whole communication with the server in detail\n\n*log*: (:no, :screen, :file, :file_run, :fix_file, \"filename\") it will log the basic communication for inspect. In case you want to add extra info to your logs you can do it for example adding to your code: http.logger.info \"example extra log\"\n\n*headers*: Hash containing the headers for the communication\n\n*cookies*: Hash containing the cookies for the communication\n\n*proxy_port, proxy_host*: in case you want to use a proxy for the connection\n\n*use_mocks*: (true or false) in case of true if the request hash contains a mock_response key it will be returning that response instead of trying to send the request.\n\n*auto_redirect*: (true or false) in case of true it will take care of the auto redirections.\n\n*timeout*: Integer that will set a time out for the time waiting to connect to a host or waiting for a response.\n\n## Authentication requests\n\nAll we need to do is to add to our request the correct authentication tokens, seeds, headers.\n\n### Basic Authentication\n\nFor example for Basic Authentication we need to add to the authorization header a seed generated with the user and password we want ot authenticate\n\n```ruby\n\n@http = NiceHttp.new(\"https://jigsaw.w3.org/\")\n\n@http.headers.authorization = NiceHttpUtils.basic_authentication(user: \"guest\", password: \"guest\")\n\n# headers will be in this example: {:authorization=\u003e\"Basic Z3Vlc3Q6Z3Vlc3Q=\\n\"}\n\nresp = @http.get(\"/HTTP/Basic/\")\n\n```\n\nIn case you want to use strict base64 use the option `strict: true`\n\nRemember for other kind of authentication systems NiceHttp take care of the redirections and cookies that are requested to be set. In case you need to add a header with a token you can add it by using your NiceHttp object and the key headers, for example:\n\n```ruby\n@http.headers.tokenuno = \"xxx\"\n# headers =\u003e {tokenuno: \"xxx\"}\n\n#another way:\n@http.headers[:tokendos] = \"yyy\"\n# headers =\u003e {tokenuno: \"xxx\", tokendos: \"yyyy\"}\n\n```\n\nIn case you want or need to control the redirections by yourself instead of allowing NiceHttp to do it, then set ```@http.auto_redirect = false```\n\n### OpenID\n\nAn example using OpenID authentication:\n\n```ruby\nserver = \"https://samples.auth0.com/\"\npath=\"/authorize?client_id=kbyuFDidLLm280LIwVFiazOqjO3ty8KH\u0026response_type=code\"\n\n@http = NiceHttp.new(server)\n\nresp = @http.get(path)\n\np \"With autoredirection:\"\np \"Cookies: \"\np @http.cookies\np \"Code: #{resp.code} #{resp.message} \"\np \"*\"*40\n\n@http2 = NiceHttp.new(server)\n@http2.auto_redirect = false\n\nresp = @http2.get(path)\n\np \"Without autoredirection:\"\np \"Cookies: \"\np @http2.cookies\np \"Code: #{resp.code} #{resp.message} \"\n\n```\n\nThe output:\n\n```\n\"With autoredirection:\"\n\"Cookies: \"\n{\"/\"=\u003e{\"auth0\"=\u003e\"s%3A6vEEwmmIf-9YAG-NjvsOIyZAh-NS97jj.yFSXILdmCov6DRwXjEei3q3eHIrxZxHI4eg4%2BTpUaK4\"}, \n       \"/usernamepassword/login\"=\u003e{\"_csrf\"=\u003e\"bboZ0koMScwXkISzWaAMTYdY\"}}\n\"Code: 200 OK \"\n\"****************************************\"\n\"Without autoredirection:\"\n\"Cookies: \"\n{\"/\"=\u003e{\"auth0\"=\u003e\"s%3AcKndc44gllWyJv8FLztUIctuH4b__g0V.QEF3SOobK8%2FvX89iUKzGbfSP4Vt2bRtY2WH7ygBUkg4\"}}\n\"Code: 302 Found \"\n\n```\n\n### OAuth2\n\nYou can see on the next link how to get the OAuth2 token for Microsoft Azure and add it to your Http connection header. \n\nhttps://gist.github.com/MarioRuiz/d3525185024737885c0c9afa6dc8b9e5\n\n### JWT token\n\nAn example for Google using JWT\n\nmy_json_key_file.json:\n```json\n{\n  \"type\": \"service_account\",\n  \"project_id\": \"example\",\n  \"private_key_id\": \"fjdslkafldkasfadsjflkjdsaklfjasdklfjlkdsjfl\",\n  \"private_key\": \"-----BEGIN PRIVATE KEY-----....==\\n-----END PRIVATE KEY-----\\n\",\n  \"client_email\": \"example@example.iam.gserviceaccount.com\",\n  \"client_id\": \"46545646\",\n  \"auth_uri\": \"https://accounts.google.com/o/oauth2/auth\",\n  \"token_uri\": \"https://oauth2.googleapis.com/token\",\n  \"auth_provider_x509_cert_url\": \"https://www.googleapis.com/oauth2/v1/certs\",\n  \"client_x509_cert_url\": \"https://www.googleapis.com/robot/v1/metadata/x509/example%40example.iam.gserviceaccount.com\"\n}\n```\n\n```ruby\n    require 'jwt'\n    require 'nice_hash'\n    def generate_jwt(audience, json_key_file)\n      json = File.open(json_key_file).read.json\n      now = Time.new\n      payload = {\n        iss: json.client_email,\n        sub: json.client_email,\n        aud: audience,\n        exp: (now + 3600).to_i,\n        iat: (now - 60).to_i,\n        kid: json.private_key_id\n      }\n      jwt_token = JWT.encode payload, OpenSSL::PKey::RSA.new(json.private_key), \"RS256\"\n      return jwt_token\n    end\n\n    NiceHttp.headers = {\n      Authorization: lambda { \"Bearer \" + generate_jwt('https:/myhost.com', './my_json_key_file.json') }\n    }\n\n```\n\n### lambda on headers\n\nIf you need a new token every time a new http connection is created you can use `lambda`\n\n```ruby\nNiceHttp.headers[:Authorization] = lambda {get_token()}\n```\n\nNiceHttp will call the get_token method you created every time a new connection is created.\n\n## Http logs\n\nYou can set where the http logs will be stored by using the log attribute of the NiceHttp. \nBy default they will be stored in your root directory with the name nice_http.log.\n```ruby\n    # you can specify the default for all connections\n    NiceHttp.log = :file_run\n\n    # also you can specify for a concrete connection\n    http = NiceHttp.new({host: 'www.example.com', log: './example.log'})\n```\n\nOther values you can supply:\n* :fix_file, will log the communication on nice_http.log. (default).\n* :no, won't generate any logs.\n* :screen, will print the logs on the screen.\n* :file, will be generated a log file with name: nice_http_YY-mm-dd-HHMMSS.log.\n* :file_run, will generate a log file with the name where the object was created and extension .log, fex: myfile.rb.log\n* String, the path and file name where the logs will be stored.\n\nIn case you want to hide the header values from the requests on the logs use the option `log_headers`. Possible values:\n* :all, (default), will log all header values.\n* :none, won't log any value of the headers.\n* :partial, will log only the last 10 characters of the header values.\n\nExample of logs:\n```\nI, [2019-03-22T18:38:58.518964 #29412]  INFO -- : (47266856647720): Http connection created. host:reqres.in,  port:443,  ssl:true, mode:, proxy_host: , proxy_port:  \nI, [2019-03-22T18:38:58.537106 #29412]  INFO -- : (47266856647720): Http connection: https://reqres.in:443\n\n\n- - - - - - - - - - - - - - - - - - - - - - - - - \nPOST Request: Doom.example\n path: /api/users\n headers: {Loop:44, Cookie:, Boom:33, Content-Type:application/json, }\n data: {\n  \"name\": \"peter\",\n  \"job\": \"leader\",\n  \"products\": [\n    {\n      \"one\": \"uno\",\n      \"two\": 2\n    },\n    {\n      \"one\": \"uno\",\n      \"two\": 22\n    }\n  ]\n}\n\nI, [2019-03-22T18:38:58.873935 #29412]  INFO -- : \nRESPONSE: \n 201:Created\n time_elapsed_total: '0.335720719'\n time_elapsed: '0.335728095'\n date: 'Fri, 22 Mar 2019 18:38:58 GMT'\n content-type: 'application/json; charset=utf-8'\n content-length: '172'\n connection: 'keep-alive'\n set-cookie: '__cfduid=dfb962e62cd8386ce4ab9bad601611553272738; expires=Sat, 21-Mar-20 18:38:58 GMT; path=/; domain=.reqres.in; HttpOnly'\n x-powered-by: 'Express'\n access-control-allow-origin: '*'\n etag: 'W/\"ac-EMh4XBmK5vry/OeKaGWILGtmHU0\"'\n expect-ct: 'max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"'\n server: 'cloudflare'\n cf-ray: '4bb99958090dbf89-AMS'\n data: '{\n  \"name\": \"peter\",\n  \"job\": \"leader\",\n  \"products\": [\n    {\n      \"one\": \"uno\",\n      \"two\": 2\n    },\n    {\n      \"one\": \"uno\",\n      \"two\": 22\n    }\n  ],\n  \"id\": \"628\",\n  \"createdAt\": \"2019-03-22T18:43:33.619Z\"\n}'\n\nI, [2019-03-22T18:38:58.874190 #29412]  INFO -- : set-cookie added to Cookie header as required\nI, [2019-03-22T18:38:59.075293 #29412]  INFO -- : \n\n- - - - - - - - - - - - - - - - - - - - - - - - - \nGET Request: Doom.example\n path: /api/users\n Same headers and data as in the previous request.\nI, [2019-03-22T18:38:59.403459 #29412]  INFO -- : \nRESPONSE: \n 200:OK\n time_elapsed_total: '0.327002338'\n time_elapsed: '0.327004766'\n date: 'Fri, 22 Mar 2019 18:38:59 GMT'\n content-type: 'application/json; charset=utf-8'\n transfer-encoding: 'chunked'\n connection: 'keep-alive'\n x-powered-by: 'Express'\n access-control-allow-origin: '*'\n etag: 'W/\"1bb-D+c3sZ5g5u/nmLPQRl1uVo2heAo\"'\n expect-ct: 'max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"'\n server: 'cloudflare'\n cf-ray: '4bb9995b5c20bf89-AMS'\n data: '{\n  \"page\": 1,\n  \"per_page\": 3,\n  \"total\": 12,\n  \"total_pages\": 4,\n  \"data\": [\n    {\n      \"id\": 1,\n      \"first_name\": \"George\",\n      \"last_name\": \"Bluth\",\n      \"avatar\": \"https://s3.amazonaws.com/uifaces/faces/twitter/calebogden/128.jpg\"\n    },\n    {\n      \"id\": 2,\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```\n\nIf you want to get the last request sent or the last response as a message use `NiceHttp.last_request` or `NiceHttp.last_response`. If you want to access the last request as a Hash use `NiceHttp.request`\n\nAlso you can collect all data sent and received by setting `NiceHttp.capture = true` and all data will be stored on `NiceHttp.captured` as an Array of Strings (Request+Response).\n\n### Multithreading\n\nIn case you want to use multithread and log in different files every thread, add an unique name for the thread then the logs will be stored accordingly\n\n```ruby\nrequire 'nice_http'\n\nthreads = []\n\n40.times do |num|\n    threads \u003c\u003c Thread.new do\n        Thread.current.name = num.to_s\n        http = NiceHttp.new(\"https://reqres.in\")\n        request = {\n          path: '/api/users',\n          data: { name: 'morpheus', job: 'leader' },\n        }\n        http.post(request)\n    end\nend\n\nthreads.each(\u0026:join)\n\n# log files: nice_http_0.log, nice_http_1.log... nice_http_39.log\n```\n\n## Http stats\n\nIf you want to get a summarize stats of your http communication you need to set `NiceHttp.create_stats = true` \n\nThen whenever you want to access the stats: `NiceHttp.stats` and if you want to save it on a file: `NiceHttp.save_stats`\n\nAfter the run is finished the stats will automatically be saved even if you didn't call `save_stats`. The stats files will use the name and path on `NiceHttp.log`.\n\nIf you are using RSpec and you want to generate the stats files after every test is finished, add to your spec_helper.rb file:\n\n```ruby\nRSpec.configure do |config|\n  config.after(:each) do\n    NiceHttp.save_stats\n  end\nend\n```\n\nThis is an example of the output:\n\n```yaml\n---\nreqres.in:443:\n  :num_requests: 11\n  :time_elapsed:\n    :total: 2.947269038\n    :maximum: 0.357101109\n    :minimum: 0.198707111\n    :average: 0.2679335489090909\n  \"/api/users\":\n    :num_requests: 11\n    :time_elapsed:\n      :total: 2.947269038\n      :maximum: 0.357101109\n      :minimum: 0.198707111\n      :average: 0.2679335489090909\n    :method:\n      POST:\n        :num_requests: 8\n        :time_elapsed:\n          :total: 2.3342455970000002\n          :maximum: 0.357101109\n          :minimum: 0.198707111\n          :average: 0.29178069962500003\n        :response:\n          '201':\n            :num_requests: 8\n            :time_elapsed:\n              :total: 2.3342455970000002\n              :maximum: 0.357101109\n              :minimum: 0.198707111\n              :average: 0.29178069962500003\n      GET:\n        :num_requests: 3\n        :time_elapsed:\n          :total: 0.613023441\n          :maximum: 0.210662528\n          :minimum: 0.200197583\n          :average: 0.20434114699999997\n        :response:\n          '200':\n            :num_requests: 3\n            :time_elapsed:\n              :total: 0.613023441\n              :maximum: 0.210662528\n              :minimum: 0.200197583\n              :average: 0.20434114699999997\n```\n\nIf you want to add specific stats for your processes you can use the method `NiceHttp.add_stats`\n\n```ruby\n   # random customer name\n   customer_name = \"10-20:L\".gen\n   started = Time.now\n   @http.send_request Requests::Customer.add_customer(name: customer_name)\n   30.times do\n      resp = @http.get(Requests::Customer.get_customer(name: customer_name))\n      break if resp.code == 200\n      sleep 0.5\n   end\n   NiceHttp.add_stats(:customer, :create, started, Time.now)\n```\n\nTo add the items for every specific stats to be accessed as an array you can add it as the last parameter of `add_stats`\n```ruby\nNiceHttp.add_stats(:customer, :create, started, Time.now, customer_name)\n```\n\nThis will generate an items key that will contain an array of the values you added.\n\n## Tips\n\n### Download a file\n\n* Direct download:\n\n```ruby\nresp = NiceHttp.new(\"https://github.com\").get(\"/MarioRuiz/slack-smart-bot/blob/master/slack-smart-bot.png\", save_data: './tmp/')\n```\n\n* Get the data and store it like you want:\n\n```ruby\nresp = NiceHttp.new(\"https://github.com\").get(\"/MarioRuiz/slack-smart-bot/blob/master/slack-smart-bot.png\")\nFile.open('./slack-smart-bot.png', 'wb') { |fp| fp.write(resp.data) }\n```\n\n### Send multipart content\n\nExample posting a csv file:\n\n```ruby\n\n\trequire 'net/http/post/multipart'\n\trequest = {\n\t\tpath: \"/customer/profile/\",\n\t\theaders: {'Content-Type' =\u003e 'multipart/form-data'},\n\t\tdata: (Net::HTTP::Post::Multipart.new \"/customer/profile/\",\n\t\t  \"file\" =\u003e UploadIO.new(\"./path/to/my/file.csv\", \"text/csv\"))\n\t}\n\tresponse=@http.post(request)\n\n```\n\n### Send x-www-form-urlencoded\n\n``` ruby\n    request = {\n      headers: { 'Content-Type': \"application/x-www-form-urlencoded\"},\n      path: \"/register\",\n      data: {\n        \"firstname\": \"test@example.com\",\n        \"lastname\": \"example\"\n      }\n    }\n```\n\n## Contributing\n\nBug reports are very welcome on GitHub at https://github.com/marioruiz/nice_http.\n\nIf you want to contribute please follow [GitHub Flow](https://docs.github.com/en/get-started/quickstart/github-flow)\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarioruiz%2Fnice_http","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarioruiz%2Fnice_http","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarioruiz%2Fnice_http/lists"}