Reuse http client for net.request

This commit is contained in:
Filip Tibell 2023-02-09 23:21:26 +01:00
parent eebe009873
commit be39ecc00a
No known key found for this signature in database
3 changed files with 48 additions and 22 deletions

View file

@ -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`. - `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. 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 ### Fixed

View file

@ -1,24 +1,40 @@
use std::collections::HashMap; use std::{
use std::future::Future; collections::HashMap,
use std::pin::Pin; future::Future,
use std::sync::{Arc, Weak}; pin::Pin,
use std::task::{Context, Poll}; sync::{Arc, Weak},
task::{Context, Poll},
};
use hyper::body::to_bytes;
use hyper::http::HeaderValue;
use hyper::server::conn::AddrStream;
use mlua::prelude::*; 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 hyper::{Body, HeaderMap, Request, Response, Server};
use reqwest::{ClientBuilder, Method}; use reqwest::{ClientBuilder, Method};
use tokio::sync::mpsc::Sender; use tokio::{sync::mpsc::Sender, task};
use tokio::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; use crate::LuneMessage;
pub fn create(lua: &Lua) -> LuaResult<()> { 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( lua.globals().raw_set(
"net", "net",
TableBuilder::new(lua)? TableBuilder::new(lua)?
@ -44,6 +60,7 @@ fn net_json_decode(lua: &Lua, json: String) -> LuaResult<LuaValue> {
} }
async fn net_request<'lua>(lua: &'lua Lua, config: LuaValue<'lua>) -> LuaResult<LuaTable<'lua>> { async fn net_request<'lua>(lua: &'lua Lua, config: LuaValue<'lua>) -> LuaResult<LuaTable<'lua>> {
let client: NetClient = lua.named_registry_value("NetClient")?;
// Extract stuff from config and make sure its all valid // Extract stuff from config and make sure its all valid
let (url, method, headers, body) = match config { let (url, method, headers, body) = match config {
LuaValue::String(s) => { LuaValue::String(s) => {
@ -103,16 +120,6 @@ async fn net_request<'lua>(lua: &'lua Lua, config: LuaValue<'lua>) -> LuaResult<
&method &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 // Create and send the request
let mut request = client.request(method, &url); let mut request = client.request(method, &url);
for (header, value) in headers { for (header, value) in headers {

View file

@ -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<U: IntoUrl>(&self, method: Method, url: U) -> RequestBuilder {
self.0.request(method, url)
}
}
impl LuaUserData for NetClient {}
pub fn get_github_owner_and_repo() -> (String, String) { pub fn get_github_owner_and_repo() -> (String, String) {
let (github_owner, github_repo) = env!("CARGO_PKG_REPOSITORY") let (github_owner, github_repo) = env!("CARGO_PKG_REPOSITORY")
.strip_prefix("https://github.com/") .strip_prefix("https://github.com/")