Created
January 8, 2010 09:38
-
-
Save brianhsu/271945 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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