diff --git a/src/client.rs b/src/client.rs index 700bb3d..7ef7b95 100644 --- a/src/client.rs +++ b/src/client.rs @@ -10,7 +10,7 @@ use magnus::{ Module, Object, RHash, RModule, Ruby, TryConvert, Value, function, method, typed_data::Obj, }; use serde::Deserialize; -use wreq::{Proxy, header::HeaderValue}; +use wreq::Proxy; use crate::{ client::{req::execute_request, resp::Response}, @@ -19,7 +19,7 @@ use crate::{ error::wreq_error_to_magnus, extractor::Extractor, gvl, - header::{Headers, OrigHeaders}, + header::{Headers, OrigHeaders, UserAgent}, http::Method, }; @@ -31,7 +31,7 @@ struct Builder { emulation: Option, /// The user agent to use for the client. #[serde(skip)] - user_agent: Option, + user_agent: Option, /// The headers to use for the client. #[serde(skip)] headers: Option, @@ -136,6 +136,10 @@ impl Builder { builder.emulation = Some((*Obj::::try_convert(v)?).clone()); } + if let Some(v) = hash.get(ruby.to_symbol(stringify!(user_agent))) { + builder.user_agent = Some(UserAgent::try_convert(v)?); + } + if let Some(v) = hash.get(ruby.to_symbol(stringify!(headers))) { builder.headers = Some(Headers::try_convert(v)?); } @@ -148,7 +152,6 @@ impl Builder { builder.cookie_provider = Some((*Obj::::try_convert(v)?).clone()); } - builder.user_agent = Extractor::::try_convert(*keyword)?.into_inner(); builder.proxy = Extractor::::try_convert(*keyword)?.into_inner(); Ok(builder) @@ -169,7 +172,7 @@ impl Client { apply_option!(set_if_some_inner, builder, params.emulation, emulation); // User agent options. - apply_option!(set_if_some, builder, params.user_agent, user_agent); + apply_option!(set_if_some_inner, builder, params.user_agent, user_agent); // Headers options. apply_option!( diff --git a/src/extractor.rs b/src/extractor.rs index 63df29a..8d3259d 100644 --- a/src/extractor.rs +++ b/src/extractor.rs @@ -32,31 +32,6 @@ where } } -// ===== impl Extractor ===== - -impl ExtractorName for HeaderValue { - const NAME: &str = "user_agent"; -} - -impl TryConvert for Extractor { - fn try_convert(value: magnus::Value) -> Result { - let ruby = Ruby::get_with(value); - let keyword = RHash::try_convert(value)?; - - if let Some(ruby_value) = keyword - .get(ruby.to_symbol(HeaderValue::NAME)) - .and_then(RString::from_value) - { - return HeaderValue::from_maybe_shared(ruby_value.to_bytes()) - .map(Some) - .map(Extractor) - .map_err(header_value_error_to_magnus); - } - - Ok(Extractor(None)) - } -} - // ===== impl Extractor ===== impl ExtractorName for HeaderMap { diff --git a/src/header.rs b/src/header.rs index cf8bd6f..5326e2c 100644 --- a/src/header.rs +++ b/src/header.rs @@ -15,6 +15,9 @@ use crate::error::{ header_name_error_to_magnus, header_value_error_to_magnus, type_value_error_to_magnus, }; +/// A wrapper for the User-Agent header value. +pub struct UserAgent(pub HeaderValue); + /// HTTP headers collection with read and write operations. /// /// This class wraps HTTP headers and provides convenient methods for @@ -31,6 +34,17 @@ struct HeaderIter { next_name: Option, } +// ===== impl UserAgent ===== + +impl TryConvert for UserAgent { + fn try_convert(value: Value) -> Result { + let s = RString::try_convert(value)?; + let header_value = + HeaderValue::from_maybe_shared(s.to_bytes()).map_err(header_value_error_to_magnus)?; + Ok(Self(header_value)) + } +} + // ===== impl Headers ===== impl Headers {