yobi-http 0.18.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b5994458b4f28cc4879858782a1dbc26a90f8ab77d7bf97b5a13ee7aaec13092
4
- data.tar.gz: ac095c048327a1ce8260f388dcc414c647fa9f912f15ab9f43fabb1327225f69
3
+ metadata.gz: ee3f871068b818f6f194f64edecbfe16bfb51c5d590445da566a8e6229bd3b28
4
+ data.tar.gz: 17e8538a544d0cdc95317180a7e11418460c26288ee5f77f770c52356c654c90
5
5
  SHA512:
6
- metadata.gz: 9a1db1c25476849b0169d3d535d3ced35f2d14034363617211aff38f7903970d9056269231d83e8617392c66587eae32ef42fd573080bd3f5165d8b7de63f63f
7
- data.tar.gz: 2ba909e076ccf9a12ff9f624ebe545675d6c540aaa248951a0ff7a5504a38d476c38b07e1fe321e5de921fd693a01be84dcee6169f6a23cde0ce7e01c3020c95
6
+ metadata.gz: 70b8027ba0bec021821bd8e50bcc216796e29650d3a4791082146b608293e5b7b088ac7352317c0a010f05e8438b92343c3b8e64e1450027888c4d86d9545f63
7
+ data.tar.gz: 1b5249c74c29c93de6ae4d6138281745b98eedb50d216e52b096248a331ff7ce552b7d53aae0e4da4d045339d7b66b92f12ef4c72ede58d1c0623aa2bb5e8e01
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.20.0]
4
+
5
+ - Add support to --stream flag
6
+
3
7
  ## [0.6.0]
4
8
 
5
9
  - Add output to file feature
data/exe/yobi CHANGED
@@ -16,7 +16,7 @@ require "yobi"
16
16
  # parsing arguments
17
17
  @options = {
18
18
  print: "HB", auth: nil, auth_type: "basic", verbose: false, raw: false, offline: false, follow: false, debug: false,
19
- timeout: nil, download: false, output: nil, content_type: :json
19
+ timeout: nil, download: false, output: nil, content_type: :json, stream: false
20
20
  }
21
21
 
22
22
  parser = OptionParser.new do |opts|
@@ -38,6 +38,7 @@ parser = OptionParser.new do |opts|
38
38
 
39
39
  opts.on("-p", "--print FORMAT", "Specify the output format (e.g., 'H' for headers, 'B' for body)") do |format|
40
40
  @options[:print] = format || "HB" # default to printing both headers and body
41
+ @options[:print_set_explicitly] = true
41
42
  warn "[Argument Error] Unsupported format: #{format}" unless format.match?(/\A[HBhb]+\z/)
42
43
  end
43
44
 
@@ -105,6 +106,12 @@ parser = OptionParser.new do |opts|
105
106
  @options[:timeout] = timeout.to_f
106
107
  end
107
108
 
109
+ opts.on("--stream", "Stream response body (chunked transfer encoding), printing each chunk as it arrives") do
110
+ @options[:stream] = true
111
+ # Default to body-only when streaming, unless the user already set --print explicitly
112
+ @options[:print] = "B" unless @options[:print_set_explicitly]
113
+ end
114
+
108
115
  opts.on("--download", "Download response body to a file specified by --output") do
109
116
  @options[:download] = true
110
117
  end
@@ -147,12 +154,14 @@ Yobi.args.auth_header(headers, @options) if @options[:auth]
147
154
  Yobi::Http.request(method, url, data: data, headers: headers, query: query, options: @options) do |http, request|
148
155
  options = @options
149
156
 
150
- # follow redirects, offline, download or standard request mode
157
+ # follow redirects, offline, download, stream or standard request mode
151
158
  response =
152
159
  if options[:follow]
153
160
  Yobi::Http.follow_redirects(http.request(request), url, method, data, headers, options)
154
161
  elsif options[:offline]
155
162
  Yobi::Http.offline_mode(request, options)
163
+ elsif options[:stream]
164
+ Yobi::Http.stream(request, http, options)
156
165
  elsif options[:download]
157
166
  Yobi::Http.download(request, http, options)
158
167
  else
data/lib/yobi/http.rb CHANGED
@@ -92,6 +92,24 @@ module Yobi
92
92
  end
93
93
  # rubocop:enable Metrics/AbcSize
94
94
 
95
+ def stream(request, http, options)
96
+ http.request(request) do |response|
97
+ Yobi::Renders::Stream.render_headers(response, options)
98
+
99
+ response.read_body do |chunk|
100
+ Yobi::Renders::Stream.render_chunk(chunk, options)
101
+ end
102
+
103
+ Yobi::Renders::Stream.flush_buffer(options)
104
+ end
105
+
106
+ exit 0
107
+ rescue Interrupt
108
+ Yobi::Renders::Stream.flush_buffer(options)
109
+ $stdout.puts
110
+ exit 0
111
+ end
112
+
95
113
  # rubocop:disable Metrics/AbcSize
96
114
  def download(request, http, options)
97
115
  http.request(request) do |response|
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yobi
4
+ module Renders
5
+ # Render streaming (chunked) response chunks to the terminal as they arrive
6
+ module Stream
7
+ class << self
8
+ # Called once when the response headers are received
9
+ def render_headers(response, options = {})
10
+ return unless options[:print]&.include?("H")
11
+
12
+ if options[:raw]
13
+ $stdout.puts "HTTP/#{response.http_version} #{response.code} #{response.message}"
14
+ response.each_header { |key, value| $stdout.puts "#{key}: #{value}" }
15
+ $stdout.puts
16
+ else
17
+ header_md = "# HTTP/#{response.http_version} #{response.code} #{response.message}\n\n" \
18
+ "```yaml\n" \
19
+ "#{response.each_capitalized.to_h.sort.map { |k, v| "#{k}: #{v}" }.join("\n")}\n" \
20
+ "```\n"
21
+ $stdout.print TTY::Markdown.parse(header_md, color: :always)
22
+ end
23
+
24
+ $stdout.flush
25
+ end
26
+
27
+ # Called for each chunk received. Buffers partial lines across calls so
28
+ # that JSON objects split across chunk boundaries are handled correctly.
29
+ def render_chunk(chunk, options = {})
30
+ return if chunk.nil? || chunk.empty?
31
+ return unless options[:print]&.include?("B")
32
+
33
+ if options[:raw]
34
+ $stdout.print chunk
35
+ $stdout.flush
36
+ return
37
+ end
38
+
39
+ data = (@line_buffer || "") + chunk
40
+ @line_buffer = nil
41
+
42
+ lines = data.split("\n", -1)
43
+
44
+ @line_buffer = lines.pop unless data.end_with?("\n")
45
+
46
+ lines.each do |line|
47
+ next if line.empty?
48
+
49
+ parsed = begin
50
+ JSON.parse(line)
51
+ rescue JSON::ParserError
52
+ nil
53
+ end
54
+
55
+ if parsed
56
+ pretty = JSON.pretty_generate(parsed)
57
+ md = "```json\n#{pretty}\n```\n"
58
+ $stdout.print TTY::Markdown.parse(md, color: :always)
59
+ else
60
+ $stdout.puts line
61
+ end
62
+
63
+ $stdout.flush
64
+ end
65
+ end
66
+
67
+ # Flush any remaining buffered line when the connection closes
68
+ def flush_buffer(options = {})
69
+ return unless @line_buffer && !@line_buffer.empty?
70
+ return unless options[:print]&.include?("B")
71
+
72
+ line = @line_buffer
73
+ @line_buffer = nil
74
+
75
+ parsed = begin
76
+ JSON.parse(line)
77
+ rescue JSON::ParserError
78
+ nil
79
+ end
80
+
81
+ if parsed && !options[:raw]
82
+ pretty = JSON.pretty_generate(parsed)
83
+ md = "```json\n#{pretty}\n```\n"
84
+ $stdout.print TTY::Markdown.parse(md, color: :always)
85
+ else
86
+ $stdout.puts line
87
+ end
88
+
89
+ $stdout.flush
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
data/lib/yobi/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Yobi
4
4
  # Yobi gem version
5
- VERSION = "0.18.0"
5
+ VERSION = "0.20.0"
6
6
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yobi-http
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.18.0
4
+ version: 0.20.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Vinciguerra
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2026-03-05 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: base64
@@ -77,6 +77,7 @@ files:
77
77
  - lib/yobi/renders.rb
78
78
  - lib/yobi/renders/colored.rb
79
79
  - lib/yobi/renders/raw.rb
80
+ - lib/yobi/renders/stream.rb
80
81
  - lib/yobi/ui.rb
81
82
  - lib/yobi/ui/progress.rb
82
83
  - lib/yobi/version.rb
@@ -108,7 +109,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
108
109
  - !ruby/object:Gem::Version
109
110
  version: '0'
110
111
  requirements: []
111
- rubygems_version: 3.6.2
112
+ rubygems_version: 4.0.3
112
113
  specification_version: 4
113
114
  summary: Yobi is a terminal tool to make HTTP requests and display responses in a
114
115
  friendly way inspired by HTTPie.