nice_http 1.7.3 → 1.7.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 37b5d9ced26f699ee29ba13fe96c0dd7b4231cd743f2ccdf8d38773ea1d92562
4
- data.tar.gz: f7231289cc72eefbd01abd5e3b70d6f98c069451540723abc981bb521482d84e
3
+ metadata.gz: 6de8ae66946e8d89269197713e036f6a1345ed1792466373a21e4fc7e51998d5
4
+ data.tar.gz: eb25249ff5b91b7edac40eeec9e47617c9f87960a03144ff7f96a0a734e154c0
5
5
  SHA512:
6
- metadata.gz: 5c1b7ca435cb059e00e19ba6fb644672c70a09055516ee48e7adfe4e02f467379689be1f15099c5b0a78aa0e893044023c6fcb9c9d5930c62948349e7afff0dd
7
- data.tar.gz: ed76814c10803373cd705f0fe9c62e566e8de84e806efe2f23dd5364b7892d4ac6dbec61bed254b1a2d36f461ce9d60ff970d4b63a1dedb0811ed303b4efe6e0
6
+ metadata.gz: 9b9c835ceaacb08a08851068fcc760263e0d4e59b193193e8a29be41afbed0b3169e1e827561433703127281648dcd67ea068b94237fd10725759e049fe69d89
7
+ data.tar.gz: c630d966d6224b11f894dc89b8d8427f4bac43d84000bcdab33970fcf91ecde3e6f4eec0d8b6c32cd0f79d0298b5d3563fbc417df33c3fa44bb7b12e90352201
data/README.md CHANGED
@@ -1,608 +1,608 @@
1
- # NiceHttp
2
-
3
- [![Gem Version](https://badge.fury.io/rb/nice_http.svg)](https://rubygems.org/gems/nice_http)
4
- [![Build Status](https://travis-ci.com/MarioRuiz/nice_http.svg?branch=master)](https://github.com/MarioRuiz/nice_http)
5
- [![Coverage Status](https://coveralls.io/repos/github/MarioRuiz/nice_http/badge.svg?branch=master)](https://coveralls.io/github/MarioRuiz/nice_http?branch=master)
6
- [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FMarioRuiz%2Fnice_http.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2FMarioRuiz%2Fnice_http?ref=badge_shield)
7
-
8
- NiceHttp the simplest library for accessing and testing HTTP and REST resources.
9
-
10
- Manage different hosts on the fly. Easily get the value you want from the JSON strings. Use hashes on your requests.
11
-
12
- Also you can use mock responses by using :mock_response key on the request hash and enable the use_mocks option on NiceHttp.
13
-
14
- NiceHttp 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.
15
-
16
- NiceHttp is able to use hashes as requests data and uses the Request Hash structure: https://github.com/MarioRuiz/Request-Hash
17
-
18
- **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**
19
-
20
- To be able to generate random requests take a look at the documentation for nice_hash gem: https://github.com/MarioRuiz/nice_hash
21
-
22
- Example 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
23
-
24
- ## Installation
25
-
26
- Install it yourself as:
27
-
28
- $ gem install nice_http
29
-
30
-
31
- ## A very simple first example
32
-
33
- ```ruby
34
- require 'nice_http'
35
-
36
- http = NiceHttp.new('https://reqres.in')
37
-
38
- resp = http.get("/api/users?page=2")
39
-
40
- pp resp.code
41
- pp resp.data.json
42
-
43
- resp = http.get("/api/users/2")
44
-
45
- pp resp.data.json(:first_name, :last_name)
46
-
47
- resp = http.post( {
48
- path: "/api/users",
49
- data: { name: "morpheus", job: "leader" }
50
- } )
51
-
52
- pp resp.data.json
53
- ```
54
-
55
- ## Create a connection
56
-
57
- The simplest way is just by supplying the value as an argument:
58
-
59
- ```ruby
60
-
61
- # as an url
62
- http1 = NiceHttp.new("https://example.com")
63
-
64
- # as parameters
65
- http2 = NiceHttp.new( host: "reqres.in", port: 443, ssl: true )
66
-
67
- # as a hash
68
- http3 = NiceHttp.new my_reqres_server
69
-
70
-
71
- ```
72
-
73
-
74
- You 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:
75
-
76
- ```ruby
77
-
78
- # default parameters
79
- NiceHttp.host = 'reqres.in'
80
- NiceHttp.ssl = true
81
- NiceHttp.port = 443
82
- NiceHttp.debug = false
83
- NiceHttp.log = "./my_logs.log"
84
- NiceHttp.headers = {"api-key": "the api key"}
85
- NiceHttp.values_for = { region: 'europe', customerId: 334 }
86
-
87
- http1 = NiceHttp.new()
88
-
89
- http2 = NiceHttp.new()
90
-
91
- http3 = NiceHttp.new("https://example.com")
92
-
93
- ```
94
-
95
- If you prefer to supply a hash to change the default settings for NiceHttp:
96
-
97
- ```ruby
98
- NiceHttp.defaults = {
99
- host: 'reqres.in',
100
- ssl: true,
101
- port: 443,
102
- debug: false,
103
- log: "./my_logs.log",
104
- headers: {"api-key": "the api key"}
105
- }
106
- ```
107
-
108
- To 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`:
109
-
110
- ```ruby
111
- http = NiceHttp.new('https://v2.namsor.com/NamSorAPIv2/')
112
-
113
- resp = http.get('/api2/json/gender/Peter/Moon')
114
- # The get request path will be: /NamSorAPIv2/api2/json/gender/Peter/Moon on server v2.namsor.com
115
-
116
- resp = http.get('/api2/json/gender/Love/Sun?ret=true')
117
- # The get request path will be: /NamSorAPIv2/api2/json/gender/Love/Sun on server v2.namsor.com
118
- ```
119
-
120
- ## Creating requests
121
-
122
- You can use hash requests to simplify the management of your requests, for example creating a file specifying all the requests for your Customers API.
123
-
124
- The keys you can use:
125
-
126
- *path*: relative or absolute path, for example: "/api2/customers/update.do"
127
-
128
- *headers*: specific headers for the request. It will include a hash with the values.
129
-
130
- *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'
131
-
132
- *mock_response*: In case of use_mocks=true then NiceHttp will return this response
133
-
134
-
135
- Let's guess you have a file with this data for your requests on */requests/example.rb*:
136
-
137
- ```ruby
138
-
139
- module Requests
140
-
141
- module Example
142
-
143
- # simple get request example
144
- def self.list_of_users()
145
- {
146
- path: "/api/users?page=2"
147
- }
148
- end
149
-
150
- # post request example using a request hash that will be converted automatically to a json string
151
- def self.create_user_hash()
152
- {
153
- path: "/api/users",
154
- data: {
155
- name: "morpheus",
156
- job: "leader"
157
- }
158
- }
159
- end
160
-
161
- # post request example using a JSON string
162
- def self.create_user_raw()
163
- {
164
- path: "/api/users",
165
- headers: {"Content-Type": "application/json"},
166
- data: '{"name": "morpheus","job": "leader"}'
167
- }
168
- end
169
-
170
- end
171
-
172
- end
173
-
174
- ```
175
-
176
-
177
- Then in your code you can require this request file and use it like this:
178
-
179
- ```ruby
180
-
181
- resp = http.get Requests::Example.list_of_users
182
-
183
- pp resp.code
184
-
185
- resp = http.post Requests::Example.create_user_hash
186
-
187
- pp resp.data.json
188
-
189
-
190
- resp = http.post Requests::Example.create_user_raw
191
-
192
- pp resp.data.json(:job)
193
-
194
-
195
- ```
196
-
197
-
198
- In 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:
199
-
200
- ```ruby
201
-
202
- req = Requests::Example.create_user_hash
203
- req.values_for = {job: "developer"}
204
-
205
- resp = http.post req
206
-
207
- pp resp.data.json
208
- #response: {:name=>"morpheus", :job=>"developer", :id=>"192", :createdAt=>"2018-12-14T14:41:54.371Z"}
209
-
210
- ```
211
-
212
- If 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:
213
-
214
- ```ruby
215
- req= {
216
- path: "/api/users",
217
- method: :post,
218
- data: {
219
- name: "morpheus",
220
- job: "leader"
221
- }
222
- }
223
- resp = @http.send_request req
224
- ```
225
-
226
-
227
- ## Responses
228
-
229
- The response will include at least the keys:
230
-
231
- *code*: the http code response, for example: 200
232
-
233
- *message*: the http message response, for example: "OK"
234
-
235
- *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)`
236
-
237
- Also interesting keys would be: *time_elapsed_total*, *time_elapsed* and many more available
238
-
239
-
240
- ## Special settings
241
-
242
- *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
243
-
244
- *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"
245
-
246
- *headers*: Hash containing the headers for the communication
247
-
248
- *cookies*: Hash containing the cookies for the communication
249
-
250
- *proxy_port, proxy_host*: in case you want to use a proxy for the connection
251
-
252
- *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.
253
-
254
- *auto_redirect*: (true or false) in case of true it will take care of the auto redirections.
255
-
256
- ## Authentication requests
257
-
258
- All we need to do is to add to our request the correct authentication tokens, seeds, headers.
259
-
260
- For example for Basic Authentication we need to add to the authorization header a seed generated with the user and password we want ot authenticate
261
-
262
- ```ruby
263
-
264
- @http = NiceHttp.new("https://jigsaw.w3.org/")
265
-
266
- @http.headers.authorization = NiceHttpUtils.basic_authentication(user: "guest", password: "guest")
267
-
268
- # headers will be in this example: {:authorization=>"Basic Z3Vlc3Q6Z3Vlc3Q=\n"}
269
-
270
- resp = @http.get("/HTTP/Basic/")
271
-
272
- ```
273
-
274
- Remember 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:
275
-
276
- ```ruby
277
- @http.headers.tokenuno = "xxx"
278
- # headers => {tokenuno: "xxx"}
279
-
280
- #another way:
281
- @http.headers[:tokendos] = "yyy"
282
- # headers => {tokenuno: "xxx", tokendos: "yyyy"}
283
-
284
- ```
285
-
286
- In case you want or need to control the redirections by yourself instead of allowing NiceHttp to do it, then set ```@http.auto_redirect = false```
287
-
288
- An example using OpenID authentication:
289
-
290
- ```ruby
291
- server = "https://samples.auth0.com/"
292
- path="/authorize?client_id=kbyuFDidLLm280LIwVFiazOqjO3ty8KH&response_type=code"
293
-
294
- @http = NiceHttp.new(server)
295
-
296
- resp = @http.get(path)
297
-
298
- p "With autoredirection:"
299
- p "Cookies: "
300
- p @http.cookies
301
- p "Code: #{resp.code} #{resp.message} "
302
- p "*"*40
303
-
304
- @http2 = NiceHttp.new(server)
305
- @http2.auto_redirect = false
306
-
307
- resp = @http2.get(path)
308
-
309
- p "Without autoredirection:"
310
- p "Cookies: "
311
- p @http2.cookies
312
- p "Code: #{resp.code} #{resp.message} "
313
-
314
- ```
315
-
316
- The output:
317
-
318
- ```
319
- "With autoredirection:"
320
- "Cookies: "
321
- {"/"=>{"auth0"=>"s%3A6vEEwmmIf-9YAG-NjvsOIyZAh-NS97jj.yFSXILdmCov6DRwXjEei3q3eHIrxZxHI4eg4%2BTpUaK4"},
322
- "/usernamepassword/login"=>{"_csrf"=>"bboZ0koMScwXkISzWaAMTYdY"}}
323
- "Code: 200 OK "
324
- "****************************************"
325
- "Without autoredirection:"
326
- "Cookies: "
327
- {"/"=>{"auth0"=>"s%3AcKndc44gllWyJv8FLztUIctuH4b__g0V.QEF3SOobK8%2FvX89iUKzGbfSP4Vt2bRtY2WH7ygBUkg4"}}
328
- "Code: 302 Found "
329
-
330
- ```
331
-
332
- You can see on the next link how to get the OAuth2 token for Microsoft Azure and add it to your Http connection header.
333
-
334
- https://gist.github.com/MarioRuiz/d3525185024737885c0c9afa6dc8b9e5
335
-
336
- If you need a new token every time a new http connection is created you can use `lambda`
337
-
338
- ```ruby
339
- NiceHttp.headers[:Authorization] = lambda {get_token()}
340
- ```
341
-
342
- NiceHttp will call the get_token method you created every time a new Http connection is created.
343
-
344
- ## Send multipart content
345
-
346
- Example posting a csv file:
347
-
348
- ```ruby
349
-
350
- require 'net/http/post/multipart'
351
- request = {
352
- path: "/customer/profile/",
353
- headers: {'Content-Type' => 'multipart/form-data'},
354
- data: (Net::HTTP::Post::Multipart.new "/customer/profile/",
355
- "file" => UploadIO.new("./path/to/my/file.csv", "text/csv"))
356
- }
357
- response=@http.post(request)
358
-
359
- ```
360
-
361
- ## Http logs
362
-
363
- You can set where the http logs will be stored by using the log attribute of the NiceHttp.
364
- By default they will be stored in your root directory with the name nice_http.log.
365
- ```ruby
366
- # you can specify the default for all connections
367
- NiceHttp.log = :file_run
368
-
369
- # also you can specify for a concrete connection
370
- http = NiceHttp.new({host: 'www.example.com', log: './example.log'})
371
- ```
372
-
373
- Other values you can supply:
374
- * :fix_file, will log the communication on nice_http.log. (default).
375
- * :no, won't generate any logs.
376
- * :screen, will print the logs on the screen.
377
- * :file, will be generated a log file with name: nice_http_YY-mm-dd-HHMMSS.log.
378
- * :file_run, will generate a log file with the name where the object was created and extension .log, fex: myfile.rb.log
379
- * String, the path and file name where the logs will be stored.
380
-
381
- Example of logs:
382
- ```
383
- I, [2019-03-22T18:38:58.518964 #29412] INFO -- : (47266856647720): Http connection created. host:www.reqres.in, port:443, ssl:true, mode:, proxy_host: , proxy_port:
384
- I, [2019-03-22T18:38:58.537106 #29412] INFO -- : (47266856647720): Http connection: https://www.reqres.in:443
385
-
386
-
387
- - - - - - - - - - - - - - - - - - - - - - - - - -
388
- POST Request: Doom.example
389
- path: /api/users
390
- headers: {Loop:44, Cookie:, Boom:33, Content-Type:application/json, }
391
- data: {
392
- "name": "peter",
393
- "job": "leader",
394
- "products": [
395
- {
396
- "one": "uno",
397
- "two": 2
398
- },
399
- {
400
- "one": "uno",
401
- "two": 22
402
- }
403
- ]
404
- }
405
-
406
- I, [2019-03-22T18:38:58.873935 #29412] INFO -- :
407
- RESPONSE:
408
- 201:Created
409
- time_elapsed_total: '0.335720719'
410
- time_elapsed: '0.335728095'
411
- date: 'Fri, 22 Mar 2019 18:38:58 GMT'
412
- content-type: 'application/json; charset=utf-8'
413
- content-length: '172'
414
- connection: 'keep-alive'
415
- set-cookie: '__cfduid=dfb962e62cd8386ce4ab9bad601611553272738; expires=Sat, 21-Mar-20 18:38:58 GMT; path=/; domain=.reqres.in; HttpOnly'
416
- x-powered-by: 'Express'
417
- access-control-allow-origin: '*'
418
- etag: 'W/"ac-EMh4XBmK5vry/OeKaGWILGtmHU0"'
419
- expect-ct: 'max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"'
420
- server: 'cloudflare'
421
- cf-ray: '4bb99958090dbf89-AMS'
422
- data: '{
423
- "name": "peter",
424
- "job": "leader",
425
- "products": [
426
- {
427
- "one": "uno",
428
- "two": 2
429
- },
430
- {
431
- "one": "uno",
432
- "two": 22
433
- }
434
- ],
435
- "id": "628",
436
- "createdAt": "2019-03-22T18:43:33.619Z"
437
- }'
438
-
439
- I, [2019-03-22T18:38:58.874190 #29412] INFO -- : set-cookie added to Cookie header as required
440
- I, [2019-03-22T18:38:59.075293 #29412] INFO -- :
441
-
442
- - - - - - - - - - - - - - - - - - - - - - - - - -
443
- GET Request: Doom.example
444
- path: /api/users
445
- Same headers and data as in the previous request.
446
- I, [2019-03-22T18:38:59.403459 #29412] INFO -- :
447
- RESPONSE:
448
- 200:OK
449
- time_elapsed_total: '0.327002338'
450
- time_elapsed: '0.327004766'
451
- date: 'Fri, 22 Mar 2019 18:38:59 GMT'
452
- content-type: 'application/json; charset=utf-8'
453
- transfer-encoding: 'chunked'
454
- connection: 'keep-alive'
455
- x-powered-by: 'Express'
456
- access-control-allow-origin: '*'
457
- etag: 'W/"1bb-D+c3sZ5g5u/nmLPQRl1uVo2heAo"'
458
- expect-ct: 'max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"'
459
- server: 'cloudflare'
460
- cf-ray: '4bb9995b5c20bf89-AMS'
461
- data: '{
462
- "page": 1,
463
- "per_page": 3,
464
- "total": 12,
465
- "total_pages": 4,
466
- "data": [
467
- {
468
- "id": 1,
469
- "first_name": "George",
470
- "last_name": "Bluth",
471
- "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/calebogden/128.jpg"
472
- },
473
- {
474
- "id": 2,
475
- "first_name": "Janet",
476
- "last_name": "Weaver",
477
- "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/josephstein/128.jpg"
478
- },
479
- ]
480
- }'
481
-
482
- ```
483
-
484
- ### Multithreading
485
-
486
- In 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
487
-
488
- ```ruby
489
- require 'nice_http'
490
-
491
- threads = []
492
-
493
- 40.times do |num|
494
- threads << Thread.new do
495
- Thread.current.name = num.to_s
496
- http = NiceHttp.new("https://www.reqres.in")
497
- request = {
498
- path: '/api/users',
499
- data: { name: 'morpheus', job: 'leader' },
500
- }
501
- http.post(request)
502
- end
503
- end
504
-
505
- t.each(&:join)
506
-
507
- # log files: nice_http_0.log, nice_http_1.log... nice_http_39.log
508
- ```
509
-
510
- ## Http stats
511
-
512
- If you want to get a summarize stats of your http communication you need to set `NiceHttp.create_stats = true`
513
-
514
- Then whenever you want to access the stats: `NiceHttp.stats`
515
-
516
- After the run is finished there will be few files starting by nice_http_stats and extension yaml on your project root folder including all http stats.
517
-
518
- If you are using RSpec and you want to generate the stats files after every test is finished, add to your spec_helper.rb file:
519
-
520
- ```ruby
521
- RSpec.configure do |config|
522
- config.after(:each) do
523
- require 'yaml'
524
- NiceHttp.stats.keys.each do |key|
525
- File.open("./nice_http_stats_#{key}.yaml", "w") { |file| file.write(NiceHttp.stats[key].to_yaml) }
526
- end
527
- end
528
- end
529
- ```
530
-
531
- This is an example of the output:
532
-
533
- ```yaml
534
- ---
535
- www.reqres.in:443:
536
- :num_requests: 11
537
- :time_elapsed:
538
- :total: 2.947269038
539
- :maximum: 0.357101109
540
- :minimum: 0.198707111
541
- :average: 0.2679335489090909
542
- "/api/users":
543
- :num_requests: 11
544
- :time_elapsed:
545
- :total: 2.947269038
546
- :maximum: 0.357101109
547
- :minimum: 0.198707111
548
- :average: 0.2679335489090909
549
- :method:
550
- POST:
551
- :num_requests: 8
552
- :time_elapsed:
553
- :total: 2.3342455970000002
554
- :maximum: 0.357101109
555
- :minimum: 0.198707111
556
- :average: 0.29178069962500003
557
- :response:
558
- '201':
559
- :num_requests: 8
560
- :time_elapsed:
561
- :total: 2.3342455970000002
562
- :maximum: 0.357101109
563
- :minimum: 0.198707111
564
- :average: 0.29178069962500003
565
- GET:
566
- :num_requests: 3
567
- :time_elapsed:
568
- :total: 0.613023441
569
- :maximum: 0.210662528
570
- :minimum: 0.200197583
571
- :average: 0.20434114699999997
572
- :response:
573
- '200':
574
- :num_requests: 3
575
- :time_elapsed:
576
- :total: 0.613023441
577
- :maximum: 0.210662528
578
- :minimum: 0.200197583
579
- :average: 0.20434114699999997
580
- ```
581
-
582
- If you want to add specific stats for your processes you can use the method `NiceHttp.add_stats`
583
-
584
- ```ruby
585
- started = Time.now
586
- @http.send_request Requests::Customer.add_customer
587
- 30.times do
588
- resp = @http.get(Requests::Customer.get_customer)
589
- break if resp.code == 200
590
- sleep 0.5
591
- end
592
- NiceHttp.add_stats(:customer, :create, started, Time.now)
593
- ```
594
-
595
- ## Contributing
596
-
597
- Bug reports are very welcome on GitHub at https://github.com/marioruiz/nice_http.
598
-
599
- If you want to contribute please follow [GitHub Flow](https://guides.github.com/introduction/flow/index.html)
600
-
601
- ## License
602
-
603
- The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
604
-
605
-
606
-
607
-
1
+ # NiceHttp
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/nice_http.svg)](https://rubygems.org/gems/nice_http)
4
+ [![Build Status](https://travis-ci.com/MarioRuiz/nice_http.svg?branch=master)](https://github.com/MarioRuiz/nice_http)
5
+ [![Coverage Status](https://coveralls.io/repos/github/MarioRuiz/nice_http/badge.svg?branch=master)](https://coveralls.io/github/MarioRuiz/nice_http?branch=master)
6
+ [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FMarioRuiz%2Fnice_http.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2FMarioRuiz%2Fnice_http?ref=badge_shield)
7
+
8
+ NiceHttp the simplest library for accessing and testing HTTP and REST resources.
9
+
10
+ Manage different hosts on the fly. Easily get the value you want from the JSON strings. Use hashes on your requests.
11
+
12
+ Also you can use mock responses by using :mock_response key on the request hash and enable the use_mocks option on NiceHttp.
13
+
14
+ NiceHttp 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.
15
+
16
+ NiceHttp is able to use hashes as requests data and uses the Request Hash structure: https://github.com/MarioRuiz/Request-Hash
17
+
18
+ **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**
19
+
20
+ To be able to generate random requests take a look at the documentation for nice_hash gem: https://github.com/MarioRuiz/nice_hash
21
+
22
+ Example 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
23
+
24
+ ## Installation
25
+
26
+ Install it yourself as:
27
+
28
+ $ gem install nice_http
29
+
30
+
31
+ ## A very simple first example
32
+
33
+ ```ruby
34
+ require 'nice_http'
35
+
36
+ http = NiceHttp.new('https://reqres.in')
37
+
38
+ resp = http.get("/api/users?page=2")
39
+
40
+ pp resp.code
41
+ pp resp.data.json
42
+
43
+ resp = http.get("/api/users/2")
44
+
45
+ pp resp.data.json(:first_name, :last_name)
46
+
47
+ resp = http.post( {
48
+ path: "/api/users",
49
+ data: { name: "morpheus", job: "leader" }
50
+ } )
51
+
52
+ pp resp.data.json
53
+ ```
54
+
55
+ ## Create a connection
56
+
57
+ The simplest way is just by supplying the value as an argument:
58
+
59
+ ```ruby
60
+
61
+ # as an url
62
+ http1 = NiceHttp.new("https://example.com")
63
+
64
+ # as parameters
65
+ http2 = NiceHttp.new( host: "reqres.in", port: 443, ssl: true )
66
+
67
+ # as a hash
68
+ http3 = NiceHttp.new my_reqres_server
69
+
70
+
71
+ ```
72
+
73
+
74
+ You 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:
75
+
76
+ ```ruby
77
+
78
+ # default parameters
79
+ NiceHttp.host = 'reqres.in'
80
+ NiceHttp.ssl = true
81
+ NiceHttp.port = 443
82
+ NiceHttp.debug = false
83
+ NiceHttp.log = "./my_logs.log"
84
+ NiceHttp.headers = {"api-key": "the api key"}
85
+ NiceHttp.values_for = { region: 'europe', customerId: 334 }
86
+
87
+ http1 = NiceHttp.new()
88
+
89
+ http2 = NiceHttp.new()
90
+
91
+ http3 = NiceHttp.new("https://example.com")
92
+
93
+ ```
94
+
95
+ If you prefer to supply a hash to change the default settings for NiceHttp:
96
+
97
+ ```ruby
98
+ NiceHttp.defaults = {
99
+ host: 'reqres.in',
100
+ ssl: true,
101
+ port: 443,
102
+ debug: false,
103
+ log: "./my_logs.log",
104
+ headers: {"api-key": "the api key"}
105
+ }
106
+ ```
107
+
108
+ To 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`:
109
+
110
+ ```ruby
111
+ http = NiceHttp.new('https://v2.namsor.com/NamSorAPIv2/')
112
+
113
+ resp = http.get('/api2/json/gender/Peter/Moon')
114
+ # The get request path will be: /NamSorAPIv2/api2/json/gender/Peter/Moon on server v2.namsor.com
115
+
116
+ resp = http.get('/api2/json/gender/Love/Sun?ret=true')
117
+ # The get request path will be: /NamSorAPIv2/api2/json/gender/Love/Sun on server v2.namsor.com
118
+ ```
119
+
120
+ ## Creating requests
121
+
122
+ You can use hash requests to simplify the management of your requests, for example creating a file specifying all the requests for your Customers API.
123
+
124
+ The keys you can use:
125
+
126
+ *path*: relative or absolute path, for example: "/api2/customers/update.do"
127
+
128
+ *headers*: specific headers for the request. It will include a hash with the values.
129
+
130
+ *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'
131
+
132
+ *mock_response*: In case of use_mocks=true then NiceHttp will return this response
133
+
134
+
135
+ Let's guess you have a file with this data for your requests on */requests/example.rb*:
136
+
137
+ ```ruby
138
+
139
+ module Requests
140
+
141
+ module Example
142
+
143
+ # simple get request example
144
+ def self.list_of_users()
145
+ {
146
+ path: "/api/users?page=2"
147
+ }
148
+ end
149
+
150
+ # post request example using a request hash that will be converted automatically to a json string
151
+ def self.create_user_hash()
152
+ {
153
+ path: "/api/users",
154
+ data: {
155
+ name: "morpheus",
156
+ job: "leader"
157
+ }
158
+ }
159
+ end
160
+
161
+ # post request example using a JSON string
162
+ def self.create_user_raw()
163
+ {
164
+ path: "/api/users",
165
+ headers: {"Content-Type": "application/json"},
166
+ data: '{"name": "morpheus","job": "leader"}'
167
+ }
168
+ end
169
+
170
+ end
171
+
172
+ end
173
+
174
+ ```
175
+
176
+
177
+ Then in your code you can require this request file and use it like this:
178
+
179
+ ```ruby
180
+
181
+ resp = http.get Requests::Example.list_of_users
182
+
183
+ pp resp.code
184
+
185
+ resp = http.post Requests::Example.create_user_hash
186
+
187
+ pp resp.data.json
188
+
189
+
190
+ resp = http.post Requests::Example.create_user_raw
191
+
192
+ pp resp.data.json(:job)
193
+
194
+
195
+ ```
196
+
197
+
198
+ In 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:
199
+
200
+ ```ruby
201
+
202
+ req = Requests::Example.create_user_hash
203
+ req.values_for = {job: "developer"}
204
+
205
+ resp = http.post req
206
+
207
+ pp resp.data.json
208
+ #response: {:name=>"morpheus", :job=>"developer", :id=>"192", :createdAt=>"2018-12-14T14:41:54.371Z"}
209
+
210
+ ```
211
+
212
+ If 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:
213
+
214
+ ```ruby
215
+ req= {
216
+ path: "/api/users",
217
+ method: :post,
218
+ data: {
219
+ name: "morpheus",
220
+ job: "leader"
221
+ }
222
+ }
223
+ resp = @http.send_request req
224
+ ```
225
+
226
+
227
+ ## Responses
228
+
229
+ The response will include at least the keys:
230
+
231
+ *code*: the http code response, for example: 200
232
+
233
+ *message*: the http message response, for example: "OK"
234
+
235
+ *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)`
236
+
237
+ Also interesting keys would be: *time_elapsed_total*, *time_elapsed* and many more available
238
+
239
+
240
+ ## Special settings
241
+
242
+ *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
243
+
244
+ *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"
245
+
246
+ *headers*: Hash containing the headers for the communication
247
+
248
+ *cookies*: Hash containing the cookies for the communication
249
+
250
+ *proxy_port, proxy_host*: in case you want to use a proxy for the connection
251
+
252
+ *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.
253
+
254
+ *auto_redirect*: (true or false) in case of true it will take care of the auto redirections.
255
+
256
+ ## Authentication requests
257
+
258
+ All we need to do is to add to our request the correct authentication tokens, seeds, headers.
259
+
260
+ For example for Basic Authentication we need to add to the authorization header a seed generated with the user and password we want ot authenticate
261
+
262
+ ```ruby
263
+
264
+ @http = NiceHttp.new("https://jigsaw.w3.org/")
265
+
266
+ @http.headers.authorization = NiceHttpUtils.basic_authentication(user: "guest", password: "guest")
267
+
268
+ # headers will be in this example: {:authorization=>"Basic Z3Vlc3Q6Z3Vlc3Q=\n"}
269
+
270
+ resp = @http.get("/HTTP/Basic/")
271
+
272
+ ```
273
+
274
+ Remember 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:
275
+
276
+ ```ruby
277
+ @http.headers.tokenuno = "xxx"
278
+ # headers => {tokenuno: "xxx"}
279
+
280
+ #another way:
281
+ @http.headers[:tokendos] = "yyy"
282
+ # headers => {tokenuno: "xxx", tokendos: "yyyy"}
283
+
284
+ ```
285
+
286
+ In case you want or need to control the redirections by yourself instead of allowing NiceHttp to do it, then set ```@http.auto_redirect = false```
287
+
288
+ An example using OpenID authentication:
289
+
290
+ ```ruby
291
+ server = "https://samples.auth0.com/"
292
+ path="/authorize?client_id=kbyuFDidLLm280LIwVFiazOqjO3ty8KH&response_type=code"
293
+
294
+ @http = NiceHttp.new(server)
295
+
296
+ resp = @http.get(path)
297
+
298
+ p "With autoredirection:"
299
+ p "Cookies: "
300
+ p @http.cookies
301
+ p "Code: #{resp.code} #{resp.message} "
302
+ p "*"*40
303
+
304
+ @http2 = NiceHttp.new(server)
305
+ @http2.auto_redirect = false
306
+
307
+ resp = @http2.get(path)
308
+
309
+ p "Without autoredirection:"
310
+ p "Cookies: "
311
+ p @http2.cookies
312
+ p "Code: #{resp.code} #{resp.message} "
313
+
314
+ ```
315
+
316
+ The output:
317
+
318
+ ```
319
+ "With autoredirection:"
320
+ "Cookies: "
321
+ {"/"=>{"auth0"=>"s%3A6vEEwmmIf-9YAG-NjvsOIyZAh-NS97jj.yFSXILdmCov6DRwXjEei3q3eHIrxZxHI4eg4%2BTpUaK4"},
322
+ "/usernamepassword/login"=>{"_csrf"=>"bboZ0koMScwXkISzWaAMTYdY"}}
323
+ "Code: 200 OK "
324
+ "****************************************"
325
+ "Without autoredirection:"
326
+ "Cookies: "
327
+ {"/"=>{"auth0"=>"s%3AcKndc44gllWyJv8FLztUIctuH4b__g0V.QEF3SOobK8%2FvX89iUKzGbfSP4Vt2bRtY2WH7ygBUkg4"}}
328
+ "Code: 302 Found "
329
+
330
+ ```
331
+
332
+ You can see on the next link how to get the OAuth2 token for Microsoft Azure and add it to your Http connection header.
333
+
334
+ https://gist.github.com/MarioRuiz/d3525185024737885c0c9afa6dc8b9e5
335
+
336
+ If you need a new token every time a new http connection is created you can use `lambda`
337
+
338
+ ```ruby
339
+ NiceHttp.headers[:Authorization] = lambda {get_token()}
340
+ ```
341
+
342
+ NiceHttp will call the get_token method you created every time a new Http connection is created.
343
+
344
+ ## Send multipart content
345
+
346
+ Example posting a csv file:
347
+
348
+ ```ruby
349
+
350
+ require 'net/http/post/multipart'
351
+ request = {
352
+ path: "/customer/profile/",
353
+ headers: {'Content-Type' => 'multipart/form-data'},
354
+ data: (Net::HTTP::Post::Multipart.new "/customer/profile/",
355
+ "file" => UploadIO.new("./path/to/my/file.csv", "text/csv"))
356
+ }
357
+ response=@http.post(request)
358
+
359
+ ```
360
+
361
+ ## Http logs
362
+
363
+ You can set where the http logs will be stored by using the log attribute of the NiceHttp.
364
+ By default they will be stored in your root directory with the name nice_http.log.
365
+ ```ruby
366
+ # you can specify the default for all connections
367
+ NiceHttp.log = :file_run
368
+
369
+ # also you can specify for a concrete connection
370
+ http = NiceHttp.new({host: 'www.example.com', log: './example.log'})
371
+ ```
372
+
373
+ Other values you can supply:
374
+ * :fix_file, will log the communication on nice_http.log. (default).
375
+ * :no, won't generate any logs.
376
+ * :screen, will print the logs on the screen.
377
+ * :file, will be generated a log file with name: nice_http_YY-mm-dd-HHMMSS.log.
378
+ * :file_run, will generate a log file with the name where the object was created and extension .log, fex: myfile.rb.log
379
+ * String, the path and file name where the logs will be stored.
380
+
381
+ Example of logs:
382
+ ```
383
+ I, [2019-03-22T18:38:58.518964 #29412] INFO -- : (47266856647720): Http connection created. host:www.reqres.in, port:443, ssl:true, mode:, proxy_host: , proxy_port:
384
+ I, [2019-03-22T18:38:58.537106 #29412] INFO -- : (47266856647720): Http connection: https://www.reqres.in:443
385
+
386
+
387
+ - - - - - - - - - - - - - - - - - - - - - - - - -
388
+ POST Request: Doom.example
389
+ path: /api/users
390
+ headers: {Loop:44, Cookie:, Boom:33, Content-Type:application/json, }
391
+ data: {
392
+ "name": "peter",
393
+ "job": "leader",
394
+ "products": [
395
+ {
396
+ "one": "uno",
397
+ "two": 2
398
+ },
399
+ {
400
+ "one": "uno",
401
+ "two": 22
402
+ }
403
+ ]
404
+ }
405
+
406
+ I, [2019-03-22T18:38:58.873935 #29412] INFO -- :
407
+ RESPONSE:
408
+ 201:Created
409
+ time_elapsed_total: '0.335720719'
410
+ time_elapsed: '0.335728095'
411
+ date: 'Fri, 22 Mar 2019 18:38:58 GMT'
412
+ content-type: 'application/json; charset=utf-8'
413
+ content-length: '172'
414
+ connection: 'keep-alive'
415
+ set-cookie: '__cfduid=dfb962e62cd8386ce4ab9bad601611553272738; expires=Sat, 21-Mar-20 18:38:58 GMT; path=/; domain=.reqres.in; HttpOnly'
416
+ x-powered-by: 'Express'
417
+ access-control-allow-origin: '*'
418
+ etag: 'W/"ac-EMh4XBmK5vry/OeKaGWILGtmHU0"'
419
+ expect-ct: 'max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"'
420
+ server: 'cloudflare'
421
+ cf-ray: '4bb99958090dbf89-AMS'
422
+ data: '{
423
+ "name": "peter",
424
+ "job": "leader",
425
+ "products": [
426
+ {
427
+ "one": "uno",
428
+ "two": 2
429
+ },
430
+ {
431
+ "one": "uno",
432
+ "two": 22
433
+ }
434
+ ],
435
+ "id": "628",
436
+ "createdAt": "2019-03-22T18:43:33.619Z"
437
+ }'
438
+
439
+ I, [2019-03-22T18:38:58.874190 #29412] INFO -- : set-cookie added to Cookie header as required
440
+ I, [2019-03-22T18:38:59.075293 #29412] INFO -- :
441
+
442
+ - - - - - - - - - - - - - - - - - - - - - - - - -
443
+ GET Request: Doom.example
444
+ path: /api/users
445
+ Same headers and data as in the previous request.
446
+ I, [2019-03-22T18:38:59.403459 #29412] INFO -- :
447
+ RESPONSE:
448
+ 200:OK
449
+ time_elapsed_total: '0.327002338'
450
+ time_elapsed: '0.327004766'
451
+ date: 'Fri, 22 Mar 2019 18:38:59 GMT'
452
+ content-type: 'application/json; charset=utf-8'
453
+ transfer-encoding: 'chunked'
454
+ connection: 'keep-alive'
455
+ x-powered-by: 'Express'
456
+ access-control-allow-origin: '*'
457
+ etag: 'W/"1bb-D+c3sZ5g5u/nmLPQRl1uVo2heAo"'
458
+ expect-ct: 'max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"'
459
+ server: 'cloudflare'
460
+ cf-ray: '4bb9995b5c20bf89-AMS'
461
+ data: '{
462
+ "page": 1,
463
+ "per_page": 3,
464
+ "total": 12,
465
+ "total_pages": 4,
466
+ "data": [
467
+ {
468
+ "id": 1,
469
+ "first_name": "George",
470
+ "last_name": "Bluth",
471
+ "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/calebogden/128.jpg"
472
+ },
473
+ {
474
+ "id": 2,
475
+ "first_name": "Janet",
476
+ "last_name": "Weaver",
477
+ "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/josephstein/128.jpg"
478
+ },
479
+ ]
480
+ }'
481
+
482
+ ```
483
+
484
+ ### Multithreading
485
+
486
+ In 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
487
+
488
+ ```ruby
489
+ require 'nice_http'
490
+
491
+ threads = []
492
+
493
+ 40.times do |num|
494
+ threads << Thread.new do
495
+ Thread.current.name = num.to_s
496
+ http = NiceHttp.new("https://www.reqres.in")
497
+ request = {
498
+ path: '/api/users',
499
+ data: { name: 'morpheus', job: 'leader' },
500
+ }
501
+ http.post(request)
502
+ end
503
+ end
504
+
505
+ t.each(&:join)
506
+
507
+ # log files: nice_http_0.log, nice_http_1.log... nice_http_39.log
508
+ ```
509
+
510
+ ## Http stats
511
+
512
+ If you want to get a summarize stats of your http communication you need to set `NiceHttp.create_stats = true`
513
+
514
+ Then whenever you want to access the stats: `NiceHttp.stats`
515
+
516
+ After the run is finished there will be few files starting by nice_http_stats and extension yaml on your project root folder including all http stats.
517
+
518
+ If you are using RSpec and you want to generate the stats files after every test is finished, add to your spec_helper.rb file:
519
+
520
+ ```ruby
521
+ RSpec.configure do |config|
522
+ config.after(:each) do
523
+ require 'yaml'
524
+ NiceHttp.stats.keys.each do |key|
525
+ File.open("./nice_http_stats_#{key}.yaml", "w") { |file| file.write(NiceHttp.stats[key].to_yaml) }
526
+ end
527
+ end
528
+ end
529
+ ```
530
+
531
+ This is an example of the output:
532
+
533
+ ```yaml
534
+ ---
535
+ www.reqres.in:443:
536
+ :num_requests: 11
537
+ :time_elapsed:
538
+ :total: 2.947269038
539
+ :maximum: 0.357101109
540
+ :minimum: 0.198707111
541
+ :average: 0.2679335489090909
542
+ "/api/users":
543
+ :num_requests: 11
544
+ :time_elapsed:
545
+ :total: 2.947269038
546
+ :maximum: 0.357101109
547
+ :minimum: 0.198707111
548
+ :average: 0.2679335489090909
549
+ :method:
550
+ POST:
551
+ :num_requests: 8
552
+ :time_elapsed:
553
+ :total: 2.3342455970000002
554
+ :maximum: 0.357101109
555
+ :minimum: 0.198707111
556
+ :average: 0.29178069962500003
557
+ :response:
558
+ '201':
559
+ :num_requests: 8
560
+ :time_elapsed:
561
+ :total: 2.3342455970000002
562
+ :maximum: 0.357101109
563
+ :minimum: 0.198707111
564
+ :average: 0.29178069962500003
565
+ GET:
566
+ :num_requests: 3
567
+ :time_elapsed:
568
+ :total: 0.613023441
569
+ :maximum: 0.210662528
570
+ :minimum: 0.200197583
571
+ :average: 0.20434114699999997
572
+ :response:
573
+ '200':
574
+ :num_requests: 3
575
+ :time_elapsed:
576
+ :total: 0.613023441
577
+ :maximum: 0.210662528
578
+ :minimum: 0.200197583
579
+ :average: 0.20434114699999997
580
+ ```
581
+
582
+ If you want to add specific stats for your processes you can use the method `NiceHttp.add_stats`
583
+
584
+ ```ruby
585
+ started = Time.now
586
+ @http.send_request Requests::Customer.add_customer
587
+ 30.times do
588
+ resp = @http.get(Requests::Customer.get_customer)
589
+ break if resp.code == 200
590
+ sleep 0.5
591
+ end
592
+ NiceHttp.add_stats(:customer, :create, started, Time.now)
593
+ ```
594
+
595
+ ## Contributing
596
+
597
+ Bug reports are very welcome on GitHub at https://github.com/marioruiz/nice_http.
598
+
599
+ If you want to contribute please follow [GitHub Flow](https://guides.github.com/introduction/flow/index.html)
600
+
601
+ ## License
602
+
603
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
604
+
605
+
606
+
607
+
608
608
  [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FMarioRuiz%2Fnice_http.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2FMarioRuiz%2Fnice_http?ref=badge_large)