Skip to content

Commit 6618545

Browse files
Make the response object testable.
1 parent c2be3db commit 6618545

File tree

5 files changed

+98
-5
lines changed

5 files changed

+98
-5
lines changed

Cargo.lock

Lines changed: 51 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/hyper_ruby/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ rb-sys = "0.9.110"
1919
hyper = { version = "1.0", features = ["http1", "http2", "server"] }
2020
hyper-util = { version = "0.1", features = ["tokio", "server", "http1", "http2"] }
2121
http-body-util = "0.1.2"
22-
jemallocator = { version = "0.5.4", features = ["disable_initial_exec_tls"] }
22+
jemallocator = { version = "0.5.4", features = ["disable_initial_exec_tls"] }
23+
futures = "0.3.31"

ext/hyper_ruby/src/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@ mod request;
22
mod response;
33
mod gvl_helpers;
44

5-
use hyper::header::HeaderName;
65
use request::Request;
76
use response::Response;
87
use gvl_helpers::nogvl;
98

109
use magnus::block::block_proc;
11-
use magnus::r_hash::ForEach;
1210
use magnus::typed_data::Obj;
1311
use magnus::{function, method, prelude::*, Error as MagnusError, IntoValue, Ruby, Value};
1412
use bytes::Bytes;
@@ -298,6 +296,9 @@ fn init(ruby: &Ruby) -> Result<(), MagnusError> {
298296

299297
let response_class = module.define_class("Response", ruby.class_object())?;
300298
response_class.define_singleton_method("new", function!(Response::new, 3))?;
299+
response_class.define_method("status", method!(Response::status, 0))?;
300+
response_class.define_method("headers", method!(Response::headers, 0))?;
301+
response_class.define_method("body", method!(Response::body, 0))?;
301302

302303
let request_class = module.define_class("Request", ruby.class_object())?;
303304
request_class.define_method("http_method", method!(Request::method, 0))?;

ext/hyper_ruby/src/response.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
use futures::FutureExt;
12
use magnus::{r_hash::ForEach, wrap, RHash, RString, Error as MagnusError};
23

3-
use hyper::{header::HeaderName, Response as HyperResponse, StatusCode};
4-
use http_body_util::Full;
4+
use hyper::{header::HeaderName, Response as HyperResponse};
5+
use http_body_util::{BodyExt, Full};
56
use bytes::Bytes;
7+
68
// Response object returned to Ruby; holds reference to the opaque ruby types for the headers and body.
79
#[wrap(class = "HyperRuby::Response")]
810
pub struct Response {
@@ -38,4 +40,27 @@ impl Response {
3840
}
3941
}
4042
}
43+
44+
pub fn status(&self) -> u16 {
45+
self.response.status().into()
46+
}
47+
48+
pub fn headers(&self) -> RHash {
49+
// map back from the hyper headers to the ruby hash; doesn't need to be performant,
50+
// only used in tests
51+
let headers = RHash::new();
52+
for (name, value) in self.response.headers() {
53+
headers.aset(name.to_string(), value.to_str().unwrap().to_string()).unwrap();
54+
}
55+
headers
56+
}
57+
58+
pub fn body(&self) -> RString {
59+
// copy back from the hyper body to the ruby string; doesn't need to be performant,
60+
// only used in tests
61+
let body = self.response.body();
62+
let frame = body.clone().frame().now_or_never().unwrap().unwrap().unwrap();
63+
let data_chunk = frame.into_data().unwrap();
64+
RString::from_slice(data_chunk.iter().as_slice())
65+
}
4166
}

test/test_response.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# frozen_string_literal: true
2+
3+
require "test_helper"
4+
require "httpx"
5+
6+
class TestHyperRuby < Minitest::Test
7+
8+
def test_can_read_properties_back
9+
response = HyperRuby::Response.new(200, { 'Content-Type' => 'text/plain' }, 'Hello, world!')
10+
assert_equal 200, response.status
11+
assert_equal 'text/plain', response.headers['content-type']
12+
assert_equal 'Hello, world!', response.body
13+
end
14+
15+
end

0 commit comments

Comments
 (0)