MINOR: uri_normalizer: Add a `strip-dot` normalizer

This normalizer removes "/./" segments from the path component.
Usually the dot refers to the current directory which renders those segments redundant.

See GitHub Issue #714.
diff --git a/src/http_act.c b/src/http_act.c
index 5da2d7d..df2bbe4 100644
--- a/src/http_act.c
+++ b/src/http_act.c
@@ -232,6 +232,23 @@
 
 			break;
 		}
+		case ACT_NORMALIZE_URI_PATH_STRIP_DOT: {
+			const struct ist path = http_get_path(uri);
+			struct ist newpath = ist2(replace->area, replace->size);
+
+			if (!isttest(path))
+				goto leave;
+
+			err = uri_normalizer_path_dot(iststop(path, '?'), &newpath);
+
+			if (err != URI_NORMALIZER_ERR_NONE)
+				break;
+
+			if (!http_replace_req_path(htx, newpath, 0))
+				goto fail_rewrite;
+
+			break;
+		}
 		case ACT_NORMALIZE_URI_PATH_STRIP_DOTDOT:
 		case ACT_NORMALIZE_URI_PATH_STRIP_DOTDOT_FULL: {
 			const struct ist path = http_get_path(uri);
@@ -350,6 +367,11 @@
 
 		rule->action = ACT_NORMALIZE_URI_PATH_MERGE_SLASHES;
 	}
+	else if (strcmp(args[cur_arg], "path-strip-dot") == 0) {
+		cur_arg++;
+
+		rule->action = ACT_NORMALIZE_URI_PATH_STRIP_DOT;
+	}
 	else if (strcmp(args[cur_arg], "path-strip-dotdot") == 0) {
 		cur_arg++;
 
diff --git a/src/uri_normalizer.c b/src/uri_normalizer.c
index ded9e1c..8d95936 100644
--- a/src/uri_normalizer.c
+++ b/src/uri_normalizer.c
@@ -75,6 +75,47 @@
 	return err;
 }
 
+/* Removes `/./` from the given path. */
+enum uri_normalizer_err uri_normalizer_path_dot(const struct ist path, struct ist *dst)
+{
+	enum uri_normalizer_err err;
+
+	const size_t size = istclear(dst);
+	struct ist newpath = *dst;
+
+	struct ist scanner = path;
+
+	/* The path will either be shortened or have the same length. */
+	if (size < istlen(path)) {
+		err = URI_NORMALIZER_ERR_ALLOC;
+		goto fail;
+	}
+
+	while (istlen(scanner) > 0) {
+		const struct ist segment = istsplit(&scanner, '/');
+
+		if (!isteq(segment, ist("."))) {
+			if (istcat(&newpath, segment, size) < 0) {
+				/* This is impossible, because we checked the size of the destination buffer. */
+				my_unreachable();
+				err = URI_NORMALIZER_ERR_INTERNAL_ERROR;
+				goto fail;
+			}
+
+			if (istend(segment) != istend(scanner))
+				newpath = __istappend(newpath, '/');
+		}
+	}
+
+	*dst = newpath;
+
+	return URI_NORMALIZER_ERR_NONE;
+
+  fail:
+
+	return err;
+}
+
 /* Merges `/../` with preceding path segments.
  *
  * If `full` is set to `0` then `/../` will be printed at the start of the resulting