Friday, March 14, 2014

SLC Tech Breakfast on Mar 21


SLC Tech Breakfast on Fri Mar 21 8:00-9:30 AM downtown at Newmont U. Bagels provided.


coursera at princeton (Josh recommends)
dynamic programming (same as memoization, sounds like)
spring roo (rails-like quick start for Java, if I remember right)
linq (for allowing SQL-like data queries in language)jlinq, jpropel
"clock of complexity"
malbolge: unreadable programming language

Friday, February 7, 2014

Today's CTO Breakfast



  • Trent Larson mentioned tool for P2P sharing family histories (familyhistories.info)
  • Sano Inteiligence for a subdermal patch for monitoring the blood stream
  • True Crypt (vs Best Crypt), with hidden volumes
  • BTSync for P2P file distribution
  • "Scrypt" coin using GPUs vs Bitcoin (w/ SHA256)
  • Vivian at Gild & Provo Dojo last night about underappreciated Utah developers
  • SaltStack, which Wade prefers over Puppet
  • Intel Galileo, running Arduino but also Linux, $60 with power on Amazon, including Wifi connector
  • playing music on a dodecahedron, drawn on a ping-pong ball with an egg-bot, then icosahedron, and then she talked about a theramin
  • Espruino, an Arduino-like board using Javascript
  • NodeRed from Google for graphical design of a node program
  • Google's purchase of Nest
  • Scott mentioned using NFC to configure devices, and Kelly Flanagan is doing it
  • power requirements & parasitic power

Thursday, January 16, 2014

Tomorrow's tech breakfast



Tomorrow morning, 8 AM, downtown: above Jason's Deli at the Gateway.

From Garth: There is a parking lot in front of Jason's Deli (you just have to make sure that the parking space says for gateway office) and the doors to the office are to the right of the entrance to Jason's Deli. My office is in suite 230.

Bagels

Here's other background info.

Friday, December 13, 2013

Yet Another SLC Tech Breakfast



Anyone using functional programming?  (Josh has done Scala)

Josh Bloch (Effective Java) & anonymous types vs Neil Gafter & closures

Tom Clancy's game The Division has an impressive new game engine

TED talk: consequences of game on real life

languages: Dart, Go, Underscore.js

Speed dating with google glass


Saturday, May 4, 2013

A command-line testing harness for multiple RESTful HTTP requests


Tasked with the creation of a quick-and-dirty REST service, I wanted an easy way to throw in a bunch of test data and verify it with the correct response data and HTTP response codes.  Most testing tools require some infrastructure and editing through their UI; I wanted to throw data (both input and output) into an easy-to-edit text file.  Here's the result.

First, here's the input test data:
POST /entry/ffff/3456
POST /entry/
POST /entry/12
POST /entry/12/qqqq
GET /entry/ffff
GET /entry/fffe
GET /entry/
POST /entry/zz/zyx
POST /entry/az/zyx
POST /entry/34/zyx
POST /entry/AF/zyx
POST /entry/zez/zyx
GET /list/0
GET /list/1
(I put this in the file named "test-input")

Sidebar 1: eyeballing the results

This was actually given to me as the full telnet command, so every entry had "HTTP/1.1" on the end, for example:
POST /entry/ffff/3456 HTTP/1.1
So first iteration was to start my server separately, then run a script that would echo that line and pipe it through "telnet 127.0.0.1 8080".  For example, here are the first 2 tests, located inside my "entries.in" file:


sleep 2
echo POST /entry/ffff/3456 HTTP/1.1      # should return a 200 OK response
echo
sleep 2
echo POST /entry/ HTTP/1.1       # should return 400 BAD REQUEST
echo 
(Interestingly, those comments at the end of each line are acceptable.)


Then I ran the following command:

.  ./entries.in | telnet 127.0.0.1 8080

(Note the "." at the first of the line, meaning to source that file to run the commands inside.)

That works great for me to run all the tests quickly, but I have to visually check the output.

End Sidebar 1

Here is the output expected; of course, only the GET commands result in output.


3456               # GET /entry/ffff
ffff -> 3456    # GET /entry/
ffff -> 3456    # following 4 are generated by GET /entry/
12 -> qqqq
zz -> zyx
az -> zyx
34 -> zyx       # following 3 are generated by GET /list/1
AF -> zyx
zez -> zyx
(That is in the file I named "test-output.body.good", without the # commentary.)


And here are the HTTP response codes expected:

HTTP/1.1 200 OK
HTTP/1.1 400 BAD REQUEST
HTTP/1.1 400 BAD REQUEST
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 404 NOT FOUND
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
(That is in the file I named "test-output.HTTP-response.good")


Now for the scripting.  Note that this requires Resty, a very convenient wrapper to access RESTful services via curl.

Here are the commands to run those HTTP inputs into my server and check the body of the output.
# run the HTTP server in the background, throwing away any output
python entries.py > /dev/null 2>&1 &
# save the process ID for that server
PID=$!
# wait for the server to fully start
sleep 1
# prepare resty, without verbose output from curl
resty http://127.0.0.1:8080 -s
# use the contents of the test-input file as one command per line
# (via Resty, which has made GET and POST into valid commands)
. ./test-input > test-output.body.out
# check that output against the expected output
diff test-output.body.good test-output.body.out
# stop the HTTP server
kill $PID
# wait for the server to fully stop
sleep 1


And here is how to do the same to check the HTTP response codes of the output.  Note that only the 3 commands after "sleep" are different.

# run the HTTP server in the background, throwing away any output
python entries.py > /dev/null 2>&1 &
# save the process ID for that server
PID=$!
# wait for the server to fully start
sleep 1
# prepare resty, without verbose output and with only the HTTP headers from curl
resty http://127.0.0.1:8080 -s -I
# use the contents of the test-input file as one command per line
# (via Resty, which has made GET and POST into valid commands)
# (Why does it end up in DOS format? Is that curl?!  ... and printing "not found" is dumb.)
. ./test2-input 2>&1 | grep HTTP > test2-output.HTTP-response.out
# check that output against the expected output
# (See the previous command for the reason behind --strip-trailing-cr)
diff --strip-trailing-cr test2-output.HTTP-response.good test2-output.HTTP-response.out 
# stop the HTTP server
kill $PID
# wait for the server to fully stop
sleep 1



That's it!  Now I've got those 3 files (input HTTP commands, output body content, and output HTTP codes) and a script that will run all those inputs and verify the outputs exactly.

Note: as this grows, I've found that I'd prefer to have the input, the output HTTP code, and the output body all next to each other, or maybe on subsequent lines of the same file.  But this fit today's use cases!





Sunday, April 1, 2012

Setting and retrieving LockerProject data in a local install


I've been trying to play with LockerProject from Singly, and I'd like to use data other than the built-in types of contacts, links, photos, and places.  (You can see one project that motivates me at familyhistories.info.)  There are ways to build new connectors and collections that support rich functionality like syncing, but there is also a simple Push API that allows for arbitrary data, so I've started by playing with that.  Following are some changes I had to make to get things working.

We can send and retrieve arbitrary data via curl, and those examples work great.

Set:
curl -H "Content-Type: application/json" \  
--data-binary '{"data":[{"id":42,"question":"my test"}]}' \  
http://localhost:8042/push/foo 
 
ok

Get:
curl http://localhost:8042/push/foo/42
 
{"_id":"4f2752c03f670f3343f7fed0","id":42,"question":"my test"}

Unfortunately, things don't work as smoothly when trying to do it in an app.  Let's start with retrieval.  First of all, we need get data from the local locker instead of the one at singly.com.  The best approach I can think is to tweak the APIClient so that we can specify which host, so instead of "new APIClient()" we can do the following:
new APIClient({baseUrl:'http://localhost:8042'})
Great.

Except now my browser won't retrieve the value via AJAX; Chrome is the most helpful, and it tells me:
Origin null is not allowed by Access-Control-Allow-Origin.
The only way I can figure to get past this is to modify LockerProject.  So I've added the following to the Ops/webservice.js file as the first line in the first function argument to express.createServer:

// "*" works for all domains; null and "X-Requested-With" work for file:// URLs in Firefox but not Chrome
res.header("Access-Control-Allow-Origin", "*");
Cool.  Now I can retrieve values that I've inserted.  This might not be a great solution, and I haven't thought through the security complications so that I can submit it to LockerProject, but I'm just going to live with it on my machine.

Unfortunately, this is where we're stuck.  It's easy enough to add a post to insert data, but there is a problem within the parsing of JSON in the locker server: it takes any values as strings, so even though we send an update/insert like the data above with a numeric ID of 42, it ends up inserting some data with a string ID of "42"... and we can't retrieve that value with the typical GET request (above)... in fact, I cannot find any way to retrieve that data through the API.  You can see it as it gets processed in the web server and you can see it inside your mongo DB.  Most unfortunate.

In summary, to get arbitrary data from your local locker in a browser app:
  • patch the locker server (see Access-Control-Allow-Origin above)
  • use the client customizations (demonstrated here in the singly-api-local.js and the test-new-datatype.html files)
To set arbitrary data in your local locker in a browser app... you're out of luck due to the string problem.

Maybe there's a better way...?


Getting results with Singly's "Build An App!"


The Singly (AKA LockerProject) approach to building an app is pretty simple, but the current instructions didn't work for me locally.  (You can see the instructions after logging in to singly.com and then going to the "Build An App!" page.)  The difficulty may be that I used my index.html incorrectly, but it was the best I could guess: I simply accessed it directly with a "file:///..." URL.  (If anyone knows a better place, I'd love to know; I tried putting it in a separate webserver I've got locally, to no avail.)  I can get this to work, but it requires some tweaking.

The symptom in Firefox was a blank page, and in the Javascript console there was an error: "Operation is not supported" on a line with sessionStorage.  I found that sessionStorage won't work for local ("file") URLs (thanks to this StackOverflow post).

So I changed the references in the api.js to localStorage and things worked for me.  Here is my version: https://github.com/trentlarson/singly-relaxing/blob/5e9cf2c1801b78c130cdc79e84a4cdbf2b3b2deb/singly-api-local.js

It uses a conditional, so I'm hoping it can be used at singly.com as a patch to the default version.