package edu.pdx.cs410J.web; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.io.*; import java.nio.charset.Charset; /** * A helper class that provides methods for requesting resources via HTTP */ public class HttpRequestHelper { /** * Performs an HTTP GET on the given URL * * @param urlString The URL to get * @param parameters The key/value query parameters * @return A <code>Response</code> summarizing the result of the GET */ protected Response get(String urlString, String... parameters) throws IOException { checkParameters(parameters); StringBuilder query = encodeParameters(parameters); if (query.length() > 0) { query.insert(0, '?'); } URL url = new URL(urlString + query); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setDoOutput(true); conn.setDoInput(true); return new Response(conn); } /** * Performs an HTTP POST to the given URL * @param urlString The URL to post to * @param parameters The key/value parameters * @return A <code>Response</code> summarizing the result of the POST */ protected Response post(String urlString, String... parameters) throws IOException { return sendEncodedRequest(urlString, "POST", parameters); } /** * Performs an HTTP DELETE to the given URL * @param urlString The URL to post to * @param parameters The key/value parameters * @return A <code>Response</code> summarizing the result of the POST */ protected Response delete(String urlString, String... parameters) throws IOException { return sendEncodedRequest(urlString, "DELETE", parameters); } private Response sendEncodedRequest(String urlString, String requestMethod, String... parameters) throws IOException { checkParameters(parameters); StringBuilder data = encodeParameters(parameters); URL url = new URL(urlString); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod(requestMethod); conn.setDoOutput(true); OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream(), Charset.forName("UTF-8")); wr.write(data.toString()); wr.flush(); Response response = new Response(conn); wr.close(); return response; } /** * Encodes parameters to be sent to the server via an HTTP GET, POST, or DELETE * @param parameters The parameter key/value pairs * @return The encoded parameters * @throws java.io.UnsupportedEncodingException If we can't encode UTF-8 */ private StringBuilder encodeParameters(String... parameters) throws UnsupportedEncodingException { StringBuilder query = new StringBuilder(); for (int i = 0; i < parameters.length; i += 2) { String key = parameters[i]; String value = parameters[i + 1]; query.append(URLEncoder.encode(key, "UTF-8")); query.append("="); query.append(URLEncoder.encode(value, "UTF-8")); if (i < parameters.length - 2) { query.append("&"); } } return query; } private void checkParameters(String... parameters) { if (parameters.length % 2 != 0) { String s = "You must specify an even number of parameters (key/value pairs)"; throw new IllegalArgumentException(s); } } /** * Performs an HTTP PUT on the given URL * * @param urlString The URL to put to * @param parameters key/value parameters to the put * @return A <code>Reponse</code> summarizing the result of the PUT */ protected Response put(String urlString, String... parameters) throws IOException { checkParameters(parameters); StringBuilder data = new StringBuilder(); for (int i = 0; i < parameters.length; i += 2) { String key = parameters[i]; String value = parameters[i + 1]; data.append(key); data.append("="); data.append(value); data.append("\n"); } URL url = new URL(urlString); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("PUT"); conn.setDoOutput(true); conn.setDoInput(true); conn.setRequestProperty("Content-Type", "text/plain"); conn.setRequestProperty("Context-Length", String.valueOf(data.length())); OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream(), Charset.forName("UTF-8")); wr.write(data.toString()); wr.flush(); Response response = new Response(conn); wr.close(); return response; } /** * Encapsulates a response to an HTTP request */ public static class Response { private final int code; private final String content; private int contentLines = 0; private Response(HttpURLConnection conn) throws IOException { this.code = conn.getResponseCode(); if (this.code != java.net.HttpURLConnection.HTTP_OK) { this.content = conn.getResponseMessage(); return; } StringBuilder content = new StringBuilder(); BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); String line; while ((line = rd.readLine()) != null) { content.append(line); content.append("\n"); contentLines++; } rd.close(); this.content = content.toString().trim(); } /** * Returns the HTTP status code of the response * @see java.net.HttpURLConnection#getResponseCode() */ public int getCode() { return code; } /** * Returns the (presumably textual) response from the URL * @return */ public String getContent() { return content; } /** * Returns the number of lines in the response's content */ public int getContentLines() { return contentLines; } } /** * A main method that requests a resource from a URL using a given HTTP method */ public static void main(String[] args) throws IOException { String method = args[0]; String url = args[1]; String[] parameters = new String[args.length - 2]; System.arraycopy(args, 2, parameters, 0, parameters.length); HttpRequestHelper helper = new HttpRequestHelper(); Response response; if (method.equalsIgnoreCase("PUT")) { response = helper.put(url, parameters); } else if (method.equalsIgnoreCase("GET")) { response = helper.get(url, parameters); } else if (method.equalsIgnoreCase("POST")) { response = helper.post(url, parameters); } else { System.err.println("** Unknown method: " + method); return; } System.out.println("Returned code " + response.getCode() + " and " + response.getContentLines() + " lines of content\n"); System.out.println(response.getContent()); } }