Skip to content

Commit

Permalink
Escape html special characters in default error response generator.
Browse files Browse the repository at this point in the history
  • Loading branch information
tokuhirom authored and NiteshKant committed Nov 10, 2016
1 parent 608ec08 commit 310a046
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@

import java.io.PrintStream;
import java.nio.charset.Charset;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* @author Nitesh Kant
Expand Down Expand Up @@ -63,7 +65,7 @@ public void updateResponse(HttpServerResponse<O> response, Throwable error) {
printStream = new PrintStream(new ByteBufOutputStream(buffer));
error.printStackTrace(printStream);
String errorPage = ERROR_HTML_TEMPLATE.replace(STACKTRACE_TEMPLATE_VARIABLE,
buffer.toString(Charset.defaultCharset()));
escapeHtml(buffer.toString(Charset.defaultCharset())));
response.writeString(errorPage);
} finally {
ReferenceCountUtil.release(buffer);
Expand All @@ -78,6 +80,41 @@ public void updateResponse(HttpServerResponse<O> response, Throwable error) {
}
}

private String escapeHtml(String src) {
Pattern compile = Pattern.compile("[<>\"&`{}']");
Matcher matcher = compile.matcher(src);
StringBuffer buffer = new StringBuffer();
while (matcher.find()) {
String rep = matcher.group();
matcher.appendReplacement(buffer, escapeChar(rep));
}
matcher.appendTail(buffer);
return buffer.toString();
}

private String escapeChar(String c) {
switch (c.charAt(0)) {
case '<':
return "&lt;";
case '>':
return "&gt;";
case '"':
return "&quot;";
case '&':
return "&amp;";
case '`':
return "&#96;";
case '{':
return "&#123;";
case '}':
return "&#125;";
case '\'':
return "&#39;";
default:
return c;
}
}

public static void main(String[] args) {
RxNetty.createHttpServer(8888, new RequestHandler<ByteBuf, ByteBuf>() {
@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package io.reactivex.netty.protocol.http.server;

import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.reactivex.netty.RxNetty;
import io.reactivex.netty.protocol.http.client.HttpClientRequest;
import io.reactivex.netty.protocol.http.client.HttpClientResponse;
import io.reactivex.netty.server.RxServer;
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
import org.junit.matchers.JUnitMatchers;
import rx.Observable;
import rx.functions.Func1;
import rx.functions.Func2;

import java.nio.charset.Charset;

public class DefaultErrorResponseGeneratorTest {
private RxServer<HttpServerRequest<ByteBuf>, HttpServerResponse<ByteBuf>> server;

@After
public void tearDown() throws Exception {
if (null != server) {
server.shutdown();
}
}

@Test
public void testErrorGenerator() throws Exception {
server = RxNetty.createHttpServer(0, new RequestHandler<ByteBuf, ByteBuf>() {
@Override
public Observable<Void> handle(
HttpServerRequest<ByteBuf> request,
HttpServerResponse<ByteBuf> response) {
return Observable
.error(new IllegalStateException(
"I always throw an error<>'&\"{}."));
}
}).start();

int port = server.getServerPort();

HttpClientRequest<ByteBuf> request =
HttpClientRequest.createGet("/");

String html =
RxNetty.createHttpClient("localhost", port).submit(request)
.flatMap(new Func1<HttpClientResponse<ByteBuf>, Observable<String>>() {
@Override
public Observable<String> call(HttpClientResponse<ByteBuf> response) {
return response.getContent().map(new Func1<ByteBuf, String>() {
@Override
public String call(ByteBuf byteBuf) {
return byteBuf.toString(Charset.forName("ASCII"));
}
}).reduce(new Func2<String, String, String>() {
@Override
public String call(String s, String s2) {
return s + s2;
}
});
}
}).toBlocking().last();

Assert.assertThat("Unexpected response status",
html,
JUnitMatchers.containsString("I always throw an error&lt;&gt;&#39;&amp;&quot;&#123;&#125;.\n"));
}
}

0 comments on commit 310a046

Please sign in to comment.