Merge "extracting project name from uri" into dev
diff --git a/include/types/proxy.h b/include/types/proxy.h
index baeac2c..c7a913b 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -259,7 +259,7 @@
int uri_len_limit; /* character limit for uri balancing algorithm */
int uri_dirs_depth1; /* directories+1 (slashes) limit for uri balancing algorithm */
int uri_whole; /* if != 0, calculates the hash from the whole uri. Still honors the len_limit and dirs_depth1 */
- int uri_git; /* if != 0, calculates the hash from the git uri. */
+ int uri_gerrit; /* if != 0, calculates the hash from extracting gerrit project from uri. */
char *hh_name; /* name of the header parameter used for hashing */
int hh_len; /* strlen(hh_name), computed only once */
int hh_match_domain; /* toggle use of special match function */
diff --git a/src/backend.c b/src/backend.c
index 87dda72..4615c90 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -188,6 +188,11 @@
int slashes = 0;
const char *start, *end;
int depth = 1;
+ int orig_uri_len = uri_len;
+ const char *orig_start;
+ const char *p, *params;
+ int buflen = 0;
+ char *buf;
if (px->lbprm.tot_weight == 0)
return NULL;
@@ -199,29 +204,99 @@
if (px->uri_len_limit)
uri_len = MIN(uri_len, px->uri_len_limit);
- start = end = uri;
- if (px->uri_git == 1) {
+ orig_start = start = end = uri;
+ if (px->uri_gerrit == 1) {
+ p = memchr(uri, '?', uri_len);
+ params = p;
+ if (p) {
+ p++;
+ uri_len = p - uri;
+ params = p;
+ if (p[7] == '=') {
+ if (memcmp(p, "service", 7) == 0) {
+ p += 8;
+ depth = 2;
+ }
+ }
+ }
+
end = uri + uri_len - 1;
while (uri_len--) {
c = *end;
if (c == '/') {
+ if (p == NULL)
+ p = end + 1;
slashes++;
if (slashes == depth)
break;
}
- else if (c == '?')
- depth = 2;
end--;
}
- //get rid of redundant '/'
- while ((end - start) > 1 && *(start+1) == '/')
- start++;
- while ((end - start) > 1 && *(end-1) == '/')
- end--;
- //get rid of trailing ".git"
- if ((end - start) > 4 && strncmp(end-4, ".git", 4) == 0)
- end -= 4;
+ if (!strncmp(p, "git-receive-pack", 16) || !strncmp(p, "git-upload-pack", 15)) {
+ // we have git request here
+ // get rid of redundant '/'
+ while ((end - start) > 1 && *(start+1) == '/')
+ start++;
+ while ((end - start) > 1 && *(end-1) == '/')
+ end--;
+ // get rid of trailing ".git"
+ if ((end - start) > 4 && strncmp(end-4, ".git", 4) == 0)
+ end -= 4;
+ hash = gen_hash(px, start, (end - start));
+ } else {
+ if (px->uri_dirs_depth1 > 0){
+ // reset state
+ uri_len = orig_uri_len;
+ if (params != NULL)
+ uri_len = params - uri;
+ depth = px->uri_dirs_depth1;
+ slashes = 0;
+ buf = (char *)malloc(uri_len);
+ orig_start = start = end = uri;
+ while (uri_len--) {
+ c = *end;
+ if (c == '/') {
+ if (slashes == 1 && end - start == 2) {
+ depth += 1;
+ orig_start = start = end;
+ }
+ slashes++;
+ if (slashes == depth - 1) {
+ if (memcmp(start, "/changes", end - start) != 0 && memcmp(start, "/projects", end - start) != 0)
+ break;
+ start = end;
+ p = start;
+ }
+ else if (slashes == depth) { /* depth+1 */
+ memcpy(buf + buflen, p, end - p);
+ buflen += (end - p);
+ break;
+ }
+ }
+ else if (c == '%') {
+ if (orig_start != start && uri_len > 2 && memcmp(end, "%2F", 3) == 0) {
+ memcpy(buf + buflen, p, end - p);
+ buflen += (end - p) + 1;
+ buf[buflen - 1] = '/';
+ p = end + 3;
+ }
+ }
+ else if (c == '~') {
+ memcpy(buf + buflen, p, end - p);
+ buflen += (end - p);
+ break;
+ }
+ end++;
+ }
+ }
+ if (buflen > 0)
+ hash = gen_hash(px, buf, buflen);
+ if (buf != NULL)
+ free(buf);
+ if (buflen <= 0) /*let's fallback to round robin */
+ return NULL;
+ }
} else {
while (uri_len--) {
c = *end;
@@ -234,10 +309,9 @@
break;
end++;
}
+ hash = gen_hash(px, start, (end - start));
}
- hash = gen_hash(px, start, (end - start));
-
if ((px->lbprm.algo & BE_LB_HASH_MOD) == BE_LB_HMOD_AVAL)
hash = full_hash(hash);
hash_done:
@@ -1384,7 +1458,7 @@
curproxy->lbprm.algo |= BE_LB_ALGO_UH;
curproxy->uri_whole = 0;
- curproxy->uri_git = 1;
+ curproxy->uri_gerrit = 0;
while (*args[arg]) {
if (!strcmp(args[arg], "len")) {
@@ -1394,7 +1468,6 @@
}
curproxy->uri_len_limit = atoi(args[arg+1]);
arg += 2;
- curproxy->uri_git = 0;
}
else if (!strcmp(args[arg], "depth")) {
if (!*args[arg+1] || (atoi(args[arg+1]) <= 0)) {
@@ -1406,12 +1479,20 @@
*/
curproxy->uri_dirs_depth1 = atoi(args[arg+1]) + 1;
arg += 2;
- curproxy->uri_git = 0;
}
else if (!strcmp(args[arg], "whole")) {
curproxy->uri_whole = 1;
arg += 1;
- curproxy->uri_git = 0;
+ }
+ else if (!strcmp(args[arg], "gerrit")) {
+ if (!*args[arg+1] || (atoi(args[arg+1]) < 0)) {
+ memprintf(err, "%s : '%s' expects a non negative integer (got '%s').", args[0], args[arg], args[arg+1]);
+ return -1;
+ }
+ curproxy->uri_gerrit = 1;
+ // 0 means whole uri
+ curproxy->uri_dirs_depth1 = atoi(args[arg+1]);
+ arg += 2;
}
else {
memprintf(err, "%s only accepts parameters 'len', 'depth', and 'whole' (got '%s').", args[0], args[arg]);