matching strings with simple regex - ruby-on-rails

In a Rails app I need to identify certain URLs paths that are expressed in this form:
paths = ['/a/*/b/c', '/f/*']
I'm in a middleware and I have access to the path, what kind of conditional should I write to check if the current URL path has a match with an entry in the provided array?
path = Rack::Request.new(env).path
included = paths.any? { |s| path.include?(s) }
this only checks for inclusion, but now wildcards have arrived.

You can convert paths into regular expression patterns:
paths = ['/a/*/b/c', '/f/*']
path = Rack::Request.new(env).path
patterns = paths.map { |path| Regexp.new path.gsub(/\*/, '[^/]+') }
# Convert `*` to `[^/]+` to match any non-`/` characters.
included = patterns.any? { |s| path =~ s }

Related

Lua remove folders in file path from request uri

I have URL's like this:
/path1/path2/path3/path4/path5/96_6.txt
/path1/path2/path3/path4/path5/96_7.txt?blah=1
So far I am doing the following to obtain the file on the end of my URL:
local request_uri = "/path1/path2/path3/path4/path5/96_645.txt?lol=1"
local name = request_uri:match( "([^/]+)$" )
local filename = string.gsub(name, "?.*", "")
print(name)
print(filename)
What outputs:
96_645.txt?lol=1
96_645.txt
What I want to do is to remove path2 and path3 from my URL. The issue is they are dynamic folder paths and can contain characters.
What is the best solution for this?
Try this one:
function fix_url(p)
p, _ = string.gsub(p, '^/([^/]+)/[^/]+/[^/]+/(.*)', '/%1/%2')
return p
end
Here are some tests:
p = fix_url('/path1/path2/path3/path4/path5/96_6.txt')
assert(p == '/path1/path4/path5/96_6.txt')
p = fix_url('/path1/path2/path3/path4/path5/96_7.txt?blah=1')
assert(p == '/path1/path4/path5/96_7.txt?blah=1')
p = fix_url('/path1/foo.txt')
assert(p == '/path1/foo.txt')

How can I use Chinese letters for locals lua

im trying to make locals with Chinese letters
local 屁 = p
or
屁 = p
none of those work
any ways to do it?
You can't do this as "屁" is not a valid Lua identifier.
Lua identifiers can only have letters, numbers and underscores and must not start with a number.
However, you can create a table with a key 屁:
local chinese_letters = {
["屁"] = p
}
And access it as chinese_letters["屁"], for example
local chinese_letters = {
["屁"] = 10
}
print(chinese_letters["屁"])
By the way, the correct name for these chinese characters is Hanzi

hmac authentication in vcl

I am trying to authenticate URL using hamc. I can do the following to verify.My question is how do I parse the URL to extract only part of the URL excluding the hmac parameter. I tried using local variables in vcl but it threw an error.
Any suggestions on how to extract the hmac value and URL query parameters as shown below.
http://localhost/zzz/?q1=xxx&q2=yyy&hmac=hash
if (digest.hmac_md5("key", "q1=xxx&q2=yyy") != "value")
{
return (synth(401, digest.hmac_md5("key", "http://localhost/zzz/?q1=xxx&q2=yyy")));
}
Thanks
You'll want to use the [querystring][1] vmod. As far as I know it does not come pre-packaged, so you will need to build it but it should do exactly what you need.
With that you can define regexes/static values to match querystring arguments, and then filter those out or in.
there is no need for a external plugin in that case you can just strip out the hmac=XXX query string parameter, from req.url and store the result in a new variable req.http.url_without_hmac and req.http.hmac to the digest.hmac_md5
see a sample test case:
varnishtest "Strip query parameter"
server s1 {
rxreq
txresp
rxreq
txresp
} -start
varnish v1 -vcl+backend {
import std;
sub vcl_recv {
# Strip out HMAC parameter
# get only the query string, ignore uri
set req.http.qs = regsuball(req.url, ".*\?(.*?)$", "?\1");
# strip hmac= from the qs
set req.http.url_without_hmac = regsuball(req.http.qs,"\?hmac=[^&]+$",""); # strips when QS = "?hmac=AAA"
set req.http.url_without_hmac = regsuball(req.http.url_without_hmac,"\?hmac=[^&]+&","?"); # strips when QS = "?hmac=AAA&foo=bar"
set req.http.url_without_hmac = regsuball(req.http.url_without_hmac,"&hmac=[^&]+",""); # strips when QS = "?foo=bar&hmac=AAA" or QS = "?foo=bar&hmac=AAA&bar=baz"
# remove the leading ? from the url_without_hmac
set req.http.url_without_hmac = regsuball(req.http.url_without_hmac,"^\?(.*)$", "\1");
# extract the hmac= value from the req.http.qs
set req.http.hmac = regsuball(req.http.qs, ".*[?&]hmac=([^&]*).*", "\1");
# NOW USE req.http.url_without_hmac for your digest validation and req.http.hmac as the value
}
sub vcl_deliver {
set resp.http.url_without_hmac = req.http.url_without_hmac;
set resp.http.hmac = req.http.hmac;
}
} -start
client c1 {
txreq -url "/1?a=1&hmac=2&b=1"
rxresp
expect resp.http.url_without_hmac == "a=1&b=1"
expect resp.http.hmac == "2"
} -run
client c2 {
txreq -url "/1?hmac=hello&a=1&b=1"
rxresp
expect resp.http.url_without_hmac == "a=1&b=1"
expect resp.http.hmac == "hello"
} -run

Given two absolute paths, how can I express one of the paths relative to the other?

I think this should be quite doable, given that there is a nice function canonicalize which normalizes paths (so I can start by normalizing my two input paths) and Path and PathBuf give us a way of iterating over the parts of paths through components. I imagine something could be worked out here to factor out a common prefix, then prepend as many .. components as remain in the anchor path to what remains of the initial input path.
My problem seems to be pretty common:
How to find relative path given two absolute paths?
Find a path in Windows relative to another
This now exists as the pathdiff crate, using the code from kennytm's answer
You can use it as:
extern crate pathdiff;
pathdiff::diff_paths(path, base);
where base is where the relative path should be applied to obtain path
If one path is a base of another, you could use Path::strip_prefix, but it won't calculate the ../ for you (instead returns an Err):
use std::path::*;
let base = Path::new("/foo/bar");
let child_a = Path::new("/foo/bar/a");
let child_b = Path::new("/foo/bar/b");
println!("{:?}", child_a.strip_prefix(base)); // Ok("a")
println!("{:?}", child_a.strip_prefix(child_b)); // Err(StripPrefixError(()))
The previous incarnation of strip_prefix was path_relative_from which used to add ../, but this behavior was dropped due to symlinks:
The current behavior where joining the result onto the first path unambiguously refers to the same thing the second path does, even if there's symlinks (which basically means base needs to be a prefix of self)
The old behavior where the result can start with ../ components. Symlinks mean traversing the base path and then traversing the returned relative path may not put you in the same directory that traversing the self path does. But this operation is useful when either you're working with a path-based system that doesn't care about symlinks, or you've already resolved symlinks in the paths you're working with.
If you need the ../ behavior, you could copy the implementation from librustc_back (the compiler backend). I didn't find any packages on crates.io providing this yet.
// This routine is adapted from the *old* Path's `path_relative_from`
// function, which works differently from the new `relative_from` function.
// In particular, this handles the case on unix where both paths are
// absolute but with only the root as the common directory.
fn path_relative_from(path: &Path, base: &Path) -> Option<PathBuf> {
use std::path::Component;
if path.is_absolute() != base.is_absolute() {
if path.is_absolute() {
Some(PathBuf::from(path))
} else {
None
}
} else {
let mut ita = path.components();
let mut itb = base.components();
let mut comps: Vec<Component> = vec![];
loop {
match (ita.next(), itb.next()) {
(None, None) => break,
(Some(a), None) => {
comps.push(a);
comps.extend(ita.by_ref());
break;
}
(None, _) => comps.push(Component::ParentDir),
(Some(a), Some(b)) if comps.is_empty() && a == b => (),
(Some(a), Some(b)) if b == Component::CurDir => comps.push(a),
(Some(_), Some(b)) if b == Component::ParentDir => return None,
(Some(a), Some(_)) => {
comps.push(Component::ParentDir);
for _ in itb {
comps.push(Component::ParentDir);
}
comps.push(a);
comps.extend(ita.by_ref());
break;
}
}
}
Some(comps.iter().map(|c| c.as_os_str()).collect())
}
}

Lua String Split

Hi I've got this function in JavaScript:
function blur(data) {
var trimdata = trim(data);
var dataSplit = trimdata.split(" ");
var lastWord = dataSplit.pop();
var toBlur = dataSplit.join(" ");
}
What this does is it take's a string such as "Hello my name is bob" and will return
toBlur = "Hello my name is" and lastWord = "bob"
Is there a way i can re-write this in Lua?
You could use Lua's pattern matching facilities:
function blur(data) do
return string.match(data, "^(.*)[ ][^ ]*$")
end
How does the pattern work?
^ # start matching at the beginning of the string
( # open a capturing group ... what is matched inside will be returned
.* # as many arbitrary characters as possible
) # end of capturing group
[ ] # a single literal space (you could omit the square brackets, but I think
# they increase readability
[^ ] # match anything BUT literal spaces... as many as possible
$ # marks the end of the input string
So [ ][^ ]*$ has to match the last word and the preceding space. Therefore, (.*) will return everything in front of it.
For a more direct translation of your JavaScript, first note that there is no split function in Lua. There is table.concat though, which works like join. Since you have to do the splitting manually, you'll probably use a pattern again:
function blur(data) do
local words = {}
for m in string.gmatch("[^ ]+") do
words[#words+1] = m
end
words[#words] = nil -- pops the last word
return table.concat(words, " ")
end
gmatch does not give you a table right away, but an iterator over all matches instead. So you add them to your own temporary table, and call concat on that. words[#words+1] = ... is a Lua idiom to append an element to the end of an array.

Resources