Libraryless. Click here for Pure Java version (2302L/16K/55K).
1 | !752 |
2 | |
3 | static S vmArgs = "-XX:+PrintGC -Xmx32m"; |
4 | |
5 | static int port = 80; |
6 | static S forwardServer = |
7 | //"ai1.lol"; |
8 | //"google.de"; |
9 | "localhost"; |
10 | |
11 | static Map<S, Integer> forwardMap = litmap( |
12 | "thedevchannel.com", 3000, |
13 | "default", 8080); |
14 | |
15 | p { |
16 | // Safety Rebooter - to hold up thedevchannel.com and ai1.lol when admin sleeps! |
17 | |
18 | thread "Rebooter" { |
19 | sleepSeconds(60*60*24); |
20 | nohupJavax(programID(), vmArgs); |
21 | System.exit (0); |
22 | } |
23 | |
24 | // turn off memory leak |
25 | |
26 | noPrintLog(); |
27 | |
28 | // Now for the actual server... |
29 | |
30 | final ServerSocket serverSocket = new ServerSocket(port); |
31 | |
32 | Thread thread = new Thread("HTTP Proxy Accept Port " + port) { public void run() { |
33 | try { |
34 | while (true) { |
35 | try { |
36 | final Socket s = serverSocket.accept(); |
37 | |
38 | thread "Lister" { |
39 | sleepSeconds(5); |
40 | listThreads(); |
41 | } |
42 | |
43 | final S client = dropPrefix("/", s.getInetAddress().toString()); // Hmm... how to get the actual IP properly? |
44 | String threadName = "PROXY: Handling client " + client; |
45 | |
46 | Thread t2 = new Thread(threadName) { |
47 | public void run() ctex { |
48 | Socket outSocket = null; |
49 | final new AtomicLong transmitted; |
50 | final new AtomicLong outTransmitted; |
51 | try { |
52 | print("HTTP Proxy Incoming!"); |
53 | |
54 | final OutputStream out = s.getOutputStream(); |
55 | final InputStream in = s.getInputStream(); |
56 | |
57 | // collect headers |
58 | |
59 | new ByteArrayOutputStream headersOut; |
60 | BufferedReader headerReader = new BufferedReader(new InputStreamReader(in, "US-ASCII"), 1); |
61 | boolean forwardedFor = false; |
62 | S host = null; |
63 | while (true) { |
64 | S line = headerReader.readLine(); |
65 | if (line == null) ret; |
66 | print("Header line read: " + quote(line)); |
67 | |
68 | if (startsWithIgnoreCase(line, "Host:")) |
69 | host = dropPrefix("Host:", line).trim(); |
70 | else { |
71 | S rewritten; |
72 | if (startsWithIgnoreCase(line, "X-Forwarded-For:")) { |
73 | forwardedFor = true; |
74 | rewritten = line + ", " + client; |
75 | } else |
76 | rewritten = empty(line) ? line : rewriteHeaderLine(line); |
77 | if (!eq(rewritten, line)) |
78 | print("Rewritten as: " + quote(rewritten)); |
79 | if (nempty(rewritten)) { |
80 | byte[] bytes = (rewritten + "\r\n").getBytes("US-ASCII"); |
81 | //print("Sending: " + bytesToHex(bytes)); |
82 | headersOut.write(bytes); |
83 | } |
84 | } |
85 | |
86 | if (l(line) == 0) |
87 | break; |
88 | } |
89 | |
90 | int port = getForwardPort(host); |
91 | |
92 | outSocket = new Socket(forwardServer, port); |
93 | print("Connected to " + forwardServer + ":" + port); |
94 | final OutputStream outOut = outSocket.getOutputStream(); |
95 | final InputStream outIn = outSocket.getInputStream(); |
96 | |
97 | outOut.write(headersOut.toByteArray()); |
98 | |
99 | if (!forwardedFor) |
100 | headerSend(outOut, "X-Forwarded-For: " + client); |
101 | |
102 | headerSend(outOut, "Host: " + hostToPort(host, port)); |
103 | |
104 | headerSend(outOut, ""); // end of headers |
105 | |
106 | outOut.flush(); |
107 | |
108 | // forward content in both directions |
109 | |
110 | //copyStream(outIn, out); |
111 | |
112 | Thread inThread = new Thread("Proxy In") { |
113 | public void run() ctex { |
114 | byte[] buf = new byte[1]; |
115 | while (true) { |
116 | int n = outIn.read(buf); |
117 | if (n <= 0) return; |
118 | out.write(buf, 0, n); |
119 | long t = transmitted.addAndGet(n); |
120 | if (t % 100000 == 0) print("Transmitted to client: " + t); |
121 | } |
122 | } |
123 | }; |
124 | inThread.start(); |
125 | |
126 | Thread outThread = new Thread("Proxy Out") { |
127 | public void run() ctex { |
128 | byte[] buf = new byte[1]; |
129 | while (true) { |
130 | int n = in.read(buf); |
131 | if (n <= 0) return; |
132 | outOut.write(buf, 0, n); |
133 | long t = outTransmitted.addAndGet(n); |
134 | if (t % 100000 == 0) print("Transmitted to server: " + t); |
135 | } |
136 | } |
137 | }; |
138 | outThread.start(); |
139 | |
140 | inThread.join(); |
141 | //outThread.join(); |
142 | } catch (IOException e) { |
143 | print("[internal] " + e); |
144 | } finally { |
145 | print("Proxy request done, got " + transmitted.get() + ", sent " + outTransmitted.get() + " + headers"); |
146 | pcall { s.close(); } |
147 | pcall { if (outSocket != null) outSocket.close(); } |
148 | } |
149 | } |
150 | }; // Thread t2 |
151 | t2.setDaemon(true); |
152 | t2.start(); |
153 | } catch (SocketTimeoutException e) { |
154 | } |
155 | } |
156 | } catch (IOException e) { |
157 | print("[internal] " + e); |
158 | } |
159 | }}; |
160 | thread.start(); |
161 | |
162 | print("HTTP proxy on port " + port + " started."); |
163 | } |
164 | |
165 | static S rewriteHeaderLine(S line) { |
166 | /*if (startsWithIgnoreCase(line, "Host:")) |
167 | line = "Host: " + forwardServer + ":" + forwardPort;*/ |
168 | ret line; |
169 | } |
170 | |
171 | static int getForwardPort(S host) { |
172 | int i = host.indexOf(':'); |
173 | if (i >= 0) |
174 | host = host.substring(0, i); |
175 | host = host.toLowerCase(); |
176 | for (S key : forwardMap.keySet()) |
177 | if (eq(host, key) || host.endsWith("." + key)) |
178 | ret forwardMap.get(key); |
179 | ret forwardMap.get("default"); |
180 | } |
181 | |
182 | static S hostToPort(S host, int port) { |
183 | int i = host.indexOf(':'); |
184 | if (i >= 0) |
185 | host = host.substring(0, i); |
186 | ret host + ":" + port; |
187 | } |
188 | |
189 | static void headerSend(OutputStream out, S header) ctex { |
190 | print("Sending header: " + header); |
191 | out.write((header + "\r\n").getBytes("US-ASCII")); |
192 | } |
download show line numbers debug dex old transpilations
Travelled to 14 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, jtubtzbbkimh, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt
No comments. add comment
Snippet ID: | #1002783 |
Snippet name: | HTTP Proxy (old) |
Eternal ID of this version: | #1002783/1 |
Text MD5: | 7cd269f9330f62fd472129b2e293ffbd |
Transpilation MD5: | 406e055dc891f05f984c2bf8119c0e91 |
Author: | stefan |
Category: | eleu |
Type: | JavaX source code |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2016-03-02 02:13:06 |
Source code size: | 6429 bytes / 192 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 896 / 938 |
Referenced in: | [show references] |