All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.arteam.embedhttp.EmbeddedHttpServer Maven / Gradle / Ivy

package com.github.arteam.embedhttp;

import com.sun.net.httpserver.Authenticator;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpContext;
import com.sun.net.httpserver.HttpServer;

import java.io.*;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Represents a simple HTTP server (a facade around {@link com.sun.net.httpserver.HttpServer for unit testing.
 * The server is started after invoking the {@link EmbeddedHttpServer#start()} method. It's a good practice
 * to shutdown it with {@link EmbeddedHttpServer#stop()} method.
 *
 * @author Artem Prigoda
 * @since 05.06.16
 */
public class EmbeddedHttpServer implements Closeable {

    private HttpServer sunHttpServer;
    private List handlers = new ArrayList<>();

    /**
     * Adds a new handler to the server to a path.
     */
    public EmbeddedHttpServer addHandler(String path, HttpHandler handler) {
        return addHandler(path, handler, null);
    }

    /**
     * Adds a new handler to the server to a path with an authenticator.
     */
    public EmbeddedHttpServer addHandler(String path, HttpHandler handler, Authenticator authenticator) {
        handlers.add(new HttpHandlerConfig(path, handler, authenticator));
        return this;
    }

    /**
     * Starts up the current server on a free port on the localhost.
     */
    public EmbeddedHttpServer start() {
        return start(0);
    }

    /**
     * Starts up the server on the provided port on the provided port on the localhost.
     */
    public EmbeddedHttpServer start(int port) {
        return start(new InetSocketAddress(InetAddress.getLoopbackAddress(), port));
    }

    /**
     * Starts up the server on provided address.
     */
    public EmbeddedHttpServer start(InetSocketAddress address) {
        try {
            sunHttpServer = HttpServer.create(address, 50);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        for (HttpHandlerConfig config : handlers) {
            HttpContext context = sunHttpServer.createContext(config.path, httpExchange -> {
                try {
                    Headers requestHeaders = httpExchange.getRequestHeaders();
                    HttpResponse response = new HttpResponse();
                    config.httpHandler.handle(new HttpRequest(httpExchange.getRequestMethod(),
                            httpExchange.getRequestURI(), httpExchange.getProtocol(), requestHeaders,
                            readFromStream(httpExchange.getRequestBody())), response);
                    for (Map.Entry> e : response.getHeaders().entrySet()) {
                        httpExchange.getResponseHeaders().put(e.getKey(), e.getValue());
                    }
                    byte[] byteBody = response.getBody().getBytes(StandardCharsets.UTF_8);
                    httpExchange.sendResponseHeaders(response.getStatusCode(), byteBody.length);
                    httpExchange.getResponseBody().write(byteBody);
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    httpExchange.close();
                }
            });
            if (config.authenticator != null) {
                context.setAuthenticator(config.authenticator);
            }
        }
        sunHttpServer.start();
        return this;
    }

    /**
     * Stops the current server and frees resources.
     */
    public void stop() {
        sunHttpServer.stop(0);
    }

    /**
     * Invokes {@link EmbeddedHttpServer#stop()}.
     */
    @Override
    public void close() throws IOException {
        stop();
    }

    /**
     * Get the port on which server has been started.
     */
    public int getPort() {
        return sunHttpServer.getAddress().getPort();
    }

    /**
     * Gets the host on which server has been bound.
     */
    public String getBindHost() {
        return sunHttpServer.getAddress().getHostName();
    }

    /**
     * Reads the provided input stream to a string in the UTF-8 encoding
     */
    private static String readFromStream(InputStream inputStream) throws IOException {
        try (Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) {
            StringBuilder stringBuilder = new StringBuilder();
            CharBuffer readBuffer = CharBuffer.allocate(1024);
            while (reader.read(readBuffer) != -1) {
                readBuffer.flip();
                stringBuilder.append(readBuffer);
                readBuffer.clear();
            }
            return stringBuilder.toString();
        }
    }


    private static class HttpHandlerConfig {

        private final String path;
        private final HttpHandler httpHandler;
        private final Authenticator authenticator;

        HttpHandlerConfig(String path, HttpHandler httpHandler, Authenticator authenticator) {
            this.path = path;
            this.httpHandler = httpHandler;
            this.authenticator = authenticator;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy