api strange response to Arduino Query

I am trying to make a api query to a smart citizen kit (sck) from inside an Arduino sketch.

If I just enter this api query in a browser window menu bar:
http://api.smartcitizen.me//v0.0.1/6e0428e19cf2bff1a9c05d14d0400bf4/me.json

Then I get the proper sck api response in the browser window:

{"me":{"id":"8","username":"mdeheras","city":"Barcelona","country":"Spain","website":"","email":"mdeheras@gmail.com","created":"2013-04-24 18:04:46","role":"citizen","devices":[{"id":"3","title":"SCK Hospitalet","description":"","location":"Hospitalet de Llobregat, Espa\u00f1a","city":"Hospitalet de Llobregat","country":"Espa\u00f1a","exposure":"outdoor","elevation":"100.0","geo_lat":"41.369310000000000","geo_long":"2.118000000000000","created":"2013-05-29 21:06:56 UTC","last_insert_datetime":"2014-03-24 01:00:44 UTC"},{"id":"41","title":"SCK Hangar","description":"","location":"Hangar, Poble Nou","city":"Barcelona","country":"Spain","exposure":"indoor","elevation":"12.0","geo_lat":"41.408420000000000","geo_long":"2.199940000000000","created":"2013-04-25 18:34:47 UTC","last_insert_datetime":"2014-03-27 13:22:16 UTC"},{"id":"333","title":"SCK_v1.1_proto","description":"","location":"Barcelona, Espa\u00f1a","city":"Barcelona","country":"Espa\u00f1a","exposure":"indoor","elevation":"0.0","geo_lat":"41.408650000000000","geo_long":"2.199620000000000","created":"2013-09-25 16:33:11 UTC","last_insert_datetime":"2015-07-09 19:02:55 UTC"},{"id":"549","title":"SCK_v1.1_KickStarter","description":"","location":"B, Espa\u00f1a","city":"B","country":"Espa\u00f1a","exposure":"indoor","elevation":"0.0","geo_lat":"41.408787694438730","geo_long":"2.199398109625249","created":"2014-01-16 13:04:50 UTC","last_insert_datetime":"2015-04-14 08:54:15 UTC"},{"id":"2389","title":"Smart Citizen TFM","description":"","location":"Barcelona, Spain","city":"","country":"","exposure":"indoor","elevation":"0.0","geo_lat":"41.410870161481420","geo_long":"2.150874137878418","created":"2015-07-10 14:50:11 UTC","last_insert_datetime":"2015-07-20 14:09:01 UTC"}]}}

But if I make the same query from within an Arduino sketch like this (Based on the Arduino WifiWebClient example):

WiFiClient client;

client.println("GET /v0.0.1/6e0428e19cf2bff1a9c05d14d0400bf4/me.json");
client.println("Host: api.smartcitizen.me");

while (client.available()) {
char c = client.read();
Serial.write(c);

Then I get back a strange response like this:

404 Not Found

Not Found

The requested URL /v0.0.1/6e0428e19cf2bff1a9c05d14d0400bf4/me.json was not found on this server.


Apache/2.4.7 (Ubuntu) Server at analytics.smartcitizen.me Port 80

Which is nothing like the response that I am looking for (the first response from above). It is strange for two reasons. First it looks like HTML code instead of the text response I am looking for (I can kind of understand how that is happening). Second, it is saying the requested URL was not found. I am pretty sure that I broke apart the URL into the "host" and "get" statements properly.

Any idea what I might be doing wrong? How can I get back the nice sck API response from such a query?

I tried changing the GET command in these ways with no luck:
client.println("GET api.smartcitizen.me/v0.0.1/6e0428e19cf2bff1a9c05d14d0400bf4/me.json");
and
client.println("GET v0.0.1/6e0428e19cf2bff1a9c05d14d0400bf4/me.json");

Thank you,
Drew

The 404 response you're getting is from "analytics.smartcitizen.me" not "api.smartcitizen.me". This means that the two servers are the same machine using virtual hosts, and that for some reason the server is not understanding your "Host:" header and therefore using the default host, which in this case is "analytics.smartcitizen.me", which does not have a "/v0.0.1/6e0428e19cf2bff1a9c05d14d0400bf4/me.json" URI.

Looking at your code, I suspect its because you've missed off the HTTP version token, so its defaulting to HTTP 1.0, which does not define the Host header.

You need to change to:

client.println("GET /v0.0.1/6e0428e19cf2bff1a9c05d14d0400bf4/me.json HTTP/1.1");

Let us know if that works. If not, can you please post your entire code so we can get a better idea of whats going on.

Wow, that fixed it. Now I get back the correct API response.

That took not only code expertise but quite a bit of deductive reasoning!

Thank you!
Drew

Thank you with the help above. Here is a follow on question if you could take a look please.
Using the code from the post above, I can now get the current temp, humidity, pollution, etc from the smart citizen kit to my Arduino. That part of my project is pretty much done! Thank you.
Now for another branch of my project, I need to “send” a tSet (temperature setting / desired room temperaure) to the Arduino. I can set the tSet using buttons on the breadboard, but I certainly would like to set the tSet through a wifi connection over the internet. Ideally, I would have a web based (or mobile android based) app that “pushes” the tSet variable to the Arduino. That seems really difficult, but I would love to try if anybody has any advice for pursuing that (java applet that pushes tSet to Arduino acting as a client…???).
The simpler plan I am proceeding with (one week until project day) is to just type my desired tSet on a webpage and have the Arduino “get” that webpage and read the tSet number. My idea is to use a google doc as the page to upload my tSet, because google docs are easy to edit and upload (maybe this is my bad decision). Here is the google doc I am using for this. It is freely viewable.

https://docs.google.com/document/d/1zzZiicQ5zlc0evlxEkyygvefJj1YpEUcgnJ2B5pdoFw/edit

So to “get” this page, I use the following code in my program:

client.println("GET /document/d/1zzZiicQ5zlc0evlxEkyygvefJj1YpEUcgnJ2B5pdoFw/edit HTTP/1.1");
client.println("Host: docs.google.com");

(Entire Code attached at bottom)
(I have tried this with and without the “edit” at the end of the address)

But I get an unexpected response to this “get” statement. Instead of getting the webpage contents, I get a “HTTP/1.1 301 Moved Permanently” error. The error tells me the page has moved, but then gives me back the exact page address that I was trying to get. Here is the full response to the “get” command:

HTTP/1.1 301 Moved Permanently
Content-Type: text/html; charset=UTF-8
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: Fri, 01 Jan 1990 00:00:00 GMT
Date: Sat, 22 Aug 2015 07:16:01 GMT
Location: https://docs.google.com/document/d/1zzZiicQ5zlc0evlxEkyygvefJj1YpEUcgnJ2B5pdoFw/edit
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Server: GSE
Accept-Ranges: none
Vary: Accept-Encoding
Connection: close

<HTML>
<HEAD>
<TITLE>Moved Permanently</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
<H1>Moved Permanently</H1>
The document has moved <A HREF="https://docs.google.com/document/d/1zzZiicQ5zlc0evlxEkyygvefJj1YpEUcgnJ2B5pdoFw/edit">here</A>.
</BODY>
</HTML>

So my questions are:

  1. Any idea why my query to docs.google.com doesn’t work and how to make it work?
    or
  2. If the problem is inherent to docs.google.com any other domain suggestion where the page is easily editable?
    or
  3. Any tips to pursue my “ideal” solution of actually “push” the tSet variable to the Arduino?

Thanks,
Drew

(entire code here)

/*
  Web client
  This sketch connects to a website using a WiFi shield.
 */


#include <SPI.h>
#include <WiFi.h>

 char ssid[] = "twosom2F"; //  your network SSID (name) 
 char pass[] = "027421008";    // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0;            // your network key Index number (needed only for WEP)

int status = WL_IDLE_STATUS;
// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
//IPAddress server(74,125,232,128);  // numeric IP for Google (no DNS)

 char server[] = "docs.google.com";

// Initialize the Ethernet client library
// with the IP address and port of the server 
// that you want to connect to (port 80 is default for HTTP):
WiFiClient client;

void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600); 
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
  
  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present"); 
    // don't continue:
    while(true);
  } 
  
  // attempt to connect to Wifi network:  
  while (status != WL_CONNECTED) { 
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:    
    status = WiFi.begin(ssid, pass);
  
    // wait 5 seconds for connection:
    delay(5000);
  } 
  Serial.println("Connected to wifi");
  printWifiStatus();
  
  Serial.println("\nStarting connection to server...");
  // if you get a connection, report back via serial:
    if (client.connect(server, 80)) {
    Serial.println("connected to server");
    // Make a HTTP request:
    
    client.println("GET /document/d/1zzZiicQ5zlc0evlxEkyygvefJj1YpEUcgnJ2B5pdoFw/edit HTTP/1.1");
    client.println("Host: docs.google.com");
    client.println("Connection: close");
    client.println();
  }
}

void loop() {
  // if there are incoming bytes available 
  // from the server, read them and print them:
  while (client.available()) {
    char c = client.read();
    Serial.write(c);
  }

  // if the server's disconnected, stop the client:
  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting from server.");
    client.stop();

    // do nothing forevermore:
    while(true);
  }
}

void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

As the last question is really a new question. I reposted it as a new post here

Thanks, Drew