Monday, June 8, 2026

Java: http and https (self sign certificate)

install mkcert


# apt install mkcert

go to root of netbeans project and create self sign certificate


$ mkcert localhost
Created a new local CA 💥
Note: the local CA is not installed in the system trust store.
Note: the local CA is not installed in the Firefox and/or Chrome/Chromium trust store.
Run "mkcert -install" for certificates to be trusted automatically ⚠️

Created a new certificate valid for the following names 📜
 - "localhost"

The certificate is at "./localhost.pem" and the key at "./localhost-key.pem" ✅

It will expire on 8 September 2028 🗓

Convert to PKCS 12


$ openssl pkcs12 -export \
  -in localhost.pem \
  -inkey localhost-key.pem \
  -out localhost.p12 \
  -name localhost
Enter Export Password:
Verifying - Enter Export Password:

main java code


/*
 * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
 */

package com.dedetok.ddtescpos;

import com.alibaba.fastjson2.JSONObject;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpsConfigurator;
import com.sun.net.httpserver.HttpsServer;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;


/**
 *
 * @author dedetok
 */
public class DdtEscPos {

    final static String serviceString = "DdtEscPos";
    final static String serviceVersion = "1.0";
    
    public static void main(String[] args) {
        System.out.println(serviceString+" "+serviceVersion);
        
        // ================= 
        // safe port  49152 to 65535
        // build http
        int httpPort = 50001;
        // build https
        int httpsPort = 50002;
        try {
            HttpServer httpServer = createHttpService(httpPort);
            HttpsServer httpsServer = createHttpsService(httpsPort);
            
            Runtime.getRuntime().addShutdownHook(new Thread(() -> {
                System.out.println("Stopping HTTP & HTTPS server...");
                httpServer.stop(5); // stop 5 second
                System.out.println("HTTP server stopped");
                httpsServer.stop(5); // stop 5 second
                System.out.println("HTTPS server stopped");

            }));
            httpServer.start();
            System.out.println("HTTP server running on http://localhost:" + httpPort);
            httpsServer.start();
            System.out.println("HTTPS server running on http://localhost:" + httpsPort);

        } catch (IOException | KeyStoreException | NoSuchAlgorithmException | CertificateException | UnrecoverableKeyException | KeyManagementException ex) {
            System.getLogger(DdtEscPos.class.getName()).log(System.Logger.Level.ERROR, (String) null, ex);
        }
    }

    /*
     * create http service in httpPort
     */
    static HttpsServer createHttpsService(int httpsPort) throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException, KeyManagementException {
        // Load PKCS12 keystore
        char[] password = "escpos".toCharArray();
        KeyStore ks = KeyStore.getInstance("PKCS12");
        try (FileInputStream fis = new FileInputStream("localhost.p12")) {
            ks.load(fis, password);
        }

        KeyManagerFactory kmf = KeyManagerFactory.getInstance(
                KeyManagerFactory.getDefaultAlgorithm());
        
        kmf.init(ks, password);

        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(kmf.getKeyManagers(), null, null);

        // Create HTTPS server
        HttpsServer httpsServer =
                HttpsServer.create(
                        new InetSocketAddress("localhost", httpsPort),
                        0);        
    
        httpsServer.setHttpsConfigurator(new HttpsConfigurator(sslContext));
        
        // Register endpoints
        httpsServer.createContext("/", DdtEscPos::handleHttpRequest);
        httpsServer.createContext("/printjson", DdtEscPos::handlePrintJson);        
        
        return httpsServer;
    }
    
    /*
     * create http service in httpPort
     */
    static HttpServer createHttpService(int httpPort) throws IOException {
        HttpServer httpServer =
                HttpServer.create(new InetSocketAddress("localhost", httpPort), 0);
        
        httpServer.createContext("/", DdtEscPos::handleHttpRequest);
        httpServer.createContext("/printjson", DdtEscPos::handlePrintJson);
        return httpServer;
    }

    /*
     * handling /
     */
    static void handleHttpRequest(HttpExchange exchange) throws IOException {
        // CORS
        exchange.getResponseHeaders().add(
                "Access-Control-Allow-Origin", "*");

        exchange.getResponseHeaders().add(
                "Access-Control-Allow-Headers",
                "Content-Type, Authorization");

        exchange.getResponseHeaders().add(
        "Access-Control-Allow-Methods",
        "GET, POST, OPTIONS");

        if ("OPTIONS".equalsIgnoreCase(exchange.getRequestMethod())) {
            exchange.sendResponseHeaders(204, -1);
            return;
        }
        
        // UTF-8 text response
        exchange.getResponseHeaders().add(
                "Content-Type",
                "text/plain; charset=UTF-8");
        
        String response = infoService(exchange).toString();

        byte[] responseBytes = response.getBytes(StandardCharsets.UTF_8);

        exchange.sendResponseHeaders(200, responseBytes.length);

        
        try (OutputStream os = exchange.getResponseBody()) {
            os.write(responseBytes);
        }
        System.out.println("Serviing client done"); // debug
    }

    /*
     * handling /printjson
     */
    static void handlePrintJson(HttpExchange exchange) throws IOException {
        // CORS
        exchange.getResponseHeaders().add(
                "Access-Control-Allow-Origin", "*");

        exchange.getResponseHeaders().add(
                "Access-Control-Allow-Headers",
                "Content-Type, Authorization");

        exchange.getResponseHeaders().add(
        "Access-Control-Allow-Methods",
        "GET, POST, OPTIONS");

        if ("OPTIONS".equalsIgnoreCase(exchange.getRequestMethod())) {
            exchange.sendResponseHeaders(204, -1);
            return;
        }
        
        // UTF-8 text response
        exchange.getResponseHeaders().add(
                "Content-Type",
                "text/plain; charset=UTF-8");
        // get json from request
        // Read request body
        String requestBody;
        try (InputStream is = exchange.getRequestBody()) {
            requestBody = new String(is.readAllBytes(), StandardCharsets.UTF_8);
            // Parse JSON
            // Parse JSON and process
            JSONObject json = JSONObject.parseObject(requestBody);
            MyController.printJson(json.toString());
            
            JSONObject responseJson = infoService(exchange);
            responseJson.put("status", "printing");
            
            byte[] bytes =
                    responseJson.toString().getBytes(StandardCharsets.UTF_8);

            exchange.sendResponseHeaders(200, bytes.length);
            OutputStream os = exchange.getResponseBody();
            os.write(bytes);
            os.flush();

        }
    }
    
    /* 
     * standard info response 
     */
    static JSONObject infoService(HttpExchange exchange) {
        JSONObject jsonObj = new JSONObject();
        
        jsonObj.put("version", serviceVersion);
        jsonObj.put("service", serviceString);
        jsonObj.put("status", "running");
        String host = exchange.getLocalAddress().getHostString();
        int port = exchange.getLocalAddress().getPort();

        String baseUrl = "http://" + host + ":" + port;
        jsonObj.put("endpoint",baseUrl+"/printjson");
        
        return jsonObj;
    }
}

to run service


$ java -jar target/DdtEscPos-1.0.jar 
Hello World!
HTTP server running on http://localhost:50001
HTTPS server running on https://localhost:50002
Serviing client done
Serviing client done

using curl to send json to print http


$ curl -H "Content-Type: application/json" \
     -d @exampleescpos.json \
     http://localhost:50001/printjson

https


$ curl -k \
  -H "Content-Type: application/json" \
  -d @exampleescpos.json \
  https://localhost:50002/printjson

or 


$ curl --insecure \
  -H "Content-Type: application/json" \
  -d @exampleescpos.json \
  https://localhost:50002/printjson

Credit: esc html using https://www.freeformatter.com/html-escape.html