mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-08-25 12:54:09 +02:00
Match path placeholders with a scan instead of a regex
This commit is contained in:
Generated
-7
@@ -6681,12 +6681,6 @@ dependencies = [
|
|||||||
"regex-syntax 0.8.5",
|
"regex-syntax 0.8.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "regex-lite"
|
|
||||||
version = "0.1.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "cab834c73d247e67f4fae452806d17d3c7501756d98c8808d7c9c7aa7d18f973"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.5.6"
|
version = "0.5.6"
|
||||||
@@ -11566,7 +11560,6 @@ dependencies = [
|
|||||||
"nanoid",
|
"nanoid",
|
||||||
"r2d2",
|
"r2d2",
|
||||||
"r2d2_sqlite",
|
"r2d2_sqlite",
|
||||||
"regex-lite",
|
|
||||||
"rusqlite",
|
"rusqlite",
|
||||||
"schemars 0.8.22",
|
"schemars 0.8.22",
|
||||||
"sea-query",
|
"sea-query",
|
||||||
|
|||||||
@@ -46,9 +46,9 @@ const WorkspacesWorkspaceIdRequestsRequestIdRoute =
|
|||||||
|
|
||||||
export interface FileRoutesByFullPath {
|
export interface FileRoutesByFullPath {
|
||||||
'/': typeof IndexRoute
|
'/': typeof IndexRoute
|
||||||
'/workspaces': typeof WorkspacesIndexRoute
|
'/workspaces/': typeof WorkspacesIndexRoute
|
||||||
'/workspaces/$workspaceId/settings': typeof WorkspacesWorkspaceIdSettingsRoute
|
'/workspaces/$workspaceId/settings': typeof WorkspacesWorkspaceIdSettingsRoute
|
||||||
'/workspaces/$workspaceId': typeof WorkspacesWorkspaceIdIndexRoute
|
'/workspaces/$workspaceId/': typeof WorkspacesWorkspaceIdIndexRoute
|
||||||
'/workspaces/$workspaceId/requests/$requestId': typeof WorkspacesWorkspaceIdRequestsRequestIdRoute
|
'/workspaces/$workspaceId/requests/$requestId': typeof WorkspacesWorkspaceIdRequestsRequestIdRoute
|
||||||
}
|
}
|
||||||
export interface FileRoutesByTo {
|
export interface FileRoutesByTo {
|
||||||
@@ -70,9 +70,9 @@ export interface FileRouteTypes {
|
|||||||
fileRoutesByFullPath: FileRoutesByFullPath
|
fileRoutesByFullPath: FileRoutesByFullPath
|
||||||
fullPaths:
|
fullPaths:
|
||||||
| '/'
|
| '/'
|
||||||
| '/workspaces'
|
| '/workspaces/'
|
||||||
| '/workspaces/$workspaceId/settings'
|
| '/workspaces/$workspaceId/settings'
|
||||||
| '/workspaces/$workspaceId'
|
| '/workspaces/$workspaceId/'
|
||||||
| '/workspaces/$workspaceId/requests/$requestId'
|
| '/workspaces/$workspaceId/requests/$requestId'
|
||||||
fileRoutesByTo: FileRoutesByTo
|
fileRoutesByTo: FileRoutesByTo
|
||||||
to:
|
to:
|
||||||
@@ -110,14 +110,14 @@ declare module '@tanstack/react-router' {
|
|||||||
'/workspaces/': {
|
'/workspaces/': {
|
||||||
id: '/workspaces/'
|
id: '/workspaces/'
|
||||||
path: '/workspaces'
|
path: '/workspaces'
|
||||||
fullPath: '/workspaces'
|
fullPath: '/workspaces/'
|
||||||
preLoaderRoute: typeof WorkspacesIndexRouteImport
|
preLoaderRoute: typeof WorkspacesIndexRouteImport
|
||||||
parentRoute: typeof rootRouteImport
|
parentRoute: typeof rootRouteImport
|
||||||
}
|
}
|
||||||
'/workspaces/$workspaceId/': {
|
'/workspaces/$workspaceId/': {
|
||||||
id: '/workspaces/$workspaceId/'
|
id: '/workspaces/$workspaceId/'
|
||||||
path: '/workspaces/$workspaceId'
|
path: '/workspaces/$workspaceId'
|
||||||
fullPath: '/workspaces/$workspaceId'
|
fullPath: '/workspaces/$workspaceId/'
|
||||||
preLoaderRoute: typeof WorkspacesWorkspaceIdIndexRouteImport
|
preLoaderRoute: typeof WorkspacesWorkspaceIdIndexRouteImport
|
||||||
parentRoute: typeof rootRouteImport
|
parentRoute: typeof rootRouteImport
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ hex = { workspace = true }
|
|||||||
include_dir = "0.7"
|
include_dir = "0.7"
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
nanoid = "0.4.0"
|
nanoid = "0.4.0"
|
||||||
regex-lite = "0.1"
|
|
||||||
rusqlite = { version = "0.38", features = ["bundled", "chrono"] }
|
rusqlite = { version = "0.38", features = ["bundled", "chrono"] }
|
||||||
sea-query = { version = "1.0", features = ["with-chrono", "attr"] }
|
sea-query = { version = "1.0", features = ["with-chrono", "attr"] }
|
||||||
sea-query-rusqlite = { version = "0.8.0", features = ["with-chrono"] }
|
sea-query-rusqlite = { version = "0.8.0", features = ["with-chrono"] }
|
||||||
|
|||||||
@@ -34,27 +34,41 @@ fn replace_path_placeholder(p: &HttpUrlParameter, url: &str) -> String {
|
|||||||
return url.to_string();
|
return url.to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
// A path placeholder is terminated by `/`, `?`, `#`, end-of-string, or a literal `:`.
|
// A placeholder is `/` followed by the parameter's name (which starts with `:`), and it
|
||||||
// The `:` boundary is what lets `/:id:increment-importance` substitute the `:id`
|
// ends at `/`, `?`, `#`, a literal `:`, or the end of the URL. The `:` boundary is what
|
||||||
// placeholder while leaving `:increment-importance` as literal text.
|
// lets `/:id:increment-importance` substitute the `:id` placeholder while leaving
|
||||||
let re = regex_lite::Regex::new(format!("(/){}([/?#:]|$)", p.name).as_str()).unwrap();
|
// `:increment-importance` as literal text. `/:foooo` is not a match for `:foo`.
|
||||||
let result = re
|
//
|
||||||
.replace_all(url, |cap: ®ex_lite::Captures| {
|
// A plain scan rather than a regex: the name is matched literally, so a name containing
|
||||||
format!(
|
// `.` or `+` means exactly that, and nothing else in the model layer needs a regex engine.
|
||||||
"{}{}{}",
|
let name = p.name.as_str();
|
||||||
cap[1].to_string(),
|
let value = urlencoding::encode(p.value.as_str());
|
||||||
urlencoding::encode(p.value.as_str()),
|
let mut result = String::with_capacity(url.len());
|
||||||
cap[2].to_string()
|
let mut rest = url;
|
||||||
)
|
while let Some(slash) = rest.find('/') {
|
||||||
})
|
let after_slash = &rest[slash + 1..];
|
||||||
.into_owned();
|
let is_placeholder = after_slash.starts_with(name)
|
||||||
|
&& after_slash[name.len()..]
|
||||||
|
.chars()
|
||||||
|
.next()
|
||||||
|
.is_none_or(|c| matches!(c, '/' | '?' | '#' | ':'));
|
||||||
|
if is_placeholder {
|
||||||
|
result.push_str(&rest[..=slash]);
|
||||||
|
result.push_str(&value);
|
||||||
|
rest = &after_slash[name.len()..];
|
||||||
|
} else {
|
||||||
|
result.push_str(&rest[..=slash]);
|
||||||
|
rest = after_slash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.push_str(rest);
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod placeholder_tests {
|
mod placeholder_tests {
|
||||||
use crate::path_placeholders::{apply_path_placeholders, replace_path_placeholder};
|
|
||||||
use crate::models::{HttpRequest, HttpUrlParameter};
|
use crate::models::{HttpRequest, HttpUrlParameter};
|
||||||
|
use crate::path_placeholders::{apply_path_placeholders, replace_path_placeholder};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn placeholder_middle() {
|
fn placeholder_middle() {
|
||||||
@@ -98,6 +112,30 @@ mod placeholder_tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn placeholder_name_is_matched_literally() {
|
||||||
|
// `.` in a name is a dot, not "any character".
|
||||||
|
let p = HttpUrlParameter {
|
||||||
|
name: ":id.v2".into(),
|
||||||
|
value: "xxx".into(),
|
||||||
|
enabled: true,
|
||||||
|
id: None,
|
||||||
|
};
|
||||||
|
assert_eq!(
|
||||||
|
replace_path_placeholder(&p, "https://example.com/:id.v2/:idXv2"),
|
||||||
|
"https://example.com/xxx/:idXv2",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn placeholder_repeated() {
|
||||||
|
let p = HttpUrlParameter { name: ":id".into(), value: "7".into(), enabled: true, id: None };
|
||||||
|
assert_eq!(
|
||||||
|
replace_path_placeholder(&p, "https://example.com/:id/:id"),
|
||||||
|
"https://example.com/7/7",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn placeholder_missing() {
|
fn placeholder_missing() {
|
||||||
let p = HttpUrlParameter {
|
let p = HttpUrlParameter {
|
||||||
|
|||||||
@@ -694,7 +694,7 @@ export function __wbg_versions_215a3ab1c9d5745a(arg0) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
export function __wbindgen_cast_0000000000000001(arg0, arg1) {
|
export function __wbindgen_cast_0000000000000001(arg0, arg1) {
|
||||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 1123, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
|
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 1116, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
|
||||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__ha1c2fa93df0107f3);
|
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__ha1c2fa93df0107f3);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -705,7 +705,7 @@ export function __wbindgen_cast_0000000000000002(arg0, arg1) {
|
|||||||
}
|
}
|
||||||
export function __wbindgen_cast_0000000000000003(arg0, arg1) {
|
export function __wbindgen_cast_0000000000000003(arg0, arg1) {
|
||||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("IDBVersionChangeEvent")], shim_idx: 114, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
|
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("IDBVersionChangeEvent")], shim_idx: 114, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
|
||||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h999df771f7987dc3);
|
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__hdf19cb46f9aecb24);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
export function __wbindgen_cast_0000000000000004(arg0, arg1) {
|
export function __wbindgen_cast_0000000000000004(arg0, arg1) {
|
||||||
@@ -762,8 +762,8 @@ function wasm_bindgen__convert__closures_____invoke__ha1c2fa93df0107f3(arg0, arg
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function wasm_bindgen__convert__closures_____invoke__h999df771f7987dc3(arg0, arg1, arg2) {
|
function wasm_bindgen__convert__closures_____invoke__hdf19cb46f9aecb24(arg0, arg1, arg2) {
|
||||||
const ret = wasm.wasm_bindgen__convert__closures_____invoke__h999df771f7987dc3(arg0, arg1, arg2);
|
const ret = wasm.wasm_bindgen__convert__closures_____invoke__hdf19cb46f9aecb24(arg0, arg1, arg2);
|
||||||
if (ret[1]) {
|
if (ret[1]) {
|
||||||
throw takeFromExternrefTable0(ret[0]);
|
throw takeFromExternrefTable0(ret[0]);
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
+1
-1
@@ -18,7 +18,7 @@ export const rust_sqlite_wasm_realloc: (a: number, b: number) => number;
|
|||||||
export const sqlite3_os_end: () => number;
|
export const sqlite3_os_end: () => number;
|
||||||
export const sqlite3_os_init: () => number;
|
export const sqlite3_os_init: () => number;
|
||||||
export const wasm_bindgen__convert__closures_____invoke__ha1c2fa93df0107f3: (a: number, b: number, c: any) => [number, number];
|
export const wasm_bindgen__convert__closures_____invoke__ha1c2fa93df0107f3: (a: number, b: number, c: any) => [number, number];
|
||||||
export const wasm_bindgen__convert__closures_____invoke__h999df771f7987dc3: (a: number, b: number, c: any) => [number, number];
|
export const wasm_bindgen__convert__closures_____invoke__hdf19cb46f9aecb24: (a: number, b: number, c: any) => [number, number];
|
||||||
export const wasm_bindgen__convert__closures_____invoke__h2cf3f4cce3b29948: (a: number, b: number, c: any, d: any) => void;
|
export const wasm_bindgen__convert__closures_____invoke__h2cf3f4cce3b29948: (a: number, b: number, c: any, d: any) => void;
|
||||||
export const wasm_bindgen__convert__closures_____invoke__ha7903b6e296dd8f4: (a: number, b: number, c: any) => void;
|
export const wasm_bindgen__convert__closures_____invoke__ha7903b6e296dd8f4: (a: number, b: number, c: any) => void;
|
||||||
export const wasm_bindgen__convert__closures_____invoke__ha1b480b83daa641f: (a: number, b: number) => void;
|
export const wasm_bindgen__convert__closures_____invoke__ha1b480b83daa641f: (a: number, b: number) => void;
|
||||||
|
|||||||
Reference in New Issue
Block a user