1 package emissary.util.web;
2
3 import org.slf4j.Logger;
4 import org.slf4j.LoggerFactory;
5
6 import java.io.BufferedReader;
7 import java.io.IOException;
8 import java.io.InputStreamReader;
9 import java.io.OutputStream;
10 import java.net.HttpURLConnection;
11 import java.net.MalformedURLException;
12 import java.net.URL;
13 import java.util.ArrayList;
14 import java.util.HashMap;
15 import java.util.List;
16 import java.util.Map;
17 import javax.annotation.Nullable;
18
19 public class Url {
20
21 private static final Logger logger = LoggerFactory.getLogger(Url.class);
22
23 public static final int UNINITIALIZED = 0;
24 public static final int GET = 1;
25 public static final int POST = 2;
26 public static final int HEAD = 3;
27
28 static final String[] theMethodString = {"GET", "POST", "HEAD"};
29
30
31
32
33
34
35 public static UrlData doUrl(final UrlData toProcess) {
36 if (toProcess == null) {
37 throw new IllegalArgumentException("Url.doUrl: null UrlData arg");
38 }
39
40 final int method = toProcess.getTheMethod();
41
42 if (method == Url.GET) {
43 return getUrl(toProcess);
44 }
45
46 if (method == Url.POST) {
47 return postUrl(toProcess);
48 }
49
50 throw new IllegalArgumentException("UrlData method " + method + " not implemented in UrlData.doUrl");
51 }
52
53
54
55
56
57
58 public static UrlData getUrl(final UrlData toGet) {
59 return getUrl(toGet.getTheUrl(), toGet.getProps());
60 }
61
62
63
64
65
66
67 public static UrlData getUrl(final String urlString) {
68 return getUrl(urlString, null);
69 }
70
71
72
73
74
75
76
77 public static UrlData getUrl(final String urlString, @Nullable final List<UrlRequestProperty> props) {
78 return processUrl(urlString, props, null, Url.GET);
79 }
80
81
82
83
84
85
86 public static UrlData postUrl(final UrlData toPost) {
87 return postUrl(toPost.getTheUrl(), toPost.getProps(), null);
88 }
89
90
91
92
93
94
95
96 public static UrlData postUrl(final UrlData toPost, final HttpPostParameters parms) {
97 return postUrl(toPost.getTheUrl(), toPost.getProps(), parms);
98 }
99
100
101
102
103
104
105 public static UrlData postUrl(final String urlString) {
106 return postUrl(urlString, null, null);
107 }
108
109
110
111
112
113
114
115
116 public static UrlData postUrl(final String urlString, @Nullable final List<UrlRequestProperty> props, @Nullable final HttpPostParameters parms) {
117
118
119
120 final UrlData u = new UrlData(urlString);
121 u.setTheMethod(Url.POST);
122 if (props != null) {
123 u.setProps(props);
124 }
125 if (parms != null) {
126 u.addProp(new UrlRequestProperty("Content-length", parms.length()));
127 }
128
129 return processUrl(u.getTheUrl(), u.getProps(), parms, u.getTheMethod());
130 }
131
132
133
134
135
136
137
138
139
140 private static UrlData processUrl(final String urlString, @Nullable final List<UrlRequestProperty> props,
141 @Nullable final HttpPostParameters parms,
142 final int method) {
143 final UrlData response = new UrlData(urlString);
144
145 final StringBuilder theOutput = new StringBuilder();
146 OutputStream os = null;
147 BufferedReader dis = null;
148 try {
149 final URL theUrl = new URL(urlString);
150 final HttpURLConnection conn = (HttpURLConnection) theUrl.openConnection();
151
152
153 conn.setDoOutput(method == Url.POST);
154 conn.setDoInput(true);
155 conn.setUseCaches(false);
156
157
158
159 if (props != null) {
160 for (UrlRequestProperty prop : props) {
161 conn.setRequestProperty(prop.getKey(), prop.getValue());
162 }
163 }
164
165
166
167 if (method == Url.POST && parms != null) {
168 os = conn.getOutputStream();
169 os.write(parms.toPostString().getBytes());
170 os.flush();
171 }
172
173
174 response.setResponseCode(conn.getResponseCode());
175
176
177 final Map<String, String> headers = new HashMap<>();
178 String s;
179 int hdr = 0;
180 while ((s = conn.getHeaderField(hdr)) != null) {
181 final String key = conn.getHeaderFieldKey(hdr);
182 if (key != null) {
183 headers.put(key, s);
184 } else {
185 headers.put("", s);
186 }
187 hdr++;
188 }
189
190
191 final List<UrlRequestProperty> theProps = new ArrayList<>(headers.size());
192 for (final Map.Entry<String, String> entry : headers.entrySet()) {
193 theProps.add(new UrlRequestProperty(entry.getKey(), entry.getValue()));
194 }
195 response.setProps(theProps);
196
197
198 if (method != Url.HEAD) {
199 dis = new BufferedReader(new InputStreamReader(conn.getInputStream()));
200
201
202 String line;
203 while ((line = dis.readLine()) != null) {
204 theOutput.append(line).append(System.getProperty("line.separator", "\n"));
205 }
206
207 response.setTheContent(theOutput.toString().getBytes());
208 }
209 } catch (MalformedURLException e) {
210 logger.warn("Bad URL " + urlString, e);
211 } catch (IOException e) {
212 logger.warn("Read error on " + urlString, e);
213 } catch (OutOfMemoryError e) {
214 logger.warn("Not enough space for read on " + urlString, e);
215 } finally {
216 if (os != null) {
217 try {
218 os.close();
219 } catch (IOException ioe) {
220 logger.warn("Unable to close stream", ioe);
221 }
222 }
223 if (dis != null) {
224 try {
225 dis.close();
226 } catch (IOException ioe) {
227 logger.warn("Unable to close stream", ioe);
228 }
229 }
230 }
231
232 return response;
233 }
234
235
236 private Url() {}
237 }