2

I'm trying to write a simple http server, using com.sun.net.httpserver class. I send html file (index.html) to browser on startup, but I don't know how to include an external css file. It works when css code is placed inside html file. I know, that browser should send a request, asking server for css file, but I'm not sure how to receive this request and send back this file to browser. I attach a fragment of my code below, if it could be helpful.

private void startServer()
{
    try
    {
        server = HttpServer.create(new InetSocketAddress(8000), 0);
    } 
    catch (IOException e) 
    {
        System.err.println("Exception in class : " + e.getMessage());
    }
    server.createContext("/", new indexHandler());
    server.setExecutor(null);
    server.start();
}

private static class indexHandler implements HttpHandler
{
    public void handle(HttpExchange httpExchange) throws IOException
    {   
        Headers header = httpExchange.getResponseHeaders();
        header.add("Content-Type", "text/html");
        sendIndexFile(httpExchange);            
    }
}

static private void sendIndexFile(HttpExchange httpExchange) throws IOException
{
    File indexFile = new File(getIndexFilePath());
    byte [] indexFileByteArray = new byte[(int)indexFile.length()];

    BufferedInputStream requestStream = new BufferedInputStream(new FileInputStream(indexFile));
    requestStream.read(indexFileByteArray, 0, indexFileByteArray.length);

    httpExchange.sendResponseHeaders(200, indexFile.length());
    OutputStream responseStream = httpExchange.getResponseBody();
    responseStream.write(indexFileByteArray, 0, indexFileByteArray.length);
    responseStream.close();
}
6
  • what this line of code does server.createContext("/", new indexHandler());? Commented Mar 21, 2016 at 18:29
  • It creates a http context associated with path "/". All requests for this path are handled by indexHandler object. Commented Mar 21, 2016 at 18:34
  • If you want to write an HTTP server, you need to understand how the relationship between an HTTP request and its response. Telling you that would amount to a tutorial. Commented Mar 21, 2016 at 18:36
  • @bizkhit right, what should you do to accept another path? (css in your case) Commented Mar 21, 2016 at 18:47
  • Create new context? But I don't know how this path should looks like. Let's assume I have my css file in C:\MyApp\src\com\xyz\view\style.css. Should I give the whole path to createContext method? Commented Mar 21, 2016 at 19:08

1 Answer 1

3

There is no built-in method for handling static content. You have two options.

Either use a light-weight webserver for static content like nginx, but than distribution of your application will be more difficult.

Or create your own file serving classes. For that, you have to create a new context in your web server:

int port = 8080;
HttpServer server = HttpServer.create(new InetSocketAddress(port), 0);
// ... more server contexts
server.createContext("/static", new StaticFileServer());

And than create the class that will serve your static files.

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;

@SuppressWarnings("restriction")
public class StaticFileServer implements HttpHandler {

    @Override
    public void handle(HttpExchange exchange) throws IOException {
        String fileId = exchange.getRequestURI().getPath();
        File file = getFile(fileId);
        if (file == null) {
            String response = "Error 404 File not found.";
            exchange.sendResponseHeaders(404, response.length());
            OutputStream output = exchange.getResponseBody();
            output.write(response.getBytes());
            output.flush();
            output.close();
        } else {
            exchange.sendResponseHeaders(200, 0);
            OutputStream output = exchange.getResponseBody();
            FileInputStream fs = new FileInputStream(file);
            final byte[] buffer = new byte[0x10000];
            int count = 0;
            while ((count = fs.read(buffer)) >= 0) {
                output.write(buffer, 0, count);
            }
            output.flush();
            output.close();
            fs.close();
        }
    }

    private File getFile(String fileId) {
        // TODO retrieve the file associated with the id
        return null;
    }
}

For the method getFile(String fileId); you can implement any way of retrieving the file associated with the fileId. A good option is to create a file structure mirroring the URL hierarchy. If you don't have many files, than you can use a HashMap to store valid id-file pairs.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.