diff --git a/Cargo.lock b/Cargo.lock index 5a4b4e5..cdc5b05 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,9 +13,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.88" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", @@ -24,9 +24,9 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" [[package]] name = "bytes" @@ -36,9 +36,9 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cfg-if" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "convert_case" @@ -51,9 +51,9 @@ dependencies = [ [[package]] name = "ctor" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4735f265ba6a1188052ca32d461028a7d1125868be18e287e756019da7607b5" +checksum = "67773048316103656a637612c4a62477603b777d91d9c62ff2290f9cde178fdb" dependencies = [ "ctor-proc-macro", "dtor", @@ -61,24 +61,24 @@ dependencies = [ [[package]] name = "ctor-proc-macro" -version = "0.0.5" +version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f211af61d8efdd104f96e57adf5e426ba1bc3ed7a4ead616e15e5881fd79c4d" +checksum = "e2931af7e13dc045d8e9d26afccc6fa115d64e115c9c84b1166288b46f6782c2" [[package]] name = "dtor" -version = "0.0.6" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97cbdf2ad6846025e8e25df05171abfb30e3ababa12ee0a0e44b9bbe570633a8" +checksum = "e58a0764cddb55ab28955347b45be00ade43d4d6f3ba4bf3dc354e4ec9432934" dependencies = [ "dtor-proc-macro", ] [[package]] name = "dtor-proc-macro" -version = "0.0.5" +version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7454e41ff9012c00d53cf7f475c5e3afa3b91b7c90568495495e8d9bf47a1055" +checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5" [[package]] name = "fnv" @@ -100,7 +100,7 @@ dependencies = [ [[package]] name = "http-handler" version = "1.0.0" -source = "git+https://github.com/platformatic/http-handler#5a4f58c43dac33e4994918024766ec7d5ab7cc06" +source = "git+https://github.com/platformatic/http-handler#f60dbc830e12b1cedae4c8a4f370bc4133a868fc" dependencies = [ "async-trait", "bytes", @@ -131,25 +131,25 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "libloading" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ "cfg-if", - "windows-targets", + "windows-link", ] [[package]] name = "memchr" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "napi" -version = "3.1.3" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afaf586c21f260e9dc327ae3585fc6efcbb24a416d5151da38bbd35a1f2663c8" +checksum = "f1b74e3dce5230795bb4d2821b941706dee733c7308752507254b0497f39cad7" dependencies = [ "bitflags", "ctor", @@ -167,9 +167,9 @@ checksum = "dcae8ad5609d14afb3a3b91dee88c757016261b151e9dcecabf1b2a31a6cab14" [[package]] name = "napi-derive" -version = "3.1.1" +version = "3.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43e61844e0c0bb81e711f2084abe7cff187b03ca21ff8b000cb59bbda61e15a9" +checksum = "7552d5a579b834614bbd496db5109f1b9f1c758f08224b0dee1e408333adf0d0" dependencies = [ "convert_case", "ctor", @@ -181,9 +181,9 @@ dependencies = [ [[package]] name = "napi-derive-backend" -version = "2.0.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7ab19e9b98efb13895f492a2e367ca50c955ac3c4723613af73fdda4011afcc" +checksum = "5f6a81ac7486b70f2532a289603340862c06eea5a1e650c1ffeda2ce1238516a" dependencies = [ "convert_case", "proc-macro2", @@ -209,27 +209,27 @@ checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.40" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" dependencies = [ "proc-macro2", ] [[package]] name = "regex" -version = "1.11.1" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ "aho-corasick", "memchr", @@ -239,9 +239,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ "aho-corasick", "memchr", @@ -250,9 +250,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "rustc-hash" @@ -262,15 +262,15 @@ checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "semver" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] name = "syn" -version = "2.0.104" +version = "2.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +checksum = "2a26dbd934e5451d21ef060c018dae56fc073894c5a7896f882928a76e6d081b" dependencies = [ "proc-macro2", "quote", @@ -279,9 +279,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "462eeb75aeb73aea900253ce739c8e18a67423fadf006037cd3ff27e82748a06" [[package]] name = "unicode-segmentation" @@ -290,65 +290,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] -name = "windows-targets" -version = "0.53.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" - -[[package]] -name = "windows_i686_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" - -[[package]] -name = "windows_i686_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.0" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" diff --git a/src/napi.rs b/src/napi.rs index f335e2e..afd4d78 100644 --- a/src/napi.rs +++ b/src/napi.rs @@ -1,5 +1,3 @@ -use std::ops::Deref; - use ::napi::bindgen_prelude::Either6; use ::napi::{Error, Result, Status}; use napi_derive::napi; @@ -43,7 +41,7 @@ impl PathCondition { /// ``` #[napi] pub fn matches(&self, request: Request) -> Result { - Ok(self.0.matches(request.deref())) + Ok(self.0.matches(&request)) } } @@ -78,7 +76,7 @@ impl HeaderCondition { /// ``` #[napi] pub fn matches(&self, request: Request) -> Result { - Ok(self.0.matches(request.deref())) + Ok(self.0.matches(&request)) } } @@ -113,7 +111,7 @@ impl MethodCondition { /// ``` #[napi] pub fn matches(&self, request: Request) -> Result { - Ok(self.0.matches(request.deref())) + Ok(self.0.matches(&request)) } } @@ -145,7 +143,7 @@ impl ExistenceCondition { /// ``` #[napi] pub fn matches(&self, request: &Request) -> Result { - Ok(self.0.matches(request)) + Ok(self.0.matches(&request)) } } @@ -177,7 +175,7 @@ impl NonExistenceCondition { /// ``` #[napi] pub fn matches(&self, request: &Request) -> Result { - Ok(self.0.matches(request)) + Ok(self.0.matches(&request)) } } @@ -495,7 +493,7 @@ impl GroupCondition { /// ``` #[napi] pub fn matches(&self, request: Request) -> Result { - Ok(self.0.matches(request.deref())) + Ok(self.0.matches(&request)) } } @@ -797,7 +795,7 @@ impl PathRewriter { pub fn rewrite(&self, request: Request) -> Result { let rewritten = self .0 - .rewrite(request.deref().to_owned()) + .rewrite(request.into_inner()) .map_err(|e| Error::new(Status::GenericFailure, e.to_string()))?; Ok(rewritten.into()) @@ -837,7 +835,7 @@ impl HeaderRewriter { pub fn rewrite(&self, request: Request) -> Result { let rewritten = self .0 - .rewrite(request.deref().to_owned()) + .rewrite(request.into_inner()) .map_err(|e| Error::new(Status::GenericFailure, e.to_string()))?; Ok(rewritten.into()) @@ -877,7 +875,7 @@ impl MethodRewriter { pub fn rewrite(&self, request: Request) -> Result { let rewritten = self .0 - .rewrite(request.deref().to_owned()) + .rewrite(request.into_inner()) .map_err(|e| Error::new(Status::GenericFailure, e.to_string()))?; Ok(rewritten.into()) @@ -917,7 +915,7 @@ impl HrefRewriter { pub fn rewrite(&self, request: Request) -> Result { let rewritten = self .0 - .rewrite(request.deref().to_owned()) + .rewrite(request.into_inner()) .map_err(|e| Error::new(Status::GenericFailure, e.to_string()))?; Ok(rewritten.into()) @@ -1156,7 +1154,7 @@ impl SequenceRewriter { pub fn rewrite(&self, request: Request) -> Result { let rewritten = self .0 - .rewrite(request.deref().to_owned()) + .rewrite(request.into_inner()) .map_err(|e| Error::new(Status::GenericFailure, e.to_string()))?; Ok(rewritten.into()) @@ -1415,7 +1413,7 @@ impl ConditionalRewriter { pub fn rewrite(&self, request: Request) -> Result { let rewritten = self .0 - .rewrite(request.deref().to_owned()) + .rewrite(request.into_inner()) .map_err(|e| Error::new(Status::GenericFailure, e.to_string()))?; Ok(rewritten.into()) @@ -1886,7 +1884,7 @@ impl Rewriter { #[napi(js_name = "rewrite")] pub fn js_rewrite(&self, request: Request) -> Result { let rewritten = self - .rewrite(request.deref().to_owned()) + .rewrite(request.into_inner()) .map_err(|e| Error::new(Status::GenericFailure, e.to_string()))?; Ok(rewritten.into()) diff --git a/src/rewriter.rs b/src/rewriter.rs index 86b56d7..4b805c5 100644 --- a/src/rewriter.rs +++ b/src/rewriter.rs @@ -215,11 +215,24 @@ impl Rewriter for PathRewriter { let new_path = self.pattern.replace(&path, &self.replacement); if new_path != path { - // Build new URI with the new path - let uri_str = if let Some(query) = parts.uri.query() { - format!("{new_path}?{query}") + // Build new URI preserving scheme and authority if present + // This ensures backwards compatibility with full URLs while supporting relative URIs + let uri_str = if let (Some(scheme), Some(authority)) = + (parts.uri.scheme(), parts.uri.authority()) + { + // Full URI - preserve scheme and authority + if let Some(query) = parts.uri.query() { + format!("{scheme}://{authority}{new_path}?{query}") + } else { + format!("{scheme}://{authority}{new_path}") + } } else { - new_path.to_string() + // Relative URI - just use path + if let Some(query) = parts.uri.query() { + format!("{new_path}?{query}") + } else { + new_path.to_string() + } }; parts.uri = uri_str @@ -522,13 +535,33 @@ impl Rewriter for HrefRewriter { fn rewrite(&self, request: Request) -> Result, RewriteError> { let (mut parts, body) = request.into_parts(); - let uri_str = parts.uri.to_string(); - let new_uri_str = self.pattern.replace(&uri_str, &self.replacement); + // Use the full URI for pattern matching + // This allows patterns to match both full URLs and path-only URIs + let input = parts.uri.to_string(); - if new_uri_str != uri_str { - parts.uri = new_uri_str + let replaced = self.pattern.replace(&input, &self.replacement); + if replaced != input { + // Parse the result URI + let new_uri: http::Uri = replaced + .as_ref() .parse() - .map_err(|_| RewriteError("Invalid URI after rewrite".to_string()))?; + .map_err(|_| RewriteError("Invalid URI after href rewrite".to_string()))?; + + // If the result doesn't have a scheme/authority but the original did, + // preserve the original scheme and authority + let final_uri = if new_uri.scheme().is_none() && parts.uri.scheme().is_some() { + let scheme = parts.uri.scheme().unwrap(); + let authority = parts.uri.authority().unwrap(); + format!("{scheme}://{authority}{new_uri}") + .parse() + .map_err(|_| { + RewriteError("Invalid URI after preserving scheme/authority".to_string()) + })? + } else { + new_uri + }; + + parts.uri = final_uri; } Ok(Request::from_parts(parts, body)) diff --git a/test/condition.test.mjs b/test/condition.test.mjs index c302efb..747f3a4 100644 --- a/test/condition.test.mjs +++ b/test/condition.test.mjs @@ -8,10 +8,10 @@ const docroot = fileURLToPath(new URL('.', import.meta.url)) test('PathCondition', async () => { const matchingRequest = new Request({ - uri: '/test/foo' + url: '/test/foo' }) const notMatchingRequest = new Request({ - uri: '/foo/bar' + url: '/foo/bar' }) const pathCondition = new PathCondition('^/test') @@ -23,13 +23,13 @@ test('PathCondition', async () => { test('HeaderCondition', async () => { const matchingRequest = new Request({ - uri: '/test/foo', + url: '/test/foo', headers: { 'X-Test-Header': 'test-value' } }) const notMatchingRequest = new Request({ - uri: '/foo/bar', + url: '/foo/bar', headers: { 'X-Test-Header': 'other-value' } @@ -44,11 +44,11 @@ test('HeaderCondition', async () => { test('MethodCondition', async () => { const matchingRequest = new Request({ - uri: '/test/foo', + url: '/test/foo', method: 'GET' }) const notMatchingRequest = new Request({ - uri: '/foo/bar', + url: '/foo/bar', method: 'POST' }) @@ -61,11 +61,11 @@ test('MethodCondition', async () => { test('ExistenceCondition', async () => { const matchingRequest = new Request({ - uri: '/condition.test.mjs', + url: '/condition.test.mjs', docroot }) const notMatchingRequest = new Request({ - uri: '/not-exists', + url: '/not-exists', docroot }) @@ -78,11 +78,11 @@ test('ExistenceCondition', async () => { test('NonExistenceCondition', async () => { const matchingRequest = new Request({ - uri: '/not-exists', + url: '/not-exists', docroot }) const notMatchingRequest = new Request({ - uri: '/condition.test.mjs', + url: '/condition.test.mjs', docroot }) @@ -126,21 +126,21 @@ test('combinators', async () => { // Verify `and` condition matches when both conditions match ok(andCondition.matches(new Request({ - uri: '/test/foo', + url: '/test/foo', headers: { 'X-Test-Header': 'test-value' } })), 'should match when all conditions match') ok(!andCondition.matches(new Request({ - uri: '/test/foo', + url: '/test/foo', headers: { 'X-Test-Header': 'other-value' } })), 'should not match when one condition does not match') ok(!andCondition.matches(new Request({ - uri: '/foo/bar', + url: '/foo/bar', headers: { 'X-Test-Header': 'test-value' } @@ -148,28 +148,28 @@ test('combinators', async () => { // Verify `or` condition matches if either condition matches ok(orCondition.matches(new Request({ - uri: '/test/foo', + url: '/test/foo', headers: { 'X-Test-Header': 'test-value' } })), 'should match when either condition matches') ok(orCondition.matches(new Request({ - uri: '/foo/bar', + url: '/foo/bar', headers: { 'X-Test-Header': 'test-value' } })), 'should match when path condition matches even if header does not') ok(orCondition.matches(new Request({ - uri: '/test/bar', + url: '/test/bar', headers: { 'X-Test-Header': 'other-value' } })), 'should match when header condition matches even if path does not') ok(!orCondition.matches(new Request({ - uri: '/foo/bar', + url: '/foo/bar', headers: { 'X-Test-Header': 'other-value' } diff --git a/test/rewriter.test.mjs b/test/rewriter.test.mjs index 78efec5..ee472e2 100644 --- a/test/rewriter.test.mjs +++ b/test/rewriter.test.mjs @@ -6,7 +6,7 @@ import { test } from 'node:test' test('PathRewriter', async () => { const request = new Request({ method: 'GET', - uri: '/test.php', + url: '/test.php', headers: { 'Content-Type': 'application/json', 'Accept': ['application/json', 'text/html'], @@ -19,12 +19,12 @@ test('PathRewriter', async () => { const rewritten = pathRewriter.rewrite(request) ok(rewritten instanceof Request, 'should return a Request instance') - strictEqual(rewritten.uri, '/index.php?/test.php', 'should rewrite the URL correctly') + strictEqual(rewritten.url, '/index.php?/test.php', 'should rewrite the URL correctly') }) test('HeaderRewriter', async () => { const request = new Request({ - uri: '/test.php', + url: '/test.php', headers: { 'X-Custom': 'custom-value' } @@ -40,7 +40,7 @@ test('HeaderRewriter', async () => { test('MethodRewriter', async () => { const request = new Request({ - uri: '/test.php', + url: '/test.php', method: 'POST' }) @@ -54,7 +54,7 @@ test('MethodRewriter', async () => { test('chaining rewriters with then()', async () => { const request = new Request({ - uri: '/old/test.php', + url: '/old/test.php', method: 'POST', headers: { 'X-Custom': 'old-value' @@ -71,13 +71,13 @@ test('chaining rewriters with then()', async () => { const rewritten = chained.rewrite(request) ok(rewritten instanceof Request, 'should return a Request instance') - strictEqual(rewritten.uri, '/new/test.php', 'should apply path rewrite') + strictEqual(rewritten.url, '/new/test.php', 'should apply path rewrite') strictEqual(rewritten.method, 'GET', 'should apply method rewrite') }) test('complex chaining with then()', async () => { const request = new Request({ - uri: '/api/v1/users', + url: '/api/v1/users', method: 'POST', headers: { 'X-API-Version': '1.0' @@ -94,7 +94,7 @@ test('complex chaining with then()', async () => { const rewritten = chained.rewrite(request) ok(rewritten instanceof Request, 'should return a Request instance') - strictEqual(rewritten.uri, '/api/v2/users', 'should apply path rewrite') + strictEqual(rewritten.url, '/api/v2/users', 'should apply path rewrite') strictEqual(rewritten.method, 'PUT', 'should apply method rewrite') strictEqual(rewritten.headers.get('X-API-Version'), '2.0', 'should apply header rewrite') }) @@ -108,21 +108,21 @@ test('conditional rewriting with when()', async () => { // Test with matching request const postRequest = new Request({ - uri: '/api/users', + url: '/api/users', method: 'POST' }) const rewritten = conditional.rewrite(postRequest) - strictEqual(rewritten.uri, '/v2/users', 'should rewrite when condition matches') + strictEqual(rewritten.url, '/v2/users', 'should rewrite when condition matches') // Test with non-matching request const otherRequest = new Request({ - uri: '/api/users', + url: '/api/users', method: 'GET' }) const notRewritten = conditional.rewrite(otherRequest) - strictEqual(notRewritten.uri, '/api/users', 'should not rewrite when condition does not match') + strictEqual(notRewritten.url, '/api/users', 'should not rewrite when condition does not match') }) test('Complex conditional and sequence chaining', async () => { @@ -139,37 +139,37 @@ test('Complex conditional and sequence chaining', async () => { // Matches both conditions, so should rewrite both path and header const rewritten = rewriter.rewrite(new Request({ - uri: '/api/users', + url: '/api/users', method: 'POST', headers: { 'X-API-Version': '1.0' } })) - strictEqual(rewritten.uri, '/v2/users', 'should rewrite when both conditions match') + strictEqual(rewritten.url, '/v2/users', 'should rewrite when both conditions match') strictEqual(rewritten.headers.get('X-API-Version'), '2.0', 'should rewrite header when condition matches') // Only matches the second conditional rewriter, so should only rewrite the header const onlyHeaderRewritten = rewriter.rewrite(new Request({ - uri: '/api/users', + url: '/api/users', method: 'GET', headers: { 'X-API-Version': '1.0' } })) - strictEqual(onlyHeaderRewritten.uri, '/api/users', 'should not rewrite when method condition does not match') + strictEqual(onlyHeaderRewritten.url, '/api/users', 'should not rewrite when method condition does not match') strictEqual(onlyHeaderRewritten.headers.get('X-API-Version'), '2.0', 'should rewrite header when condition matches') // No conditions match, so no rewriting should occur const noRewrite = rewriter.rewrite(new Request({ - uri: '/api/users', + url: '/api/users', method: 'GET', headers: { 'X-API-Version': '3.0' } })) - strictEqual(noRewrite.uri, '/api/users', 'should not rewrite when no conditions match') + strictEqual(noRewrite.url, '/api/users', 'should not rewrite when no conditions match') strictEqual(noRewrite.headers.get('X-API-Version'), '3.0', 'should not rewrite header when no conditions match') }) @@ -191,17 +191,17 @@ test('ConditionalRewriter.fromConfig creates rewriter from configuration', async // Test request that matches conditions const matchingRequest = simpleRewriter.rewrite(new Request({ - uri: '/api/v1/users', + url: '/api/v1/users', method: 'POST' })) - strictEqual(matchingRequest.uri, '/api/v2/users', 'should rewrite when conditions match') + strictEqual(matchingRequest.url, '/api/v2/users', 'should rewrite when conditions match') // Test request that doesn't match conditions const nonMatchingRequest = simpleRewriter.rewrite(new Request({ - uri: '/api/v1/users', + url: '/api/v1/users', method: 'GET' })) - strictEqual(nonMatchingRequest.uri, '/api/v1/users', 'should not rewrite when conditions do not match') + strictEqual(nonMatchingRequest.url, '/api/v1/users', 'should not rewrite when conditions do not match') }) test('ConditionalRewriter.fromConfig with multiple rewriters and conditions', async () => { @@ -225,31 +225,31 @@ test('ConditionalRewriter.fromConfig with multiple rewriters and conditions', as // Test with header condition matching const headerMatch = complexRewriter.rewrite(new Request({ - uri: '/old/api', + url: '/old/api', method: 'GET', headers: { 'X-API-Version': '1.0' } })) - strictEqual(headerMatch.uri, '/new/api', 'should rewrite path') + strictEqual(headerMatch.url, '/new/api', 'should rewrite path') strictEqual(headerMatch.method, 'PUT', 'should rewrite method') strictEqual(headerMatch.headers.get('X-API-Version'), '2.0', 'should rewrite header') // Test with method condition matching const methodMatch = complexRewriter.rewrite(new Request({ - uri: '/old/api', + url: '/old/api', method: 'POST', headers: { 'X-API-Version': '3.0' } })) - strictEqual(methodMatch.uri, '/new/api', 'should rewrite path when POST') + strictEqual(methodMatch.url, '/new/api', 'should rewrite path when POST') strictEqual(methodMatch.method, 'PUT', 'should rewrite method') strictEqual(methodMatch.headers.get('X-API-Version'), '3.0', 'header should not change when pattern does not match') // Test with no conditions matching const noMatch = complexRewriter.rewrite(new Request({ - uri: '/old/api', + url: '/old/api', method: 'GET', headers: { 'X-API-Version': '3.0' } })) - strictEqual(noMatch.uri, '/old/api', 'should not rewrite when no conditions match') + strictEqual(noMatch.url, '/old/api', 'should not rewrite when no conditions match') strictEqual(noMatch.method, 'GET', 'method should not change') strictEqual(noMatch.headers.get('X-API-Version'), '3.0', 'header should not change') }) @@ -273,13 +273,13 @@ test('ConditionalRewriter.fromConfig with no conditions applies rewriters uncond // Should always apply rewriters const rewritten = unconditionalRewriter.rewrite(new Request({ - uri: '/api/users', + url: '/api/users', method: 'GET', headers: { 'X-API-Version': '1.0' } })) - strictEqual(rewritten.uri, '/v2/users', 'should rewrite path unconditionally') + strictEqual(rewritten.url, '/v2/users', 'should rewrite path unconditionally') strictEqual(rewritten.method, 'POST', 'should rewrite method unconditionally') strictEqual(rewritten.headers.get('X-API-Version'), '2.0', 'should rewrite header unconditionally') })