-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merged branch 'pbhenson-response-header-rule' into 'jetty-12.0.x'.
- Loading branch information
Showing
2 changed files
with
275 additions
and
0 deletions.
There are no files selected for viewing
136 changes: 136 additions & 0 deletions
136
...ewrite/src/main/java/org/eclipse/jetty/rewrite/handler/ResponseStatusHeaderRegexRule.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
// | ||
// ======================================================================== | ||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others. | ||
// | ||
// This program and the accompanying materials are made available under the | ||
// terms of the Eclipse Public License v. 2.0 which is available at | ||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 | ||
// which is available at https://www.apache.org/licenses/LICENSE-2.0. | ||
// | ||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 | ||
// ======================================================================== | ||
// | ||
|
||
package org.eclipse.jetty.rewrite.handler; | ||
|
||
import java.io.IOException; | ||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
|
||
import org.eclipse.jetty.http.HttpStatus; | ||
import org.eclipse.jetty.server.Response; | ||
import org.eclipse.jetty.util.Callback; | ||
|
||
/** | ||
* Sends a response with the configured status code whenever the value of the configured request header matches a regular expression. | ||
*/ | ||
public class ResponseStatusHeaderRegexRule extends Rule | ||
{ | ||
private String _headerName; | ||
private Pattern _headerRegex; | ||
private int _code; | ||
private String _message; | ||
|
||
public ResponseStatusHeaderRegexRule() | ||
{ | ||
} | ||
|
||
@Override | ||
public boolean isTerminating() | ||
{ | ||
return true; | ||
} | ||
|
||
public String getHeaderName() | ||
{ | ||
return _headerName; | ||
} | ||
|
||
/** | ||
* Set the http header to match on | ||
* @param headerName the http header to match on | ||
*/ | ||
public void setHeaderName(String headerName) | ||
{ | ||
_headerName = headerName; | ||
} | ||
|
||
public String getHeaderRegex() | ||
{ | ||
return _headerRegex == null ? null : _headerRegex.pattern(); | ||
} | ||
|
||
/** | ||
* Set the regex to match against the header value, null to match on any value | ||
* @param headerRegex regex to match against the header value | ||
*/ | ||
public void setHeaderRegex(String headerRegex) | ||
{ | ||
_headerRegex = headerRegex == null ? null : Pattern.compile(headerRegex); | ||
} | ||
|
||
public int getCode() | ||
{ | ||
return _code; | ||
} | ||
|
||
/** | ||
* Set the http status code returned on a match. | ||
* @param code the http status code | ||
*/ | ||
public void setCode(int code) | ||
{ | ||
if (code < HttpStatus.CONTINUE_100) | ||
throw new IllegalArgumentException("invalid http status code"); | ||
|
||
_code = code; | ||
} | ||
|
||
public String getMessage() | ||
{ | ||
return _message; | ||
} | ||
|
||
/** | ||
* <p>Sets the message for the response body.</p> | ||
* | ||
* @param message the response body message | ||
*/ | ||
public void setMessage(String message) | ||
{ | ||
_message = message; | ||
} | ||
|
||
@Override | ||
public Handler matchAndApply(Handler input) throws IOException | ||
{ | ||
String value = input.getHeaders().get(getHeaderName()); | ||
if (value == null) | ||
return null; | ||
if (_headerRegex == null) | ||
return apply(input, value); | ||
Matcher matcher = _headerRegex.matcher(value); | ||
if (matcher.matches()) | ||
return apply(input, value); | ||
return null; | ||
} | ||
|
||
public Handler apply(Handler input, String value) throws IOException | ||
{ | ||
return new Handler(input) | ||
{ | ||
@Override | ||
protected boolean handle(Response response, Callback callback) | ||
{ | ||
Response.writeError(this, response, callback, _code, _message); | ||
return true; | ||
} | ||
}; | ||
} | ||
|
||
@Override | ||
public String toString() | ||
{ | ||
return "%s[header:%s=%s][response:%d>%s]".formatted(super.toString(), getHeaderName(), getHeaderRegex(), getCode(), getMessage()); | ||
} | ||
} |
139 changes: 139 additions & 0 deletions
139
...te/src/test/java/org/eclipse/jetty/rewrite/handler/ResponseStatusHeaderRegexRuleTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
// | ||
// ======================================================================== | ||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others. | ||
// | ||
// This program and the accompanying materials are made available under the | ||
// terms of the Eclipse Public License v. 2.0 which is available at | ||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 | ||
// which is available at https://www.apache.org/licenses/LICENSE-2.0. | ||
// | ||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 | ||
// ======================================================================== | ||
// | ||
|
||
package org.eclipse.jetty.rewrite.handler; | ||
|
||
import org.eclipse.jetty.http.HttpTester; | ||
import org.eclipse.jetty.server.Handler; | ||
import org.eclipse.jetty.server.Request; | ||
import org.eclipse.jetty.server.Response; | ||
import org.eclipse.jetty.util.Callback; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import static org.hamcrest.MatcherAssert.assertThat; | ||
import static org.hamcrest.Matchers.containsString; | ||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
|
||
public class ResponseStatusHeaderRegexRuleTest extends AbstractRuleTest | ||
{ | ||
private void start(ResponseStatusHeaderRegexRule rule) throws Exception | ||
{ | ||
_rewriteHandler.addRule(rule); | ||
start(new Handler.Abstract() | ||
{ | ||
@Override | ||
public boolean handle(Request request, Response response, Callback callback) | ||
{ | ||
callback.succeeded(); | ||
return true; | ||
} | ||
}); | ||
} | ||
|
||
@Test | ||
public void testNoMatch() throws Exception | ||
{ | ||
ResponseStatusHeaderRegexRule rule = new ResponseStatusHeaderRegexRule(); | ||
rule.setHeaderName("Regex-Test"); | ||
start(rule); | ||
|
||
String request = """ | ||
GET /test HTTP/1.1 | ||
Host: localhost | ||
"""; | ||
|
||
HttpTester.Response response = HttpTester.parseResponse(_connector.getResponse(request)); | ||
assertEquals(200, response.getStatus()); | ||
} | ||
|
||
@Test | ||
public void testMatchNoRegex() throws Exception | ||
{ | ||
ResponseStatusHeaderRegexRule rule = new ResponseStatusHeaderRegexRule(); | ||
rule.setHeaderName("Regex-Test"); | ||
rule.setCode(403); | ||
start(rule); | ||
|
||
String request = """ | ||
GET /test HTTP/1.1 | ||
Host: localhost | ||
Regex-Test: random stuff | ||
"""; | ||
|
||
HttpTester.Response response = HttpTester.parseResponse(_connector.getResponse(request)); | ||
assertEquals(403, response.getStatus()); | ||
} | ||
|
||
@Test | ||
public void testMatchStaticRegexNoMessage() throws Exception | ||
{ | ||
ResponseStatusHeaderRegexRule rule = new ResponseStatusHeaderRegexRule(); | ||
rule.setHeaderName("Regex-Test"); | ||
rule.setHeaderRegex("value"); | ||
rule.setCode(403); | ||
start(rule); | ||
|
||
String request = """ | ||
GET /test HTTP/1.1 | ||
Host: localhost | ||
Regex-Test: value | ||
"""; | ||
|
||
HttpTester.Response response = HttpTester.parseResponse(_connector.getResponse(request)); | ||
assertEquals(403, response.getStatus()); | ||
} | ||
|
||
@Test | ||
public void testMatchRegexNoMessage() throws Exception | ||
{ | ||
ResponseStatusHeaderRegexRule rule = new ResponseStatusHeaderRegexRule(); | ||
rule.setHeaderName("Regex-Test"); | ||
rule.setHeaderRegex(".*value.*"); | ||
rule.setCode(403); | ||
start(rule); | ||
|
||
String request = """ | ||
GET /test HTTP/1.1 | ||
Host: localhost | ||
Regex-Test: this is the value found | ||
"""; | ||
|
||
HttpTester.Response response = HttpTester.parseResponse(_connector.getResponse(request)); | ||
assertEquals(403, response.getStatus()); | ||
} | ||
|
||
@Test | ||
public void testMatchRegexMessage() throws Exception | ||
{ | ||
ResponseStatusHeaderRegexRule rule = new ResponseStatusHeaderRegexRule(); | ||
rule.setHeaderName("Regex-Test"); | ||
rule.setCode(403); | ||
rule.setMessage("Matched"); | ||
start(rule); | ||
|
||
String request = """ | ||
GET /test HTTP/1.1 | ||
Host: localhost | ||
Regex-Test: random stuff | ||
"""; | ||
|
||
HttpTester.Response response = HttpTester.parseResponse(_connector.getResponse(request)); | ||
assertEquals(403, response.getStatus()); | ||
assertThat(response.getContent(), containsString(rule.getMessage())); | ||
} | ||
} |