Skip to content

Commit

Permalink
Inlined AntPath- and AntPathRequestMatcher
Browse files Browse the repository at this point in the history
  • Loading branch information
Willi Schönborn committed Apr 30, 2016
1 parent 16d5a75 commit 13655ad
Show file tree
Hide file tree
Showing 33 changed files with 550 additions and 139 deletions.
44 changes: 40 additions & 4 deletions logbook-api/src/main/java/org/zalando/logbook/BaseHttpRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,57 @@

import com.google.common.collect.ListMultimap;

import javax.annotation.Nullable;

import static java.util.Arrays.asList;

public interface BaseHttpRequest extends BaseHttpMessage {

String getRemote();

String getMethod();

/**
* Request URI without the query string.
* Absolute Request URI including scheme, host, port (unless http/80 or https/443), path and query string.
*
* <p>Note that the URI may be invalid if the client issued an HTTP request using a malformed URL.</p>
*
* @return the requested URI
* @return the requested URI
*/
String getRequestUri();

default String getRequestUri() {
final String scheme = getScheme();
final String host = getHost();
final int port = getPort();
final String path = getPath();
final String query = getQuery();

final StringBuilder url = new StringBuilder()
.append(scheme).append("://").append(host);

if ("http".equals(scheme) && port != 80 ||
"https".equals(scheme) && port != 443) {
url.append(':').append(port);
}

url.append(path);

if (!query.isEmpty()) {
url.append('?').append(query);
}

return url.toString();
}

String getScheme();

String getHost();

int getPort();

String getPath();

String getQuery();

ListMultimap<String, String> getQueryParameters();

}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ private String formatRequestLine(final HttpRequest request) {
return String.format("%s %s %s", request.getMethod(), renderRequestUri(request), request.getProtocolVersion());
}

private String renderRequestUri(HttpRequest request) {
private String renderRequestUri(final HttpRequest request) {
final String query = QueryParameters.render(request.getQueryParameters());
return request.getRequestUri() + (query.isEmpty() ? "" : "?" + query);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ public final class DefaultLogbookFactory implements LogbookFactory {

@Override
public Logbook create(
@Nullable Predicate<RawHttpRequest> predicate,
@Nullable Obfuscator headerObfuscator,
@Nullable Obfuscator parameterObfuscator,
@Nullable BodyObfuscator bodyObfuscator,
@Nullable HttpLogFormatter formatter,
@Nullable HttpLogWriter writer) {
@Nullable final Predicate<RawHttpRequest> predicate,
@Nullable final Obfuscator headerObfuscator,
@Nullable final Obfuscator parameterObfuscator,
@Nullable final BodyObfuscator bodyObfuscator,
@Nullable final HttpLogFormatter formatter,
@Nullable final HttpLogWriter writer) {

return new DefaultLogbook(
firstNonNull(predicate, request -> true),
firstNonNull(predicate, $ -> true),
new Obfuscation(
firstNonNull(headerObfuscator, Obfuscator.authorization()),
firstNonNull(parameterObfuscator, Obfuscator.none()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,31 @@ public String getRequestUri() {
return delegate().getRequestUri();
}

@Override
public String getHost() {
return delegate().getHost();
}

@Override
public String getScheme() {
return delegate().getScheme();
}

@Override
public int getPort() {
return delegate().getPort();
}

@Override
public String getPath() {
return delegate().getPath();
}

@Override
public String getQuery() {
return delegate().getQuery();
}

@Override
public ListMultimap<String, String> getQueryParameters() {
return delegate().getQueryParameters();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,31 @@ public String getRequestUri() {
return delegate().getRequestUri();
}

@Override
public String getScheme() {
return delegate().getScheme();
}

@Override
public String getHost() {
return delegate().getHost();
}

@Override
public int getPort() {
return delegate().getPort();
}

@Override
public String getPath() {
return delegate().getPath();
}

@Override
public String getQuery() {
return delegate().getQuery();
}

@Override
public ListMultimap<String, String> getQueryParameters() {
return delegate().getQueryParameters();
Expand Down
222 changes: 222 additions & 0 deletions logbook-core/src/main/java/org/zalando/logbook/Glob.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
package org.zalando.logbook;

/*
* #%L
* Logbook: Core
* %%
* Copyright (C) 2015 - 2016 Zalando SE
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/

import com.google.common.base.Splitter;

import java.util.List;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.google.common.base.Splitter.on;

final class Glob {

public static Predicate<String> compile(final String pattern) {
if (pattern.equals("/**") || pattern.equals("**")) {
return $ -> true;
} else if (isSuffix(pattern)) {
return new SuffixGlob(pattern.substring(0, pattern.length() - 3));
} else {
return new DefaultGlob(pattern);
}
}

private static boolean isSuffix(final String pattern) {
return pattern.endsWith("/**")
&& pattern.indexOf('?') == -1
&& pattern.indexOf("*") == pattern.length() - 2;
}

private static class SuffixGlob implements Predicate<String> {
private final String subPath;

private SuffixGlob(final String subPath) {
this.subPath = subPath;
}

@Override
public boolean test(final String path) {
return path.startsWith(subPath)
&& (path.length() == subPath.length() || path.charAt(subPath.length()) == '/');
}
}

private static final class DefaultGlob implements Predicate<String> {

private static final Pattern GLOB_PATTERN = Pattern.compile("\\?|\\*");
private static final String DEFAULT_VARIABLE_PATTERN = "(.*)";
private static final Splitter SLASH = on('/').trimResults().omitEmptyStrings();

private final String pattern;

DefaultGlob(final String pattern) {
this.pattern = pattern;
}

@Override
public boolean test(final String path) {
if (path.startsWith("/") != pattern.startsWith("/")) {
return false;
}

final String[] patternSegments = tokenizePath(pattern);
final String[] pathSegments = tokenizePath(path);

int patternSegmentIndex = 0;
int patternSegmentEnd = patternSegments.length - 1;
int pathSegmentIndex = 0;
int pathIndexEnd = pathSegments.length - 1;

while (patternSegmentIndex <= patternSegmentEnd && pathSegmentIndex <= pathIndexEnd) {
final String patternSegment = patternSegments[patternSegmentIndex];
if ("**".equals(patternSegment)) {
break;
}
if (!match(patternSegment, pathSegments[pathSegmentIndex])) {
return false;
}
patternSegmentIndex++;
pathSegmentIndex++;
}

if (pathSegmentIndex > pathIndexEnd) {
if (patternSegmentIndex > patternSegmentEnd) {
return pattern.endsWith("/") == path.endsWith("/");
}
if (patternSegmentIndex == patternSegmentEnd && patternSegments[patternSegmentIndex].equals("*") && path.endsWith("/")) {
return true;
}
for (int i = patternSegmentIndex; i <= patternSegmentEnd; i++) {
if (!patternSegments[i].equals("**")) {
return false;
}
}
return true;
} else if (patternSegmentIndex > patternSegmentEnd) {
return false;
}

while (patternSegmentIndex <= patternSegmentEnd && pathSegmentIndex <= pathIndexEnd) {
final String patternSegment = patternSegments[patternSegmentEnd];
if (patternSegment.equals("**")) {
break;
}
if (!match(patternSegment, pathSegments[pathIndexEnd])) {
return false;
}
patternSegmentEnd--;
pathIndexEnd--;
}
if (pathSegmentIndex > pathIndexEnd) {
for (int i = patternSegmentIndex; i <= patternSegmentEnd; i++) {
if (!patternSegments[i].equals("**")) {
return false;
}
}
return true;
}

while (patternSegmentIndex != patternSegmentEnd && pathSegmentIndex <= pathIndexEnd) {
int temporaryPatternIndex = -1;
for (int i = patternSegmentIndex + 1; i <= patternSegmentEnd; i++) {
if (patternSegments[i].equals("**")) {
temporaryPatternIndex = i;
break;
}
}
if (temporaryPatternIndex == patternSegmentIndex + 1) {
patternSegmentIndex++;
continue;
}
final int patternLength = (temporaryPatternIndex - patternSegmentIndex - 1);
final int strLength = (pathIndexEnd - pathSegmentIndex + 1);
int foundSegment = -1;

loop:
for (int i = 0; i <= strLength - patternLength; i++) {
for (int j = 0; j < patternLength; j++) {
final String subPat = patternSegments[patternSegmentIndex + j + 1];
final String subStr = pathSegments[pathSegmentIndex + i + j];
if (!match(subPat, subStr)) {
continue loop;
}
}
foundSegment = pathSegmentIndex + i;
break;
}

if (foundSegment == -1) {
return false;
}

patternSegmentIndex = temporaryPatternIndex;
pathSegmentIndex = foundSegment + patternLength;
}

for (int i = patternSegmentIndex; i <= patternSegmentEnd; i++) {
if (!patternSegments[i].equals("**")) {
return false;
}
}

return true;
}

private String[] tokenizePath(final String path) {
final List<String> tokens = SLASH.splitToList(path);
return tokens.toArray(new String[tokens.size()]);
}

private boolean match(final String pattern, final String str) {
return toPattern(pattern).matcher(str).matches();
}

private Pattern toPattern(final String pattern) {
final StringBuilder result = new StringBuilder();
final Matcher matcher = GLOB_PATTERN.matcher(pattern);
int end = 0;
while (matcher.find()) {
result.append(quote(pattern, end, matcher.start()));
final String match = matcher.group();
if ("?".equals(match)) {
result.append('.');
} else if ("*".equals(match)) {
result.append(".*");
} else {
result.append(DEFAULT_VARIABLE_PATTERN);
}
end = matcher.end();
}
result.append(quote(pattern, end, pattern.length()));
return Pattern.compile(result.toString());
}

private String quote(final String s, final int start, final int end) {
if (start == end) {
return "";
}
return Pattern.quote(s.substring(start, end));
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public String format(final Precorrelation<HttpRequest> precorrelation) throws IO
return mapper.writeValueAsString(content);
}

private String renderRequestUri(HttpRequest request) {
private String renderRequestUri(final HttpRequest request) {
final String query = QueryParameters.render(request.getQueryParameters());
return request.getRequestUri() + (query.isEmpty() ? "" : "?" + query);
}
Expand Down
Loading

0 comments on commit 13655ad

Please sign in to comment.