package ovh.alexisdelhaie.curling.web; import java.io.*; import java.net.*; import java.util.Map; public class HttpClient { public static String CRLF = "\r\n"; public static int DEFAULT_PORT = 80; public static int DEFAULT_TIMEOUT = 10000; protected InetAddress addr; protected URL url; protected boolean valid; protected Method method; protected Map headers; protected String body; public HttpClient(String u, Method method, String body, Map headers) { try { URL url = new URL(u); addr = resolve(url.getHost()); this.url = url; this.headers = headers; this.method = method; this.body = body; valid = true; } catch (UnknownHostException | MalformedURLException e) { valid = false; } } public InetAddress getAddr() { return addr; } public URL getUrl() { return url; } public Method getMethod() { return method; } public Map getHeaders() { return headers; } public String getBody() { return body; } public boolean isDomain() { if(valid) { String comparable = url.getHost(); if(comparable.contains(":")) { comparable = comparable.split(":")[0]; } return !(comparable.equals(addr.getHostAddress())); } return false; } public String run() { String result = ""; Socket s = null; if (valid) { String request = String.format("%s%s%s", buildHeader(), CRLF, body); result += String.format("--- Request ---\n%s", request); BufferedOutputStream bos = null; BufferedInputStream bis = null; try { s = new Socket(addr, getPort()); s.setKeepAlive(false); s.setSoTimeout(DEFAULT_TIMEOUT); if (s.isConnected()) { bos = new BufferedOutputStream(s.getOutputStream()); bos.write(request.getBytes()); bos.flush(); bis = new BufferedInputStream(s.getInputStream()); byte[] b = bis.readAllBytes(); result += String.format("\n\n--- Response ---\n%s", new String(b, "UTF-8")); } else { result += "/!\\ Not connected"; } } catch (IOException io) { result += String.format("\n\n /!\\ %s", io.getMessage()); } finally { try { if(bos != null) { bos.close(); } if(bis != null) { bis.close(); } if(s != null && s.isConnected()) { s.close(); } } catch (IOException e) { result += String.format("\n\n /!\\ %s", e.getMessage()); } } } return result; } private InetAddress resolve(String host) throws UnknownHostException { InetAddress[] addrs = InetAddress.getAllByName(host); return addrs[0]; } protected String buildHeader() { String result = String.format("%s %s HTTP/1.1%s", method.toString(), getPath(), CRLF); result += getHostHeader(); result += String.format("Accept: */*%s", CRLF); result += String.format("Connection: close%s", CRLF); if(method == Method.POST || method == Method.PUT) { result += String.format("Content-Length: %d%s", body.length(), CRLF); } if(!headers.containsKey("User-Agent")) { result += String.format("User-Agent: cURLing/2.0 %s%s", System.getProperty("os.name"), CRLF); } if(headers != null) { for (Map.Entry entry : headers.entrySet()) { if (isAuthorizedHeader(entry.getKey())) { result += String.format("%s: %s%s", entry.getKey(), entry.getValue(), CRLF); } } } return result; } private boolean isAuthorizedHeader(String key) { boolean result = true; if (key.toUpperCase().equals("ACCEPT") || key.toUpperCase().equals("HOST") || key.toUpperCase().equals("CONNECTION")) { result = false; } return result; } public boolean isValid() { return valid; } private String getPath() { if(url.getPath().isBlank()) { return "/"; } return url.getPath(); } private String getHostHeader() { String result; if (url.getPort() != -1) { result = String.format("Host: %s:%d%s", url.getHost(), url.getPort(), CRLF); } else { result = String.format("Host: %s%s", url.getHost(), CRLF); } return result; } protected int getPort() { if(url.getPort() != -1) { return url.getPort(); } return DEFAULT_PORT; } }