Bassam Bibalex
Bassam Bibalex

Reputation: 31

Handling HTTPS requests with Akka-http [java]

I was creating a small proxy to intercept all local http requests, then authorize them with the remote proxy. Here is the code snippet:

Source<IncomingConnection, CompletionStage<ServerBinding>> serverSource =
                Http.get(system).bind(ConnectWithHttps.toHost("localhost", LOCAL_PORT), materializer);
        Authorization authorization = Authorization.basic(USERNAME, PASSWORD);

        Flow<HttpRequest, HttpRequest, NotUsed> applySecurity =
                Flow.of(HttpRequest.class)
                    .map(request -> request.addHeader(authorization));

        Flow<HttpRequest, HttpResponse, CompletionStage<OutgoingConnection>> forwardToProxy =
                Http.get(system).outgoingConnection(ConnectWithHttps.toHost(PROXY_ADDRESS, PROXY_PORT));

        Flow<HttpRequest, HttpResponse, NotUsed> handler =
                Flow.of(HttpRequest.class)
                   .via(applySecurity)
                .via(forwardToProxy);


    serverSource.to(Sink.foreach(conn -> {
             System.out.println("Accepted new connection from " + conn.remoteAddress());
             conn.handleWith(handler, materializer);
                }
 )).run(materializer);

I need to handle Https requests also. But I always get this error:

[WARN] [04/14/2016 00:07:28.480] [MyActorSystem-akka.actor.default-dispatcher-13] [akka.actor.ActorSystemImpl(MyActorSystem)] Illegal request, responding with status '400 Bad Request': Request is missing required `Host` header: 'Host' header value of request to `eg.linkedin.com:443` doesn't match request target authority: Host header: Some(Host: eg.linkedin.com:443)

I've tried to use "ConnectWithHttps" instead of "ConnectHttp" but it didn't. I couldn't find any example related to Https

Any idea, thanks?

Note:

Documentation has no example specially in Java

Regards,

Bassam

Upvotes: 2

Views: 701

Answers (1)

EuDgee
EuDgee

Reputation: 13

Try to change

ConnectWithHttps.toHost("localhost", LOCAL_PORT)

to

ConnectWithHttps.toHost("localhost", LOCAL_PORT).withCustomHttpsContext(ctx)

Then you need to create HttpsConnectionContext for this to work (ctx). Simple example of how you can do it:

char[] password = config.getString("https.password").toCharArray();
SSLContext context = SSLContext.getInstance("TLS");
KeyStore ks = KeyStore.getInstance("PKCS12");

ks.load(App.class.getClassLoader().getResourceAsStream("keys/server.p12"), password);
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");

keyManagerFactory.init(ks, password);
context.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom());

HttpsConnectionContext ctx = ConnectionContext.https(context);

Upvotes: 1

Related Questions