diff --git a/CHANGELOG.md b/CHANGELOG.md index 450071f..1f173f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `NetRequest` query parameters value has been changed to be a table of key-value pairs similar to `process.env`. If any query parameter is specified more than once in the request url, the value chosen will be the last one that was specified. +- The internal http client for `net.request` now reuses headers and connections for more efficient requests. ### Fixed diff --git a/packages/lib/src/globals/net.rs b/packages/lib/src/globals/net.rs index fd71260..77bb477 100644 --- a/packages/lib/src/globals/net.rs +++ b/packages/lib/src/globals/net.rs @@ -1,24 +1,40 @@ -use std::collections::HashMap; -use std::future::Future; -use std::pin::Pin; -use std::sync::{Arc, Weak}; -use std::task::{Context, Poll}; +use std::{ + collections::HashMap, + future::Future, + pin::Pin, + sync::{Arc, Weak}, + task::{Context, Poll}, +}; -use hyper::body::to_bytes; -use hyper::http::HeaderValue; -use hyper::server::conn::AddrStream; use mlua::prelude::*; -use hyper::service::Service; +use hyper::{body::to_bytes, http::HeaderValue, server::conn::AddrStream, service::Service}; use hyper::{Body, HeaderMap, Request, Response, Server}; use reqwest::{ClientBuilder, Method}; -use tokio::sync::mpsc::Sender; -use tokio::task; +use tokio::{sync::mpsc::Sender, task}; -use crate::utils::{net::get_request_user_agent_header, table::TableBuilder}; +use crate::utils::{ + net::{get_request_user_agent_header, NetClient}, + table::TableBuilder, +}; use crate::LuneMessage; pub fn create(lua: &Lua) -> LuaResult<()> { + // Create a reusable client for performing our + // web requests and store it in the lua registry + let mut default_headers = HeaderMap::new(); + default_headers.insert( + "User-Agent", + HeaderValue::from_str(&get_request_user_agent_header()).map_err(LuaError::external)?, + ); + let client = NetClient::new( + ClientBuilder::new() + .default_headers(default_headers) + .build() + .map_err(LuaError::external)?, + ); + lua.set_named_registry_value("NetClient", client)?; + // Create the global table for net lua.globals().raw_set( "net", TableBuilder::new(lua)? @@ -44,6 +60,7 @@ fn net_json_decode(lua: &Lua, json: String) -> LuaResult { } async fn net_request<'lua>(lua: &'lua Lua, config: LuaValue<'lua>) -> LuaResult> { + let client: NetClient = lua.named_registry_value("NetClient")?; // Extract stuff from config and make sure its all valid let (url, method, headers, body) = match config { LuaValue::String(s) => { @@ -103,16 +120,6 @@ async fn net_request<'lua>(lua: &'lua Lua, config: LuaValue<'lua>) -> LuaResult< &method ))), }?; - // TODO: Figure out how to reuse this client - let mut default_headers = HeaderMap::new(); - default_headers.insert( - "User-Agent", - HeaderValue::from_str(&get_request_user_agent_header()).map_err(LuaError::external)?, - ); - let client = ClientBuilder::new() - .default_headers(default_headers) - .build() - .map_err(LuaError::external)?; // Create and send the request let mut request = client.request(method, &url); for (header, value) in headers { diff --git a/packages/lib/src/utils/net.rs b/packages/lib/src/utils/net.rs index 9625650..2083a05 100644 --- a/packages/lib/src/utils/net.rs +++ b/packages/lib/src/utils/net.rs @@ -1,3 +1,21 @@ +use mlua::prelude::*; +use reqwest::{IntoUrl, Method, RequestBuilder}; + +#[derive(Clone)] +pub struct NetClient(reqwest::Client); + +impl NetClient { + pub fn new(client: reqwest::Client) -> Self { + Self(client) + } + + pub fn request(&self, method: Method, url: U) -> RequestBuilder { + self.0.request(method, url) + } +} + +impl LuaUserData for NetClient {} + pub fn get_github_owner_and_repo() -> (String, String) { let (github_owner, github_repo) = env!("CARGO_PKG_REPOSITORY") .strip_prefix("https://github.com/")