<|start_filename|>src/main/java/org/webbitserver/handler/HttpToEventSourceHandler.java<|end_filename|>
package org.webbitserver.handler;

import org.webbitserver.EventSourceHandler;
import org.webbitserver.HttpControl;
import org.webbitserver.HttpHandler;
import org.webbitserver.HttpRequest;
import org.webbitserver.HttpResponse;

public class HttpToEventSourceHandler implements HttpHandler {
    private final EventSourceHandler handler;

    public HttpToEventSourceHandler(EventSourceHandler handler) {
        this.handler = handler;
    }

    @Override
    public void handleHttpRequest(HttpRequest request, HttpResponse response, HttpControl control) throws Exception {
        control.upgradeToEventSourceConnection(handler);
    }
}


<|start_filename|>src/test/java/samples/authentication/content/index.html<|end_filename|>
<!DOCTYPE html>
<html>
    <body>
        Hello! This is a secure page.

        <ul>
            <li><a href="whoami">Who am I? (HTTP example)</a></li>
            <li><a href="websocket.html">Who am I? (WebSocket example)</a></li>
        </ul>
    </body>
</html>

<|start_filename|>src/main/java/org/webbitserver/handler/HttpToWebSocketHandler.java<|end_filename|>
package org.webbitserver.handler;

import org.webbitserver.HttpControl;
import org.webbitserver.HttpHandler;
import org.webbitserver.HttpRequest;
import org.webbitserver.HttpResponse;
import org.webbitserver.WebSocketHandler;

public class HttpToWebSocketHandler implements HttpHandler {
    private final WebSocketHandler handler;

    public HttpToWebSocketHandler(WebSocketHandler handler) {
        this.handler = handler;
    }

    @Override
    public void handleHttpRequest(HttpRequest request, HttpResponse response, HttpControl control) throws Exception {
        control.upgradeToWebSocketConnection(handler);
    }
}


<|start_filename|>src/main/java/org/webbitserver/handler/ServerHeaderHandler.java<|end_filename|>
package org.webbitserver.handler;

import org.webbitserver.HttpControl;
import org.webbitserver.HttpHandler;
import org.webbitserver.HttpRequest;
import org.webbitserver.HttpResponse;

/**
 * Handler that sets the HTTP 'Server' response header.
 */
public class ServerHeaderHandler implements HttpHandler {

    private final String value;

    /**
     * Value to set for HTTP Server header, or null to ensure the header is blank.
     */
    public ServerHeaderHandler(String value) {
        this.value = value;
    }

    @Override
    public void handleHttpRequest(HttpRequest request, HttpResponse response, HttpControl control) throws Exception {
        response.header("Server", value);
        control.nextHandler();
    }
}


<|start_filename|>src/main/java/org/webbitserver/handler/NotFoundHttpHandler.java<|end_filename|>
package org.webbitserver.handler;

import org.webbitserver.HttpControl;
import org.webbitserver.HttpHandler;
import org.webbitserver.HttpRequest;
import org.webbitserver.HttpResponse;

public class NotFoundHttpHandler implements HttpHandler {

    @Override
    public void handleHttpRequest(HttpRequest request, HttpResponse response, HttpControl control) {
        response.status(404).end();
    }

}


<|start_filename|>src/main/java/org/webbitserver/handler/exceptions/PrintStackTraceExceptionHandler.java<|end_filename|>
package org.webbitserver.handler.exceptions;

import java.io.PrintStream;

/**
 * Exception handler that dumps the stack trace.
 *
 * @see org.webbitserver.WebServer#connectionExceptionHandler(java.lang.Thread.UncaughtExceptionHandler)
 * @see org.webbitserver.WebServer#uncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler)
 */
public class PrintStackTraceExceptionHandler implements Thread.UncaughtExceptionHandler {

    private final PrintStream out;

    public PrintStackTraceExceptionHandler() {
        this(System.err);
    }

    public PrintStackTraceExceptionHandler(PrintStream out) {
        this.out = out;
    }

    @Override
    public void uncaughtException(Thread t, Throwable exception) {
        exception.printStackTrace(out);
    }
}


<|start_filename|>src/main/java/org/webbitserver/handler/AliasHandler.java<|end_filename|>
package org.webbitserver.handler;

import org.webbitserver.HttpControl;
import org.webbitserver.HttpHandler;
import org.webbitserver.HttpRequest;
import org.webbitserver.HttpResponse;

public class AliasHandler implements HttpHandler {
    private final String uri;

    public AliasHandler(String uri) {
        this.uri = uri;
    }

    @Override
    public void handleHttpRequest(HttpRequest request, HttpResponse response, HttpControl control) throws Exception {
        request.uri(uri);
        control.nextHandler(request, response);
    }
}


<|start_filename|>src/main/java/org/webbitserver/stub/StubDataHolder.java<|end_filename|>
package org.webbitserver.stub;

import org.webbitserver.DataHolder;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class StubDataHolder implements DataHolder {

    private Map<String, Object> data = new HashMap<String, Object>();

    @Override
    public Map<String, Object> data() {
        return data;
    }

    @Override
    public Object data(String key) {
        return data.get(key);
    }

    @Override
    public DataHolder data(String key, Object value) {
        data.put(key, value);
        return this;
    }

    @Override
    public Set<String> dataKeys() {
        return data.keySet();
    }
}


<|start_filename|>src/main/java/org/webbitserver/EventSourceHandler.java<|end_filename|>
package org.webbitserver;

public interface EventSourceHandler {
    void onOpen(EventSourceConnection connection) throws Exception;

    void onClose(EventSourceConnection connection) throws Exception;
}


<|start_filename|>src/main/java/org/webbitserver/DataHolder.java<|end_filename|>
package org.webbitserver;

import java.util.Map;
import java.util.Set;

/**
 * Objects implementing this interface can have arbitrary named values associated with
 * them, making it easy to pass data around an application.
 *
 * @author <NAME>
 */
public interface DataHolder {

    /**
     * Arbitrary data that can be stored for the lifetime of the connection.
     */
    Map<String, Object> data();

    /**
     * Retrieve data value by key.
     *
     * @see #data()
     */
    Object data(String key);

    /**
     * Store data value by key.
     *
     * @see #data()
     */
    DataHolder data(String key, Object value);

    /**
     * List data keys.
     *
     * @see #data()
     */
    Set<String> dataKeys();

}


<|start_filename|>src/main/java/org/webbitserver/handler/DelayedHttpHandler.java<|end_filename|>
package org.webbitserver.handler;

import org.webbitserver.HttpControl;
import org.webbitserver.HttpHandler;
import org.webbitserver.HttpRequest;
import org.webbitserver.HttpResponse;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executor;

/**
 * Wraps a standard HttpHandler, and will introduce an artificial delay. Useful for testing
 * how things will behave when they are slow.
 */
public class DelayedHttpHandler implements HttpHandler {

    private final Executor executor;
    private Timer timer;
    private final long delayInMillis;
    private final HttpHandler handler;

    public DelayedHttpHandler(Executor executor, long delayInMillis, HttpHandler handler) {
        this.delayInMillis = delayInMillis;
        this.handler = handler;
        timer = new Timer();
        this.executor = executor;
    }

    @Override
    public void handleHttpRequest(final HttpRequest request, final HttpResponse response, final HttpControl control) throws Exception {
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            handler.handleHttpRequest(request, response, control);
                        } catch (Exception e) {
                            // TODO
                            e.printStackTrace();
                        }
                    }
                });
            }
        }, delayInMillis);
    }
}


<|start_filename|>src/main/java/org/webbitserver/handler/exceptions/SilentExceptionHandler.java<|end_filename|>
package org.webbitserver.handler.exceptions;

/**
 * Exception handler that does nothing. Exceptions are silently discarded.
 *
 * @see org.webbitserver.WebServer#connectionExceptionHandler(java.lang.Thread.UncaughtExceptionHandler)
 * @see org.webbitserver.WebServer#uncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler)
 */
public class SilentExceptionHandler implements Thread.UncaughtExceptionHandler {

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        // Do nothing.
    }

}



<|start_filename|>src/main/java/org/webbitserver/handler/logging/LoggingEventSourceHandler.java<|end_filename|>
package org.webbitserver.handler.logging;

import org.webbitserver.EventSourceConnection;
import org.webbitserver.EventSourceHandler;

class LoggingEventSourceHandler implements EventSourceHandler {

    private final LogSink logSink;
    private final EventSourceConnection loggingConnection;
    private final EventSourceHandler handler;

    LoggingEventSourceHandler(LogSink logSink, EventSourceConnection loggingConnection, EventSourceHandler handler) {
        this.logSink = logSink;
        this.loggingConnection = loggingConnection;
        this.handler = handler;
    }

    @Override
    public void onOpen(EventSourceConnection connection) throws Exception {
        logSink.eventSourceConnectionOpen(connection);
        handler.onOpen(loggingConnection);
    }

    @Override
    public void onClose(EventSourceConnection connection) throws Exception {
        logSink.eventSourceConnectionClose(connection);
        logSink.httpEnd(connection.httpRequest());
        handler.onClose(loggingConnection);
    }
}


<|start_filename|>src/main/java/org/webbitserver/handler/StringHttpHandler.java<|end_filename|>
package org.webbitserver.handler;

import org.webbitserver.HttpControl;
import org.webbitserver.HttpHandler;
import org.webbitserver.HttpRequest;
import org.webbitserver.HttpResponse;

import java.nio.charset.Charset;

public class StringHttpHandler implements HttpHandler {

    private final String contentType;
    private final String body;
    private final Charset charset;

    public StringHttpHandler(String contentType, String body) {
        this(contentType, body, Charset.forName("UTF-8"));
    }

    public StringHttpHandler(String contentType, String body, Charset charset) {
        this.contentType = contentType;
        this.charset = charset;
        this.body = body;
    }

    @Override
    public void handleHttpRequest(HttpRequest request, HttpResponse response, HttpControl control) {
        response.charset(charset)
                .header("Content-Type", contentType + "; charset=" + charset.name())
                .header("Content-Length", body.length())
                .content(body)
                .end();
    }

}


<|start_filename|>src/test/java/org/webbitserver/helpers/Base64Test.java<|end_filename|>
package org.webbitserver.helpers;

import org.junit.Test;

import static org.junit.Assert.assertEquals;

/**
 * This code originally came from the XStream http://xstream.codehaus.org project by <NAME>. Relicensed to Webbit.
 */
public class Base64Test {

    @Test
    public void testEncodesEntireByteArrayAsString() {
        byte input[] = "hello world".getBytes();
        String expected = "aGVsbG8gd29ybGQ=";
        assertEquals(expected, Base64.encode(input));
        assertByteArrayEquals(input, Base64.decode(expected));
    }

    @Test
    public void wrapsLinesAt76Chars() {
        byte input[] = ("hello world. hello world. hello world. hello world. hello world. hello world. hello world. "
                + "hello world. hello world. hello world. hello world. hello world. hello world. hello world. ").getBytes();
        String expected = "<KEY>"
                + "<KEY>"
                + "<KEY>"
                + "<KEY>;
        assertEquals(expected, Base64.encode(input));
        assertByteArrayEquals(input, Base64.decode(expected));
    }

    @Test
    public void padsSingleMissingByteWhenNotMultipleOfThree() {
        byte input[] = {1, 2, 3, 4, 5};
        String expected = "AQIDBAU=";
        assertEquals(expected, Base64.encode(input));
        assertByteArrayEquals(input, Base64.decode(expected));
    }

    @Test
    public void padsDoubleMissingByteWhenNotMultipleOfThree() {
        byte input[] = {1, 2, 3, 4};
        String expected = "AQIDBA==";
        assertEquals(expected, Base64.encode(input));
        assertByteArrayEquals(input, Base64.decode(expected));
    }

    @Test
    public void doesNotPadWhenMultipleOfThree() {
        byte input[] = {1, 2, 3, 4, 5, 6};
        String expected = "AQIDBAUG";
        assertEquals(expected, Base64.encode(input));
        assertByteArrayEquals(input, Base64.decode(expected));
    }

    @Test
    public void handlesAllPositiveBytes() {
        byte input[] = new byte[127];
        for (int i = 0; i < 126; i++) input[i] = (byte) (i + 1);
        String expected = "AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyAhIiMkJSYnKCkqKywtLi8wMTIzNDU2Nzg5\n"
                + "O<KEY>"
                + "c3R1dnd4eXp7fH1+AA==";
        assertEquals(expected, Base64.encode(input));
        assertByteArrayEquals(input, Base64.decode(expected));
    }

    @Test
    public void handlesAllNegativeBytes() {
        byte input[] = new byte[128];
        for (int i = 0; i < 127; i++) input[i] = (byte) (-1 - i);
        String expected = "//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjH\n"
                + "xsXEw8LBwL++vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI+O\n"
                + "jYyLiomIh4aFhIOCgQA=";
        assertEquals(expected, Base64.encode(input));
        assertByteArrayEquals(input, Base64.decode(expected));
    }

    @Test
    public void handlesZeroByte() {
        byte input[] = {0, 0, 0, 0};
        String expected = "AAAAAA==";
        assertEquals(expected, Base64.encode(input));
        assertByteArrayEquals(input, Base64.decode(expected));
    }

    @Test
    public void producesEmptyStringWhenNoBytesGiven() {
        byte input[] = new byte[0];
        String expected = "";
        assertEquals(expected, Base64.encode(input));
        assertByteArrayEquals(input, Base64.decode(expected));
    }

    protected void assertByteArrayEquals(byte expected[], byte actual[]) {
        assertEquals(dumpBytes(expected), dumpBytes(actual));
    }

    private String dumpBytes(byte bytes[]) {
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            result.append(bytes[i]).append(' ');
            if (bytes[i] < 100) result.append(' ');
            if (bytes[i] < 10) result.append(' ');
            if (bytes[i] >= 0) result.append(' ');
            if (i % 16 == 15) result.append('\n');
        }
        return result.toString();
    }
}


<|start_filename|>src/test/java/samples/authentication/WhoAmIHttpHandler.java<|end_filename|>
package samples.authentication;

import org.webbitserver.HttpControl;
import org.webbitserver.HttpHandler;
import org.webbitserver.HttpRequest;
import org.webbitserver.HttpResponse;
import org.webbitserver.handler.authentication.BasicAuthenticationHandler;

/**
 * Simple handler that shows the user who they are logged in as, using plain ol' HTTP
 */
public class WhoAmIHttpHandler implements HttpHandler {
    @Override
    public void handleHttpRequest(HttpRequest request, HttpResponse response, HttpControl control) throws Exception {
        response.header("Content-type", "text/html")
            .content("You are: " + request.data(BasicAuthenticationHandler.USERNAME))
            .end();
    }
}


<|start_filename|>src/main/java/org/webbitserver/HttpHandler.java<|end_filename|>
package org.webbitserver;

public interface HttpHandler {
    void handleHttpRequest(HttpRequest request, HttpResponse response, HttpControl control) throws Exception;
}


<|start_filename|>src/main/java/org/webbitserver/wrapper/HttpRequestWrapper.java<|end_filename|>
package org.webbitserver.wrapper;

import org.webbitserver.HttpRequest;

import java.net.HttpCookie;
import java.net.SocketAddress;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class HttpRequestWrapper implements HttpRequest {

    private HttpRequest request;

    public HttpRequestWrapper(HttpRequest request) {
        this.request = request;
    }

    public HttpRequest underlyingRequest() {
        return request;
    }

    public HttpRequestWrapper underlyingRequest(HttpRequest request) {
        this.request = request;
        return this;
    }

    public HttpRequest originalRequest() {
        if (request instanceof HttpRequestWrapper) {
            HttpRequestWrapper wrapper = (HttpRequestWrapper) request;
            return wrapper.originalRequest();
        } else {
            return request;
        }
    }

    @Override
    public String uri() {
        return request.uri();
    }

    @Override
    public HttpRequestWrapper uri(String uri) {
        request.uri(uri);
        return this;
    }

    @Override
    public String header(String name) {
        return request.header(name);
    }

    @Override
    public boolean hasHeader(String name) {
        return request.hasHeader(name);
    }

    @Override
    public List<HttpCookie> cookies() {
        return request.cookies();
    }

    @Override
    public HttpCookie cookie(String name) {
        return request.cookie(name);
    }

    @Override
    public String queryParam(String key) {
        return request.queryParam(key);
    }

    @Override
    public List<String> queryParams(String key) {
        return request.queryParams(key);
    }

    @Override
    public Set<String> queryParamKeys() {
        return request.queryParamKeys();
    }

    @Override
    public String postParam(String key) {
        return request.postParam(key);
    }

    @Override
    public List<String> postParams(String key) {
        return request.postParams(key);
    }

    @Override
    public Set<String> postParamKeys() {
        return request.postParamKeys();
    }

    @Override
    public String cookieValue(String name) {
        return request.cookieValue(name);
    }

    @Override
    public List<String> headers(String name) {
        return request.headers(name);
    }

    @Override
    public List<Map.Entry<String, String>> allHeaders() {
        return request.allHeaders();
    }

    @Override
    public String method() {
        return request.method();
    }

    @Override
    public String body() {
        return request.body();
    }

    @Override
    public byte[] bodyAsBytes() {
        return request.bodyAsBytes();
    }

    @Override
    public Map<String, Object> data() {
        return request.data();
    }

    @Override
    public Object data(String key) {
        return request.data(key);
    }

    @Override
    public HttpRequestWrapper data(String key, Object value) {
        request.data(key, value);
        return this;
    }

    @Override
    public Set<String> dataKeys() {
        return request.dataKeys();
    }

    @Override
    public SocketAddress remoteAddress() {
        return request.remoteAddress();
    }

    @Override
    public Object id() {
        return request.id();
    }

    @Override
    public long timestamp() {
        return request.timestamp();
    }
}
