javaservernanohttpd

Extending NanoHTTPD


I need to write a HTTP server program in Java that

The problem is, in the "home" page I want to show a page that uses local images or JavaScript, and I don't know how to make it work. I mean, I have seen the example in NanoHTTPD home page and it works great, but where should I place the static content (images, js) to be included in the HTML I generate as a response?

Code added as per request.

@nicomp, this example is an adaptation from the example code in https://github.com/NanoHttpd/nanohttpd. The image monkey.png is not served (it appears as a broken img in the browser).

public class Main extends NanoHTTPD {

    public Main() throws IOException {
        super(8080);
        start(NanoHTTPD.SOCKET_READ_TIMEOUT, false);
        System.out.println("\nRunning! Point your browsers to http://localhost:8080/ \n");
    }

    public static void main(String[] args) {
        try {
            new Main();
        } catch (IOException ioe) {
            System.err.println("Couldn't start server:\n" + ioe);
        }
    }

    @Override
    public Response serve(IHTTPSession session) {
        String msg = "<html><body><h1>Hello server</h1>\n";
        msg += "<img src=\"monkey.png\">";
        return newFixedLengthResponse(msg + "</body></html>\n");
    }
}

Solution

  • To include static content such as images and JavaScript in the HTML response, you can create a directory within your project to store these files. Let's call it static.

    Next, you need to serve the static content files from this directory. You can do this by creating a StaticFileServer class that extends the NanoHTTPD class and overrides the serve() method. In the serve() method, you can check if the requested URI starts with the string "/static" and if so, serve the corresponding file from the static directory. Here's an example:

    import fi.iki.elonen.NanoHTTPD;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    
    public class StaticFileServer extends NanoHTTPD {
        private final String staticDir;
    
        public StaticFileServer(int port, String staticDir) {
            super(port);
            this.staticDir = staticDir;
        }
    
        @Override
        public Response serve(IHTTPSession session) {
            String uri = session.getUri();
            if (uri.startsWith("/static")) {
                String filePath = staticDir + uri.substring(7); // Remove "/static" prefix
                try {
                    InputStream inputStream = new FileInputStream(filePath);
                    return newChunkedResponse(Response.Status.OK, getMimeType(filePath), inputStream);
                } catch (IOException e) {
                    return newFixedLengthResponse(Response.Status.NOT_FOUND, NanoHTTPD.MIME_PLAINTEXT, "File not found");
                }
            } else {
                // Handle other requests here
            }
        }
    
        private String getMimeType(String filePath) {
            if (filePath.endsWith(".html")) {
                return NanoHTTPD.MIME_HTML;
            } else if (filePath.endsWith(".css")) {
                return "text/css";
            } else if (filePath.endsWith(".js")) {
                return "application/javascript";
            } else if (filePath.endsWith(".png")) {
                return "image/png";
            } else if (filePath.endsWith(".jpg") || filePath.endsWith(".jpeg")) {
                return "image/jpeg";
            } else if (filePath.endsWith(".gif")) {
                return "image/gif";
            } else {
                return NanoHTTPD.MIME_DEFAULT_BINARY;
            }
        }
    }
    

    In the serve() method, we check if the URI starts with "/static". If it does, we construct the file path by removing the "/static" prefix and appending it to the staticDir path. Then we open an input stream to read the file and return a ChunkedResponse with the file's MIME type. If the file is not found, we return a 404 Not Found response.

    Now that we have our StaticFileServer class, we can use it to serve our static files. In your main HTTP server program, you can create an instance of the StaticFileServer class and pass in the port and the path to the static directory. Then, in the serve() method of your main HTTP server program, you can generate the HTML response and include references to the static files using their URLs:

    public class MainServer extends NanoHTTPD {
        private static final int PORT = 8080;
        private static final String STATIC_DIR = "static";
    
        public MainServer() {
            super(PORT);
        }
    
        @Override
        public Response serve(IHTTPSession session) {
            String uri = session.getUri();
            if (uri.equals("/")) {
                // Generate HTML response with references to static files
                String responseHtml = "<html><head><title>Home</title>" +
                                      "<link rel=\"stylesheet\" href=\"/static/style.css\">" +
                                      "<script src=\"/static/script.js\"></script></head>" +
                                      "<body