1

I use below code to open https server. When I go to my ip address: xx.xxx.xxx.xxx the zip file downloads normally. But when I access the ip: https://xx.xxx.xxx.xxx/, the zip file is not automatically downloaded I am a newbie to http so if possible please give me an example code. Thank you

public class Main implements HttpHandler {
    @Override
    public void handle(HttpExchange exchange) throws IOException {
        Headers h = exchange.getResponseHeaders();
        h.add("Content-Type", "application/octet-stream");
        h.add("Content-Disposition", "attachment; filename=Pack.zip");
        exchange.sendResponseHeaders(200, 0);
        OutputStream os = exchange.getResponseBody();
        Files.newInputStream(Paths.get("C://Pack.zip")).transferTo(os);
        os.close();
    }

    public static void main(String[] args) throws Exception {
        HttpServer server = HttpServer.create(new InetSocketAddress(36), 0);
        server.createContext("/", new Main());
        server.start();
    }
}
  • Can you add the log or output you have? We can then read the error you're facing – Marc Le Bihan Jun 19 '23 at 16:28
  • @MarcLeBihan It's not a bug, everything is fine when I go directly to the ip. But when I still access that ip but with the beginning 'https://' then the file is not downloaded – Nguyễn Khôi Jun 19 '23 at 16:35
  • You're trying to access it over the HTTPS protocol but your code is only hosting an HTTP server. You need something like `server.setHttpsConfigurator(new HttpsConfigurator(createSSLContext()));` – Kon Jun 19 '23 at 16:38
  • @Kon There is no method server.setHttpsConfigurator() – Nguyễn Khôi Jun 19 '23 at 16:47
  • You need to start with `HttpsServer server = HttpsServer.create(new InetSocketAddress(36), 0);` – g00se Jun 19 '23 at 17:03

1 Answers1

1

I think, what you are searching for is this answer here. As described here, your server might work without the use of certificates, however, you should provide them, otherwise https would have no effect, compared to http.

Checkout the first link, it's describing very detailed, what you will need, to set up a simple Java https-Server. The second answer (not the one with the highest ranking) is even closer to your code.

EDIT (due to the comment below):

So, based on the above link, you could do the following: First you could create a self-signed ssl-cert using the following command:

keytool -genkeypair -keyalg RSA -alias selfsigned -keystore testkey.jks -storepass password -validity 360 -keysize 2048

Its name is testkey.jks, which you could use in your code to load the SSL-Context (I wrote a few TODOs in the code, so you'll know, which parts you will have to adjust / edit).

import java.io.*;
import java.net.InetSocketAddress;
import java.lang.*;
import com.sun.net.httpserver.HttpsServer;

import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyStore;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManagerFactory;
import com.sun.net.httpserver.*;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLContext;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;

public class Main implements HttpHandler {

    @Override
    public void handle(HttpExchange exchange) throws IOException {
        HttpsExchange httpsExchange = (HttpsExchange) exchange;
        Headers h = httpsExchange.getResponseHeaders();
        h.add("Content-Type", "application/octet-stream");
        h.add("Content-Disposition", "attachment; filename=Pack.zip");
        httpsExchange.sendResponseHeaders(200, 0);
        OutputStream os = httpsExchange.getResponseBody();
        Files.newInputStream(Paths.get("C://Pack.zip")).transferTo(os);
        os.close();
    }

    public static void main(String[] args) throws Exception {
        HttpsServer server = HttpsServer.create(new InetSocketAddress(36), 0);
        server.createContext("/", new Main());
        setHttpsConfigurator(server);
        server.setExecutor(null); // creates a default executor
        server.start();
    }
    
    private static void setHttpsConfigurator(HttpsServer server) {
        SSLContext sslContext = loadSSLContext();
        server.setHttpsConfigurator(new HttpsConfigurator(sslContext) {
            public void configure(HttpsParameters params) {
                try {
                    // initialise the SSL context
                    SSLContext context = getSSLContext();
                    SSLEngine engine = context.createSSLEngine();
                    params.setNeedClientAuth(false);
                    params.setCipherSuites(engine.getEnabledCipherSuites());
                    params.setProtocols(engine.getEnabledProtocols());

                    // Set the SSL parameters
                    SSLParameters sslParameters = context.getSupportedSSLParameters();
                    params.setSSLParameters(sslParameters);

                } catch (Exception ex) {
                    // TODO : handle or rethrow
                }
            }
        });
    }

    private static SSLContext loadSSLContext() {
        try {

            // initialise the SSL-Context
            SSLContext sslContext = SSLContext.getInstance("TLS");

            // initialise the keystore
            // TODO : replace "password" with the password you used when generating your keystore
            char[] password = "password".toCharArray();
            KeyStore ks = KeyStore.getInstance("JKS");
            // TODO : the path to YOUR Keystore
            FileInputStream fis = new FileInputStream("testkey.jks");
            ks.load(fis, password);

            // setup the key manager factory
            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
            kmf.init(ks, password);

            // setup the trust manager factory
            TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
            tmf.init(ks);

            // setup the HTTPS context and parameters
            sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
            return sslContext;

        } catch (Exception exception) {
            // TODO : handle or rethrow
            exception.printStackTrace();
        }
        throw new RuntimeException("Failed to load SSL-Context");
    }
}

Let us know, if there are problems. I changed the code, so it looks like the code you initially provided. Feel free to refactor.

tim-danger
  • 11
  • 4