A HTTP GET Example Using The Apache HTTPClient Library

Here’s a quick example of using the Apache HTTPClient library to issue a simple GET request. The URL you’re connecting to is in endpoint, and the contents of the URL can be read from the BufferedReader response_reader.

		HttpGet get_request = new HttpGet(endpoint);
		get_request.addHeader(HttpHeaders.USER_AGENT, "Example Reader Service");

		HttpResponse http_response = HttpClientBuilder.create().build().execute(get_request);
		content_type_header = http_response.getFirstHeader("Content-Type").getValue();
		
		int response_code = http_response.getStatusLine().getStatusCode();

		if (response_code != 200) {
			throw new IOException("Response code is not 200 OK. Response code: " + response_code + " : " + endpoint.toString());
		}

		//Pull out text response
		InputStream response_is = http_response.getEntity().getContent();
		BufferedReader response_reader = new BufferedReader(new InputStreamReader(response_is, "UTF-8"));

Mapping Unicode Punctuation To ASCII Punctuation

The following code maps a bunch of unicode punctuation to their more normal ASCII counterparts. For example, the Unicode character LEFT DOUBLE QUOTATION MARK is mapped to the ASCII double quotation mark: “.

		Hashtable<String, String> map = new Hashtable<String, String>();
		map.put(new String(Character.toChars(0x00AB)), new String("\""));
		map.put(new String(Character.toChars(0x00AD)), "-");
		map.put(new String(Character.toChars(0x00B4)), "\'");
		map.put(new String(Character.toChars(0x00BB)), "\"");
		map.put(new String(Character.toChars(0x00F7)), "/");
		map.put(new String(Character.toChars(0x01C0)), "|");
		map.put(new String(Character.toChars(0x01C3)), "!");
		map.put(new String(Character.toChars(0x02B9)), "\'");
		map.put(new String(Character.toChars(0x02BA)), "\"");
		map.put(new String(Character.toChars(0x02BC)), "\'");
		map.put(new String(Character.toChars(0x02C4)), "^");
		map.put(new String(Character.toChars(0x02C6)), "^");
		map.put(new String(Character.toChars(0x02C8)), "\'");
		map.put(new String(Character.toChars(0x02CB)), "`");
		map.put(new String(Character.toChars(0x02CD)), "_");
		map.put(new String(Character.toChars(0x02DC)), "~");
		map.put(new String(Character.toChars(0x0300)), "`");
		map.put(new String(Character.toChars(0x0301)), "\'");
		map.put(new String(Character.toChars(0x0302)), "^");
		map.put(new String(Character.toChars(0x0303)), "~");
		map.put(new String(Character.toChars(0x030B)), "\"");
		map.put(new String(Character.toChars(0x030E)), "\"");
		map.put(new String(Character.toChars(0x0331)), "_");
		map.put(new String(Character.toChars(0x0332)), "_");
		map.put(new String(Character.toChars(0x0338)), "/");
		map.put(new String(Character.toChars(0x0589)), ":");
		map.put(new String(Character.toChars(0x05C0)), "|");
		map.put(new String(Character.toChars(0x05C3)), ":");
		map.put(new String(Character.toChars(0x066A)), "%");
		map.put(new String(Character.toChars(0x066D)), "*");
		map.put(new String(Character.toChars(0x200B)), " ");
		map.put(new String(Character.toChars(0x2010)), "-");
		map.put(new String(Character.toChars(0x2011)), "-");
		map.put(new String(Character.toChars(0x2012)), "-");
		map.put(new String(Character.toChars(0x2013)), "-");
		map.put(new String(Character.toChars(0x2014)), "-");
		map.put(new String(Character.toChars(0x2015)), "-");
		map.put(new String(Character.toChars(0x2016)), "|");
		map.put(new String(Character.toChars(0x2017)), "_");
		map.put(new String(Character.toChars(0x2018)), "\'");
		map.put(new String(Character.toChars(0x2019)), "\'");
		map.put(new String(Character.toChars(0x201A)), ",");
		map.put(new String(Character.toChars(0x201B)), "\'");
		map.put(new String(Character.toChars(0x201C)), "\"");
		map.put(new String(Character.toChars(0x201D)), "\"");
		map.put(new String(Character.toChars(0x201E)), "\"");
		map.put(new String(Character.toChars(0x201F)), "\"");
		map.put(new String(Character.toChars(0x2032)), "\'");
		map.put(new String(Character.toChars(0x2033)), "\"");
		map.put(new String(Character.toChars(0x2034)), "\'");
		map.put(new String(Character.toChars(0x2035)), "`");
		map.put(new String(Character.toChars(0x2036)), "\"");
		map.put(new String(Character.toChars(0x2037)), "\'");
		map.put(new String(Character.toChars(0x2038)), "^");
		map.put(new String(Character.toChars(0x2039)), "<");
		map.put(new String(Character.toChars(0x203A)), ">");
		map.put(new String(Character.toChars(0x203D)), "?");
		map.put(new String(Character.toChars(0x2044)), "/");
		map.put(new String(Character.toChars(0x204E)), "*");
		map.put(new String(Character.toChars(0x2052)), "%");
		map.put(new String(Character.toChars(0x2053)), "~");
		map.put(new String(Character.toChars(0x2060)), " ");
		map.put(new String(Character.toChars(0x20E5)), "\\");
		map.put(new String(Character.toChars(0x2212)), "-");
		map.put(new String(Character.toChars(0x2215)), "/");
		map.put(new String(Character.toChars(0x2216)), "\\");
		map.put(new String(Character.toChars(0x2217)), "*");
		map.put(new String(Character.toChars(0x2223)), "|");
		map.put(new String(Character.toChars(0x2236)), ":");
		map.put(new String(Character.toChars(0x223C)), "~");
		map.put(new String(Character.toChars(0x2264)), "<");
		map.put(new String(Character.toChars(0x2265)), ">");
		map.put(new String(Character.toChars(0x2266)), "<");
		map.put(new String(Character.toChars(0x2267)), ">");
		map.put(new String(Character.toChars(0x2303)), "^");
		map.put(new String(Character.toChars(0x2329)), "<");
		map.put(new String(Character.toChars(0x232A)), ">");
		map.put(new String(Character.toChars(0x266F)), "#");
		map.put(new String(Character.toChars(0x2731)), "*");
		map.put(new String(Character.toChars(0x2758)), "|");
		map.put(new String(Character.toChars(0x2762)), "!");
		map.put(new String(Character.toChars(0x27E6)), "[");
		map.put(new String(Character.toChars(0x27E8)), "<");
		map.put(new String(Character.toChars(0x27E9)), ">");
		map.put(new String(Character.toChars(0x2983)), "{");
		map.put(new String(Character.toChars(0x2984)), "}");
		map.put(new String(Character.toChars(0x3003)), "\"");
		map.put(new String(Character.toChars(0x3008)), "<");
		map.put(new String(Character.toChars(0x3009)), ">");
		map.put(new String(Character.toChars(0x301B)), "]");
		map.put(new String(Character.toChars(0x301C)), "~");
		map.put(new String(Character.toChars(0x301D)), "\"");
		map.put(new String(Character.toChars(0x301E)), "\"");
		map.put(new String(Character.toChars(0xFEFF)), " ");

Creating A WordPress Blog Slug – NodeJS

A slug in WordPress is the part of the URL that references the blog title. For example, if the URL looks like example.com/2019/this-is-my-test-post, then this-is-my-test-post would be a slug. Typically a slug is all letters and numbers, with any other character being replaced by a dash.

The below code fragment is a simple JS function to reduce a blog title down to a slug – you may want to add some additional code to guarantee a certain slug length.


var generateSlug = function generateSlug(title) {
  var allowable_characters = "abcdefghijklmnopqrstuvwxyz1234567890";
  
  //Builds our own slug
  title = title.trim().toLowerCase();
  var title_array = title.split("");
  
  var outbound_title = " ";
  for ( var i = 0; i < title_array.length; i++) {
    var title_char = title_array[i];
    if ( allowable_characters.indexOf(title_char) != -1 ) {
      outbound_title = outbound_title + title_char;
    }
    else if ( outbound_title.split("").pop() != "-" ) {
      outbound_title = outbound_title + "-";
    }
  }
  
  console.log("Generated slug: " + outbound_title);
  
  return outbound_title.trim();
  
}//end generateSlug

Querying For Previous Published WordPress Posts

The following code example pulls out the last 5 published WordPress posts by their ID, extracts the first ID (which is the last published post ID) and then extracts the post’s tags into an array.

$return_tag_array is a list of the last published post’s tags.

  //Get list of past published posts, up to 5
  $args = array(
	'numberposts' => 5,
	'offset' => 0,
	'category' => 0,
	'orderby' => 'post_date',
	'order' => 'DESC',
	'include' => '',
	'exclude' => '',
	'meta_key' => '',
	'meta_value' =>'',
	'post_type' => 'post',
	'post_status' => 'publish',
	'suppress_filters' => true
);
	
  $published_posts = wp_get_recent_posts( $args, ARRAY_A );

  //Pull off the top most post, & retrieve the ID
  $last_published_post = reset($published_posts);
  $last_published_post_id = $last_published_post["ID"];

  //TAGS	
  //Use the post ID to pull off tags
  $tags = wp_get_post_tags($last_published_post_id);
  $return_tag_array = array();	
  foreach ($tags as $tag) {
	  $tag_name = $tag->name;
	  array_push($return_tag_array, $tag_name);
  }

Google Doodle: 30th Anniversary Of The World Wide Web

Today’s Google doodle celebrates the 30th anniversary of the world wide web. Here’s a screenshot of today’s Google front page:

Google front page for March 12, 2019.

Here’s the doodle itself:

The Google doodle for March 12, 2019.

Clicking on the doodle performs a Google search for World Wide Web:

Clicking on the doodle Google search.

On the Google front page, clicking on the text Happy Birthday to the World Wide Web goes to a Google Arts & Culture page discussing the history of the Internet:

Adding Categories To A WordPress Post

I’ve been writing a custom WordPress plugin to accept emailed posts and insert them into a WordPress blog. One of the difficult issues I’ve encountered is that WordPress deals with tags and categories in different ways: it’s relatively easy to add and remove tags. It takes a bit of roundabout work to do the same with categories.

The below code fragment takes a string array of categories ( $to_post_categories ) and sets them onto a post (the ID of the post is in $created_post_id ).

	//Set post categories
	/**
	 * WP doesn't allow us to set categories as easily as tags. With tags we can simply declare 
	 * the names of the tags and be done with it. WP requires that we pass in the ID of the category, 
	 * and if the category doesn't exist, we need to create it. So we loop through the array of 
	 * category names, see if they exist (and if so, collect the ID) and if they don't exist, 
	 * create the category and map the ID to the post.
	 **/
	 foreach ($to_post_categories as $category_name) {
		 $category_id = get_category_by_slug($category_name);
		 if ($category_id == false) {
			 //Category doesn't exist, create it
			 $category_id = wp_create_category($category_name);
		 }
		 
		 //category_id now holds ID of right category or recently created category.
		 //Add category to post
		 wp_set_post_categories($created_post_id, array($category_id), true);
	 }//end looping through post categories sent to us

Newsworthy And Non-Newsworthy Searches

I stumbled upon this interesting article from The Verge, where YouTube modified its search results by tagging Brie Larson as part of the news: https://www.theverge.com/2019/3/8/18255265/brie-larson-youtube-captain-marvel-mcu-algorithm-review-bomb-trolls .

In short, YouTube searches for Brie Larson were initially returning videos about boycotting the movie Captain Marvel. By tagging Larson as a news item, the search results immediately changed to reflect videos from authoritative news services: ABC, CBS, Entertainment Tonight, and so forth. This is a useful function for most people searching, as most users will be looking for late night interviews, news media reports, and so forth.

A search for Brie Larson on YouTube returns videos from news services – note the Top news notice on the top of the image.

As this article demonstrates, search context can be very important. To fully learn about a topic, it’s vitally important to search Google, review the results, then make more searches that are informed by your previous searches. Let’s say you’re a journalist, and want to write about Brie Larson. You’d start out with a general Google and YouTube search about Larson. Then by reviewing the search results (at least the first 2-3 pages of results) you’d learn that there was controversy over Larson playing Captain Marvel. Then you could search for Brie Larson Captain Marvel. Then Brie Larson controversy.

Possibly you might dig a bit deeper and search for Brie Larson boycott. After you’ve exhausted that route, follow other discussion threads: for example, searching for Brie Larson fans, or Captain Marvel box office numbers.

A search for Brie Larson boycott reveals further information for an aspiring journalist. Why is there a boycott? Further Google searching would help.

There are numerous ways that a good journalist could dig up even more information about this issue – for example, why not use Google’s date searching feature to exclude recent news reports and only search earlier postings?

Googling current-news topics can be difficult, as you’ll see many current news items pop up on your results. With intelligent Googling, you can extract useful knowledge about almost anything.

Distance Search: The AROUND(#) Search Operator – The Most Underrated Google Search Function

The AROUND(#) search operator is one of my favorite, and frankly underrated, search functions. It is a distance operator between two words; in other words, it searches for web pages that have two words together, with no more than # of words separating them.

Here’s a simple example. Suppose I tried searching for bacon AROUND(3) cheeseburger.

bacon AROUND(3) cheeseburger

Google returns the expected bacon cheeseburger results, but there are also some interesting, unexpected results. The second result is for a bacon avocado cheeseburger (1 word – avocado – separating our search terms of bacon and cheeseburger). The third result is for a bacon ultimate cheeseburger (again, 1 word separating bacon and cheeseburger). The fourth result is for cheeseburgers with bourbon bacon (2 words – with bourbon – separating our search terms).

Use the operator whenever you need to find two words closely associated with each other, but possibly modified by other words. Try not to use a high # with AROUND(#) – I would suggest no more than 5 unless there’s a really good reason for a greater distance.

Google Doodle: International Women’s Day

Today, March 8 2019, Google celebrates International Women’s Day with a doodle. Here’s how the doodle looks like on the Google home page:

Clicking on the doodle makes it expand:

And then moves into a slideshow with quotes from famous women:

Clicking on the search option goes to a Google search for International Women’s Day. Clicking the share option goes to a screen to share on Twitter, Facebook and other social media: