I'm working on a JSON API and I want to do something like Facebook's opengraph styling.
The opengraph style indents and breaks lines, how do you go about doing this? If you use styling through HTML or CSS the JSON can not be loaded.
You can use JSON_PRETTY_PRINT which is new in PHP 5.4:
<?php
// Facebook sends a Content-Type of text/javascript
// So I assume you want to too, but you may prefer
// application/json
header('Content-Type: text/javascript');
echo json_encode($data, JSON_PRETTY_PRINT);
?>
If you don't have, or can't upgrade to version 5.4 then you have to find some side of server-side parser.
Edit
I don't know why I assumed you're using PHP when you haven't tagged it. Whatever server side language you're using though you'll want to send out a non-html Content-Type and use new lines and tabs to pretty print it, not HTML.
facebook appear to be using browser detection to format the JSON on the server.
for wget, no formatting is applied:
> wget -q -S -O - http://graph.facebook.com/4
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Cache-Control: private, no-cache, no-store, must-revalidate
Content-Type: text/javascript; charset=UTF-8
ETag: "539feb8aee5c3d20a2ebacd02db380b27243b255"
Expires: Sat, 01 Jan 2000 00:00:00 GMT
P3P: CP="Facebook does not have a P3P policy. Learn why here: http://fb.me/p3p"
Pragma: no-cache
X-FB-Rev: 526949
Set-Cookie: datr=imJrT4lrhBZ48Mrtw4uYfByk; expires=Sat, 22-Mar-2014 17:34:02 GMT; path=/; domain=.facebook.com; httponly
X-FB-Debug: +gpBLnliDoRvuNtlHIwHASwsDz4pJm9TP3btrrw6AsE=
X-Cnection: close
Date: Thu, 22 Mar 2012 17:34:02 GMT
Content-Length: 172
{"id":"4","name":"Mark Zuckerberg","first_name":"Mark","last_name":"Zuckerberg","link":"http:\/\/www.facebook.com\/zuck","username":"zuck","gender":"male","locale":"en_US"}
but for google chrome, wireshark shows text formatted with spaces and newlines:
{
"id": "4",
"name": "Mark Zuckerberg",
"first_name": "Mark",
"last_name": "Zuckerberg",
"link": "http://www.facebook.com/zuck",
"username": "zuck",
"gender": "male",
"locale": "en_US"
}
(it really is different data - the Content-Length is 210 in this case). note that Content-Type is still text/javascript - they are not rendering into HTML.
so you'd need to use a JSON formatter for whatever language you are using (i guess you are already using a library, so check whether it has a "prettyprint" option or similar). plus, if you want to save bandwidth when formatting seems unimportant, browser (and general context - see Paul's comment) detection from request headers.
Related
folks!
I'm looking for the best and efficient way to parse server responds that content both HTML and XML stuff. The respond come from servers I need to poll each 5 minutes (it's about half a thousand of them in list currently, but it will double very soon). Respond stored in buffer as plane text (got from socket). So, I need to parse HTML part and in case of success (mandatory things found) I should then try to parse XML part and get statistics information to store in DB. The responses are like this:
HTTP/1.0 200 OK
Connection: close
Content-Length: 682
Content-Type: text/xml; charset=utf-8
Date: Sun, 09 Mar 2014 15:44:52 GMT
Last-Modified: Sun, 09 Mar 2014 15:44:52 GMT
Server: DrWebAV-DeskServer/REL-610-AV-6.02.0.201311040 Linux/x86_64 Lua/5.1.4 OpenSSL/1.0.0e
<?xml version="1.0" encoding="utf-8"?><avdesk-xml-api API='2.1.0' API_BUILD='20130709' branch='REL-610-AV' oper='get-server-info' rc='true' timestamp='20140309154452987' version='6.02.0.201311040'><server><id>00c1d140-d21d-b211-a828-b62919c4250d</id><platform>Linux 2.6.39-gentoo-r3 x86_64 (4 SMP Mon Oct 24 11:04:40 YEKT 2011)</platform><version>6.02.0.201311040</version><statistics from='20140301000000000' till='20140309235959999'><noviruses/><stations total='101'><online>5</online><deinstalled>21</deinstalled><blocked>0</blocked><expired>81</expired><offline>96</offline><activated>74</activated><unactivated>27</unactivated></stations></statistics></server></avdesk-xml-api>
And could be smth. like this
HTTP/1.0 401 Authorization Required
Cache-Control: post-check=0, pre-check=0
Connection: close
Content-Length: 421
Content-Type: text/html; charset=utf-8
Date: Sun, 09 Mar 2014 15:44:22 GMT
Expires: Date: Sat, 27 Nov 2004 10:18:15 GMT
Last-Modified: Date: Sat, 27 Nov 2004 10:18:15 GMT
Pragma: no-cahe
Server: DrWebAV-DeskServer/REL-610-AV-6.02.0.201311040 Linux/x86_64 Lua/5.1.4 OpenSSL/1.0.1
WWW-Authenticate: Basic realm="Dr.Web XML API area"
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><HTML><TITLE>Unauthorized</TITLE><BODY><STRONG>Unauthorized</STRONG><P>The error "401 Unauthorized" occured while processing request you had sent.<P><BR><BR><I>Access denied or your browser does not support HTTP authentication!</I><BR><P><BR><BR><HR><P>Dr.Web ® AV-Desk Server REL-610-AV 6.02.0.201311040 Linux/x86_64 Lua/5.1.4 OpenSSL/1.0.1</BODY></HTML>
Concerning HTML part I'm basically interested in HTTP/1.0 STRING and Server: STRING stuff, and then need per-tag XML parsing, if authorization succeeded.
I have found, that libxml2 is suitable for parsing both HTML/XML stuff, but unable to find any real examples how to use it, just some major interface description. So, help needed.
Code examples for libxml2 are here
The mailing list is friendly, and the code is mature and good quality.
However, nothing in your example suggests you need to parse HTML. You need to parse (I think) HTTP to process the headers (and detect the 401 error from the HTTP response), then parse the XML content. Parsing HTTP headers to the level you require it is trivial (just strtok the response separating on line breaks and the first line has the answer you need). The body of the response starts after a double line break (I think your second example has a paste error). This reduces your task to simply processing HTTP headers and XML (no HTML parsing).
I'm trying to send a csv file to the client. I'm setting the right response headers as far as I know (it used to work), and the browser (Chrome, IE) is getting this:
HTTP/1.1 200 OK
Cache-Control: private, s-maxage=0
Transfer-Encoding: chunked
Content-Type: text/csv; charset=utf-8
Content-Encoding: gzip
Vary: Accept-Encoding
Server: Microsoft-IIS/8.0
X-AspNetMvc-Version: 5.0
Content-Disposition: attachment; filename="Cameras_Camcorders_Photo_Frames_Binoculars_Telescope_Surveillance_Camera_Accessories_(10-29-2013).xlsm_140217.csv"
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcbGZlcnJhb1xEb2N1bWVudHNcVmlzdWFsIFN0dWRpbyAyMDEzXFByb2plY3RzXFRlbXBsZXhcdHJ1bmtcQ29uU29sLlRlbXBsZXguV2ViQWxwaGEzXEpvYlxSdW5cMTc1YWRlY2UtYzM2MC00ZjMxLWJkM2YtMjk3ZjNkYWMwNTQ2?=
X-Powered-By: ASP.NET
Date: Mon, 17 Feb 2014 13:02:05 GMT
The form that's triggering the file download is a jQuery form. If I don't use jQuery form, the download occurs normally, if I use jQuery form, nothing happens.
From your comments:
I'm using jQuery Form
From the jQuery Form homepage:
The jQuery Form Plugin allows you to easily and unobtrusively upgrade HTML forms to use AJAX
If you are handling the response with Ajax, then you completely bypass the normal browser mechanism for handling the HTTP response (which decides if it should render or save). It goes to JavaScript instead.
You need to use a regular form submission and not Ajax if you want Content-Disposition to trigger a save action on the response.
I'm converting a Web Api project to service stack and in json responses I'm getting an extra line of text before and after the json content. I'm using fiddler to capture the response.
Edited for brevity, here is an example:
18d
[{"id": ... }]
0
What are these lines? I can't find any configuration option that would seem to correspond to keep this from happening.
Edit
I went back and started with the basic hello service stack example, and here's what I got for a response:
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: application/json; charset=utf-8
Server: Microsoft-HTTPAPI/1.0
X-Powered-By: ServiceStack/3.943 Win32NT/.NET
Date: Thu, 18 Apr 2013 15:48:49 GMT
1b
{"Result":"Hello, JRandom"}
0
I'm assuming the extra response lines are the result of the Transfer-Encoding: chunked header.
On a page of a website we're building http://ovsd.nutrislice.com/wellness/ , pdf download links ("Download the Issue") get stuck while loading in Chrome's PDF Viewer but work in all other browsers by triggering a download. Right click + "Save as" works in Chrome. I realize Chrome is the only browser with a built-in, default pdf viewer.
I figure we can instruct people to right click and then "save as", but I wanted to see if anyone can see a problem with either the html, or in the server response, which would cause chrome to fail like that.
Its not a traditional pass-thru file download sitting on a server somewhere. We use Heroku, and I'm currently storing the pdf's in the DB (I realize the downsides of this, but it was a simpler system than managing off-site files on S3 for now). I'm generating the response dynamically via a Django View, so I wonder if there's something i'm missing in the response headers or something.
Thanks!
Looks like a bad content-type:
Content-Type:('application/pdf', None)
Check your code where you are assigning a content-type to the response. Looks like you're sending a tuple instead of just application/pdf.
Like #dgel mentioned, your content type is incorrect:
$ curl -I http://ovsd.nutrislice.com/dbfiles/cms/resources/Vol5_Issue1_5_Dos_and_Donts_for_Supermarket_Survival.pdf
HTTP/1.1 200 OK
Access-Control-Allow-Methods: POST,GET,OPTIONS,PUT,DELETE
Access-Control-Allow-Origin: *
Cache-Control: max-age=90000
Content-Type: ('application/pdf', None) # <- Incorrect
Date: Fri, 09 Nov 2012 19:25:06 GMT
Expires: Fri, 09 Nov 2012 23:20:28 GMT
Last-Modified: Thu, 08 Nov 2012 22:20:28 GMT
Server: gunicorn/0.14.6
Connection: keep-alive
Also it might be a good idea to add Content-Length header.
Is there a way in htaccess to ensure the headers for my json are correct?
Update: Does anyone see anything wrong with these headers for json?
Date Mon, 26 Jul 2010 08:31:11 GMT
Server Apache/2.2.15 (Unix) mod_ssl/2.2.15 OpenSSL/0.9.7a mod_fcgid/2.3.5 Phusion_Passenger/2.2.15 mod_auth_passthrough/2.1 mod_bwlimited/1.4 FrontPage/5.0.2.2635
X-Powered-By PHP/5.2.13
X-Pingback http://brettbarros.com/wordpress/xmlrpc.php
Content-Disposition attachment; filename="json_api.json"
Vary Accept-Encoding
Content-Encoding gzip
Content-Length 719
Keep-Alive timeout=5, max=98
Connection Keep-Alive
Content-Type application/json; charset=UTF-8
Specifically, it's working with jquery's getJSON in ie8, ffx, chrome, but not ie7 or ie6...
AddType application/json .json
is a simple way to make all your *.json files being sent with the correct mime type. That, of course, doesn't work, if you create them dynamically in something like a, say, PHP script. In that case, you can add the info inside the script:
<?php
header('Content-Type: application/json');
// ...
You can inspect the headers sent along from the server side using Firebug's Net tab. It shows all the headers for both the request and the response.
Make sure the Content-Type is application/json. You can inspect the http headers with wget and whatnot if you aren't sure what they are.