Friday, December 19, 2014

Java: Https clients, headers and cookies

Sample HTTPS client

Processing the input stream is more reliable than using the #getContent() method.

http://alvinalexander.com/blog/post/java/simple-https-example

  package foo;
   
  import java.net.URL;
  import java.io.*;
  import javax.net.ssl.HttpsURLConnection;
   
  public class JavaHttpsExample
  {
    public static void main(String[] args)
    throws Exception
    {
      String httpsURL = "https://your.https.url.here/";
      URL myurl = new URL(httpsURL);
      HttpsURLConnection con = (HttpsURLConnection)myurl.openConnection();
      InputStream ins = con.getInputStream();
      InputStreamReader isr = new InputStreamReader(ins);
      BufferedReader in = new BufferedReader(isr);
   
      String inputLine;
   
      while ((inputLine = in.readLine()) != null)
      {
        System.out.println(inputLine);
      }
   
      in.close();
    }
  }
Additional references:

Url parameters (GET and POST)

Depending on the method for the request, there are a couple different ways that url parameters can be configured. GET requests will include the parameter names and values in the url itself. POST will include the parameter names and values in a request header.

GET


  String http_url = "http://127.0.0.1:3771/greeting/test";

  String charset = "UTF-8";  // Or in Java 7 and later, use the constant: java.nio.charset.StandardCharsets.UTF_8.name()
  String param1 = "value1";
  String param2 = "value2";

  URL url;
  try {

    String query = String.format("param1=%s¶m2=%s",
           URLEncoder.encode(param1, charset),
           URLEncoder.encode(param2, charset));

    url = new URL(http_url + "?" + query);
    HttpURLConnection con = (HttpURLConnection)url.openConnection();
    con.setRequestProperty("Accept-Charset", charset);
    ...

  } catch (Exception e) {
		e.printStackTrace();
  }

POST


  http_url = "http://127.0.0.1:3771/greeting/shake.json";

  String charset = "UTF-8";  // Or in Java 7 and later, use the constant: java.nio.charset.StandardCharsets.UTF_8.name()
  String param1 = "value1";
  String param2 = "value2";

  URL url;
  try {
    url = new URL(http_url);

    con = (HttpURLConnection)url.openConnection();
    con.setRequestMethod("POST");
    con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + charset);
    con.setDoOutput(true);

    String query = String.format("param1=%s¶m2=%s",
           URLEncoder.encode(param1, charset),
           URLEncoder.encode(param2, charset));

    try (OutputStream output = con.getOutputStream()) {
        output.write(query.getBytes(charset));
    }
    ...
    
  } catch (Exception e) {
		e.printStackTrace();
  }

Additional references:

The nature of cookies

Cookies are only set by the server; any modifications to the cookies on the client side are ignored (at least when using java.net's CookieManager class). Cookies are stored on the client side and the client may read them.

http://curl.haxx.se/rfc/cookie_spec.html

  HttpCookie cookie = new HttpCookie("blah", "bleh");

  url = new URL(http_url); 
  cookieJar.add(url.toURI(), cookie);
  HttpURLConnection con = (HttpURLConnection)url.openConnection();

Accessing Cookies, both retrieval and assignment.

HTTP response code: 411

When sending a POST request to a server, there must be a non-null body provided, even if it is an empty string or an exception will be thrown. The behavior for other libraries may differ, but for the java.net package, this is the case.


  java.io.IOException: Server returned HTTP response code: 411 for URL: http://127.0.0.1:3771/greeting/shake.json

You will need to write to the output stream to overcome this problem. Doing so automatically creates the "Content-Length" request header.


  con.setRequestMethod("POST");

  con.setDoOutput(true);
  BufferedWriter bf = new BufferedWriter(new OutputStreamWriter(con.getOutputStream()));
  bf.write("");
  bf.flush();
Additional references:

Setting request headers and their respective values

http://stackoverflow.com/questions/6469540/setting-custom-http-request-headers-in-an-url-object-doesnt-work

  URL url = new URL("http://myipcam/snapshot.jpg");
  URLConnection uc = url.openConnection();
  uc.setRequestProperty("Authorization", 
    "Basic " + new String(Base64.encode("user:pass".getBytes())));

  // outputs "null"
  System.out.println(uc.getRequestProperty("Authorization"));
http://stackoverflow.com/questions/12731211/pass-cookies-from-httpurlconnection-java-net-cookiemanager-to-webview-android

  webCookieManager.setAcceptCookie(true);

Print out all header keys and their respective values.

http://www.mkyong.com/java/how-to-get-http-response-header-in-java/

	//get all headers
	Map> map = conn.getHeaderFields();
	for (Map.Entry> entry : map.entrySet()) {
		System.out.println("Key : " + entry.getKey() + 
                 " ,Value : " + entry.getValue());
	}
 
	//get header by 'key'
	String server = conn.getHeaderField("Server");

Ruby/Rails: access cookies

http://api.rubyonrails.org/classes/ActionDispatch/Cookies.html

  cookies[:user_name] = "david"
  cookies.signed[:user_id] = current_user.id

Ruby/Rails: access headers

http://stackoverflow.com/questions/19972313/accessing-custom-header-variables-in-ruby-on-rails

  request.headers['custom_header']
Now custom variables are always prepended with HTTP_ ... except for CGI variables Harsh Gupta