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: | 1251 / 1282 |
| Referenced in: | [show references] |