From https://github.com/apache/couchdb/blob/master/src/couchdb/couch_httpd_rewrite.erl#L367-385
Output for both programs:
=> /
/ => /
/foo/bar/baz => /foo/bar/baz
foo/one//two///three//// => /foo/one/two/three
foo/bar/..//baz => /foo/baz
| % normalize_path experiments | |
| -define(SEPARATOR, $\/). | |
| main(_) -> ok | |
| , Paths = [ "" | |
| , "/" | |
| , "/foo/bar/baz" | |
| , "foo/one//two///three////" | |
| , "foo/bar/..//baz" | |
| ] | |
| , lists:foreach(fun(Path) -> ok | |
| , io:format("~s => ~s\n", [Path, normalize_path(Path)]) | |
| end, Paths) | |
| . | |
| normalize_path(Path) -> | |
| "/" ++ string:join(normalize_path1(string:tokens(Path, | |
| "/"), []), [?SEPARATOR]). | |
| normalize_path1([], Acc) -> | |
| lists:reverse(Acc); | |
| normalize_path1([".."|Rest], Acc) -> | |
| Acc1 = case Acc of | |
| [] -> [".."|Acc]; | |
| [T|_] when T =:= ".." -> [".."|Acc]; | |
| [_|R] -> R | |
| end, | |
| normalize_path1(Rest, Acc1); | |
| normalize_path1(["."|Rest], Acc) -> | |
| normalize_path1(Rest, Acc); | |
| normalize_path1([Path|Rest], Acc) -> | |
| normalize_path1(Rest, [Path|Acc]). |
| var SEPARATOR = '/' | |
| main() | |
| function main() { | |
| var paths = [ "" | |
| , "/" | |
| , "/foo/bar/baz" | |
| , "foo/one//two///three////" | |
| , "foo/bar/..//baz" | |
| ] | |
| paths.forEach(function(path, i) { | |
| console.log(path + ' => ' + normalize_path(path)) | |
| }) | |
| } | |
| function string_tokens(str, separator) { | |
| return str.split(separator).filter(function(part) { return part != '' }) | |
| } | |
| // normalize_path(Path) -> | |
| function normalize_path(path) { | |
| return '/' + normalize_path1(string_tokens(path, '/'), []).join(SEPARATOR) | |
| } | |
| function normalize_path1(parts, acc) { | |
| // normalize_path1([], Acc) -> | |
| if(parts.length == 0) | |
| return acc.reverse() | |
| // normalize_path1([".."|Rest], Acc) -> | |
| else if(parts[0] == '..') { | |
| var rest = parts.slice(1) | |
| var acc1 | |
| if(acc.length == 0) | |
| acc1 = ['..'].concat(acc) | |
| else if(acc[0] == '..') | |
| acc1 = ['..'].concat(acc) | |
| else | |
| acc1 = acc.slice(1) | |
| return normalize_path1(rest, acc1) | |
| } | |
| // normalize_path1(["."|Rest], Acc) -> | |
| else if(parts[0] == '.') { | |
| var rest = parts.slice[1] | |
| return normalize_path1(rest, acc) | |
| } | |
| // normalize_path1([Path|Rest], Acc) -> | |
| else { | |
| var path = parts[0] | |
| , rest = parts.slice(1) | |
| return normalize_path1(rest, [path].concat(acc)) | |
| } | |
| } |
From https://github.com/apache/couchdb/blob/master/src/couchdb/couch_httpd_rewrite.erl#L367-385
Output for both programs:
=> /
/ => /
/foo/bar/baz => /foo/bar/baz
foo/one//two///three//// => /foo/one/two/three
foo/bar/..//baz => /foo/baz