Proxy Use Case support CONNECT Method

Hi,

My use case is to use reactive streams to make an efficient proxy (functioning similar to https://docs.mitmproxy.org/stable/concepts-howmitmproxyworks/ or squid) to protect children in schools from abuse.

Other similar projects in java:

http://paw-project.sourceforge.net

PAW (pro-active webfilter) is an Open-Source filtering HTTP proxy based on the Brazil Framework provided as a Open-Source Project by SUN. Because the Brazil Framework and PAW are written in Java the software is highly portable.
PAW allows for easy plugin of Handlers (filter outgoing requests) and Filters (filter incoming data - the HTML response) and a GUI for end users. All the configuration files are in XML-Format and thus easy to modify (even without the GUI).
Features
HTTP/HTTPS support
Pluggable Handlers/Filters. See Handler and Filter list.
Remote adminitstration with PAW GUI.
XML Configuration files.
Redirector
Import Filters/Handlers
Modify Request/Response Headers
Export of Handlers/Filters
Editing of Handerl/Filter definition

Seems to be unsupported from

https://sourceforge.net/projects/jhttp2/

jHTTPp2 is a very small HTTP/1.1 proxy server written in Java. It offers following features: IPv6 support, high-performance, blocks URL’s based on a block-list, removes data from the HTTP-Header, blocks Cookies from untrusted hosts.

Seems to be unsupported from 2011

The idea is to ideally intercept all web traffic and perform the equivalent of deep packet inspection, filtering images, and text sent to and from the internet.

I imagine having access to the HttpRequest from the browser and being able to reject the request straight away, or connect to the website and stream the http response from the destination website to the browser through a filter that can either modify the ByteStrings or terminate the coneection.

This is a non streaming (non working) version of a prototype


  val serverSource = Http().bind(interface = "0.0.0.0", port = httpPort)

  val requestHandler: HttpRequest => HttpResponse = {
    case r: HttpRequest =>
      r.discardEntityBytes() // important to drain incoming HTTP Entity stream
      //HttpResponse(200, entity = s"Proxy intercepted URI ${r.uri} METHOD ${r.method} HEADERS ${r.headers}")

      val responseFuture: Future[HttpResponse] = Http().singleRequest(HttpRequest(uri = r.uri))
      Await.result(responseFuture,Duration.Inf)
  }

  val bindingFuture: Future[Http.ServerBinding] =
    serverSource.to(Sink.foreach { connection =>
      println("Accepted new connection from " + connection.remoteAddress)

      connection handleWithSyncHandler requestHandler
    }).run()

  log.info("Proxy online at http://localhost:{}/",httpPort)

I have seen that in HttpServerBluePrint the CONNECT method is rejected


case connect: RequestStart if connect.method == HttpMethods.CONNECT =>
        MessageStartError(StatusCodes.BadRequest, ErrorInfo(s"CONNECT requests are not supported", s"Rejecting CONNECT request to '${connect.uri}'"))

Also that in object HttpMethods


 val CONNECT = register(HttpMethod("CONNECT", isSafe = false, isIdempotent = false, requestEntityAcceptance = Disallowed))

which I imagine should need to be:


 val CONNECT = register(HttpMethod("CONNECT", isSafe = false, isIdempotent = false, requestEntityAcceptance = Expected))

How difficult would it be to support the CONNECT method?

Could this be included in akka http?

Thanks in advance.
Could someone assist me to get my example to work?

Handling CONNECT would require implementing a HTTP full proxy, not only changing the blueprint to accept the method, that is not something we have any plans on (See ancient issue: https://github.com/akka/akka-http/issues/101).

Johan thanks for the response.

How much work would be involved to accept the CONNECT method and then stream that via an Akka Http Client stream to the host. (No Authentication etc) ?

Can you give me some pointers as to what would need to be done?

I can think of lots of interesting use cases for a lightweight proxy functionality.

There has been some work on a reverseProxy directive, perhaps that can be useful to look at: https://github.com/akka/akka-http/pull/2811/files