Skip to content

Instantly share code, notes, and snippets.

@brianhsu
Created January 8, 2010 09:38
Show Gist options
  • Save brianhsu/271945 to your computer and use it in GitHub Desktop.
Save brianhsu/271945 to your computer and use it in GitHub Desktop.
import java.net._
import java.io._
import scala.io._
def listenToPort (port: Int) =
{
val address = new InetSocketAddress(InetAddress.getLocalHost, port)
val socket = new ServerSocket
socket.bind (address, 5)
socket
}
def openConnection (host: String, port: Int) =
{
val remote = new Socket
val ip = new InetSocketAddress (host, port)
remote.connect (ip)
remote
}
def analyzeRequest (client: BufferedReader) =
{
def isLocal (host: String) = {
val localHost = InetAddress.getLocalHost.getHostName
val localIP = InetAddress.getLocalHost.getHostAddress
host.toLowerCase match {
case "127.0.0.1" => true
case "localhost" => true
case s if (s == localHost) => true
case s if (s == localIP) => true
case _ => false
}
}
val first = client.readLine.trim
val List (method, url, version) = first.split("""\s+""").toList
val result = new URL (url)
val host = result.getHost
val port = if (result.getPort != -1) {result.getPort} else {80}
if ( isLocal(host) ) {
println ("--- Connection to proxy server ignored.")
println ("It's not nice to make me loop on myself!.")
client.close ()
System.exit (1)
}
val remote = openConnection (host, port)
println ("%s -> %s" format (host, port))
(first, method, remote)
}
def main ()
{
// Step 1: Create Socket
val proxyPort: Int = if (args.length >= 1) {args(0).toInt} else {5364}
val socket = listenToPort (proxyPort)
println ("Proxy sever running on:" + socket)
// Step 2: Wait for Request
while (true) {
println ("--- Waiting to be of service ...")
val client = socket.accept ()
// Setp 3: Read first line and analyze it.
val clientReader = new BufferedReader(
new InputStreamReader(client.getInputStream)
)
val (first, method, remote) = analyzeRequest (clientReader)
println ("Meow")
// Step 4: Send request to remote host
val remoteWriter = new PrintWriter (remote.getOutputStream, true)
remoteWriter.println (first)
remoteWriter.println ("Connection: close")
remoteWriter.println ()
// Step 5: Read headers from client.
var line = clientReader.readLine
var contentLength = 0
while (line != null && line.trim != "") {
line.toLowerCase.split(":").toList match {
// Filter header we don't want to pass
case "connection" :: _ => println ("Here 1")
case "keep-alive" :: _ => println ("Here 2")
// Get content length
case "content-length" :: x => contentLength = x.head.trim.toInt
remoteWriter.println (line)
case _ => remoteWriter.println ("GET /")
}
if (method == "POST") {
val data = if (contentLength != 0) {
val buffer = new Array[Char](contentLength)
clientReader.read (buffer, 0, contentLength)
buffer
} else {
clientReader.readLine
}
println ("POST body:" + data)
remoteWriter.println (data)
}
line = clientReader.readLine
}
// Step 5: Wait for response and transfer it to requestor.
println ("--- Done sending. Response:")
contentLength = -1
val clientWriter = new PrintWriter (client.getOutputStream, false)
val remoteReader = Source.fromInputStream (remote.getInputStream)
for (line <- remoteReader.getLines) {
line.toLowerCase.split(":").toList match {
// Get content length
case "content-length" :: x => contentLength = x.head.trim.toInt
case _ =>
}
clientWriter.println (line)
}
if (contentLength != -1) {
val buffer = new Array[Char] (contentLength)
remoteReader.readInto (buffer, remoteReader.pos, contentLength)
clientWriter.print (buffer)
}
clientWriter.flush ()
remote.close ()
client.close ()
}
}
main ()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment