Mercurial > hg
annotate tests/get-with-headers.py @ 24545:9e0c67e84896
json: implement {tags} template
Tags is pretty easy to implement. Let's start there.
The output is slightly different from `hg tags -Tjson`. For reference,
the CLI has the following output:
[
{
"node": "e2049974f9a23176c2addb61d8f5b86e0d620490",
"rev": 29880,
"tag": "tip",
"type": ""
},
...
]
Our output has the format:
{
"node": "0aeb19ea57a6d223bacddda3871cb78f24b06510",
"tags": [
{
"node": "e2049974f9a23176c2addb61d8f5b86e0d620490",
"tag": "tag1",
"date": [1427775457.0, 25200]
},
...
]
}
"rev" is omitted because it isn't a reliable identifier. We shouldn't
be exposing them in web APIs and giving the impression it remotely
resembles a stable identifier. Perhaps we could one day hide this behind
a config option (it might be useful to expose when running servers
locally).
The "type" of the tag isn't defined because this information isn't yet
exposed to the hgweb templater (it could be in a follow-up) and because
it is questionable whether different types should be exposed at all.
(Should the web interface really be exposing "local" tags?)
We use an object for the outer type instead of Array for a few reasons.
First, it is extensible. If we ever need to throw more global properties
into the output, we can do that without breaking backwards compatibility
(property additions should be backwards compatible). Second, uniformity
in web APIs is nice. Having everything return objects seems much saner than
a mix of array and object. Third, there are security issues with arrays
in older browsers. The JSON web services world almost never uses arrays
as the main type for this reason.
Another possibly controversial part about this patch is how dates are
defined. While JSON has a Date type, it is based on the JavaScript Date
type, which is widely considered a pile of garbage. It is a non-starter
for this reason.
Many of Mercurial's built-in date filters drop seconds resolution. So
that's a non-starter as well, since we want the API to be lossless where
possible. rfc3339date, rfc822date, isodatesec, and date are all lossless.
However, they each require the client to perform string parsing on top of
JSON decoding. While date parsing libraries are pretty ubiquitous, some
languages don't have them out of the box. However, pretty much every
programming language can deal with UNIX timestamps (which are just
integers or floats). So, we choose to use Mercurial's internal date
representation, which in JSON is modeled as float seconds since UNIX
epoch and an integer timezone offset from UTC (keep in mind
JavaScript/JSON models all "Numbers" as double prevision floating point
numbers, so there isn't a difference between ints and floats in JSON).
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Tue, 31 Mar 2015 14:52:21 -0700 |
parents | 747401086a38 |
children | 5a6820f8da4d |
rev | line source |
---|---|
2532
84655f721f39
Add a test for getting raw files via the web UI.
Eric Hopper <hopper@omnifarious.org>
parents:
diff
changeset
|
1 #!/usr/bin/env python |
84655f721f39
Add a test for getting raw files via the web UI.
Eric Hopper <hopper@omnifarious.org>
parents:
diff
changeset
|
2 |
8447
d5ebcf8f6855
tests: fix doc string in get-with-headers.py
Martin Geisler <mg@lazybytes.net>
parents:
7544
diff
changeset
|
3 """This does HTTP GET requests given a host:port and path and returns |
2532
84655f721f39
Add a test for getting raw files via the web UI.
Eric Hopper <hopper@omnifarious.org>
parents:
diff
changeset
|
4 a subset of the headers plus the body of the result.""" |
84655f721f39
Add a test for getting raw files via the web UI.
Eric Hopper <hopper@omnifarious.org>
parents:
diff
changeset
|
5 |
10905
13a1b2fb7ef2
pylint, pyflakes: remove unused or duplicate imports
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
9722
diff
changeset
|
6 import httplib, sys |
7054
e837f2294643
get-with-headers: fix stream modes under Windows
Patrick Mezard <pmezard@gmail.com>
parents:
5561
diff
changeset
|
7 |
e837f2294643
get-with-headers: fix stream modes under Windows
Patrick Mezard <pmezard@gmail.com>
parents:
5561
diff
changeset
|
8 try: |
24543
747401086a38
get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23409
diff
changeset
|
9 import json |
747401086a38
get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23409
diff
changeset
|
10 except ImportError: |
747401086a38
get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23409
diff
changeset
|
11 try: |
747401086a38
get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23409
diff
changeset
|
12 import simplejson as json |
747401086a38
get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23409
diff
changeset
|
13 except ImportError: |
747401086a38
get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23409
diff
changeset
|
14 json = None |
747401086a38
get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23409
diff
changeset
|
15 |
747401086a38
get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23409
diff
changeset
|
16 try: |
7054
e837f2294643
get-with-headers: fix stream modes under Windows
Patrick Mezard <pmezard@gmail.com>
parents:
5561
diff
changeset
|
17 import msvcrt, os |
e837f2294643
get-with-headers: fix stream modes under Windows
Patrick Mezard <pmezard@gmail.com>
parents:
5561
diff
changeset
|
18 msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) |
e837f2294643
get-with-headers: fix stream modes under Windows
Patrick Mezard <pmezard@gmail.com>
parents:
5561
diff
changeset
|
19 msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY) |
e837f2294643
get-with-headers: fix stream modes under Windows
Patrick Mezard <pmezard@gmail.com>
parents:
5561
diff
changeset
|
20 except ImportError: |
e837f2294643
get-with-headers: fix stream modes under Windows
Patrick Mezard <pmezard@gmail.com>
parents:
5561
diff
changeset
|
21 pass |
e837f2294643
get-with-headers: fix stream modes under Windows
Patrick Mezard <pmezard@gmail.com>
parents:
5561
diff
changeset
|
22 |
12182
1121af239761
tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10905
diff
changeset
|
23 twice = False |
1121af239761
tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10905
diff
changeset
|
24 if '--twice' in sys.argv: |
1121af239761
tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10905
diff
changeset
|
25 sys.argv.remove('--twice') |
1121af239761
tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10905
diff
changeset
|
26 twice = True |
18400
f1118507174b
get-with-headers: add a --headeronly switch
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
18393
diff
changeset
|
27 headeronly = False |
f1118507174b
get-with-headers: add a --headeronly switch
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
18393
diff
changeset
|
28 if '--headeronly' in sys.argv: |
f1118507174b
get-with-headers: add a --headeronly switch
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
18393
diff
changeset
|
29 sys.argv.remove('--headeronly') |
f1118507174b
get-with-headers: add a --headeronly switch
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
18393
diff
changeset
|
30 headeronly = True |
24543
747401086a38
get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23409
diff
changeset
|
31 formatjson = False |
747401086a38
get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23409
diff
changeset
|
32 if '--json' in sys.argv: |
747401086a38
get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23409
diff
changeset
|
33 sys.argv.remove('--json') |
747401086a38
get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23409
diff
changeset
|
34 formatjson = True |
12182
1121af239761
tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10905
diff
changeset
|
35 |
12250
bd98796c0b6f
tests: fix incompatibility with python-2.4 in test-hgweb
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
12182
diff
changeset
|
36 reasons = {'Not modified': 'Not Modified'} # python 2.4 |
bd98796c0b6f
tests: fix incompatibility with python-2.4 in test-hgweb
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
12182
diff
changeset
|
37 |
12182
1121af239761
tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10905
diff
changeset
|
38 tag = None |
1121af239761
tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10905
diff
changeset
|
39 def request(host, path, show): |
17017
953faba28e91
tests: prepare get-with-headers.py for MSYS
Mads Kiilerich <mads@kiilerich.com>
parents:
12250
diff
changeset
|
40 assert not path.startswith('/'), path |
12182
1121af239761
tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10905
diff
changeset
|
41 global tag |
1121af239761
tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10905
diff
changeset
|
42 headers = {} |
1121af239761
tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10905
diff
changeset
|
43 if tag: |
1121af239761
tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10905
diff
changeset
|
44 headers['If-None-Match'] = tag |
5561
22713dce19f6
hgweb: return meaningful HTTP status codes instead of nonsense
Bryan O'Sullivan <bos@serpentine.com>
parents:
2532
diff
changeset
|
45 |
12182
1121af239761
tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10905
diff
changeset
|
46 conn = httplib.HTTPConnection(host) |
17017
953faba28e91
tests: prepare get-with-headers.py for MSYS
Mads Kiilerich <mads@kiilerich.com>
parents:
12250
diff
changeset
|
47 conn.request("GET", '/' + path, None, headers) |
12182
1121af239761
tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10905
diff
changeset
|
48 response = conn.getresponse() |
12250
bd98796c0b6f
tests: fix incompatibility with python-2.4 in test-hgweb
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
12182
diff
changeset
|
49 print response.status, reasons.get(response.reason, response.reason) |
18380
a4d7fd7ad1f7
serve: don't send any content headers with 304 responses
Mads Kiilerich <madski@unity3d.com>
parents:
17017
diff
changeset
|
50 if show[:1] == ['-']: |
18393
a38039ef7312
tests: make test-hgweb.t output stable
Mads Kiilerich <madski@unity3d.com>
parents:
18380
diff
changeset
|
51 show = sorted(h for h, v in response.getheaders() |
a38039ef7312
tests: make test-hgweb.t output stable
Mads Kiilerich <madski@unity3d.com>
parents:
18380
diff
changeset
|
52 if h.lower() not in show) |
12182
1121af239761
tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10905
diff
changeset
|
53 for h in [h.lower() for h in show]: |
1121af239761
tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10905
diff
changeset
|
54 if response.getheader(h, None) is not None: |
1121af239761
tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10905
diff
changeset
|
55 print "%s: %s" % (h, response.getheader(h)) |
18400
f1118507174b
get-with-headers: add a --headeronly switch
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
18393
diff
changeset
|
56 if not headeronly: |
f1118507174b
get-with-headers: add a --headeronly switch
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
18393
diff
changeset
|
57 print |
23409
dc4d2cd3aa3e
hgweb: send proper HTTP response after uncaught exception
Gregory Szorc <gregory.szorc@gmail.com>
parents:
19865
diff
changeset
|
58 data = response.read() |
24543
747401086a38
get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23409
diff
changeset
|
59 |
747401086a38
get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23409
diff
changeset
|
60 # Pretty print JSON. This also has the beneficial side-effect |
747401086a38
get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23409
diff
changeset
|
61 # of verifying emitted JSON is well-formed. |
747401086a38
get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23409
diff
changeset
|
62 if formatjson: |
747401086a38
get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23409
diff
changeset
|
63 if not json: |
747401086a38
get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23409
diff
changeset
|
64 print 'no json module not available' |
747401086a38
get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23409
diff
changeset
|
65 print 'did you forget a #require json?' |
747401086a38
get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23409
diff
changeset
|
66 sys.exit(1) |
747401086a38
get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23409
diff
changeset
|
67 |
747401086a38
get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23409
diff
changeset
|
68 # json.dumps() will print trailing newlines. Eliminate them |
747401086a38
get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23409
diff
changeset
|
69 # to make tests easier to write. |
747401086a38
get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23409
diff
changeset
|
70 data = json.loads(data) |
747401086a38
get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23409
diff
changeset
|
71 lines = json.dumps(data, sort_keys=True, indent=2).splitlines() |
747401086a38
get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23409
diff
changeset
|
72 for line in lines: |
747401086a38
get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23409
diff
changeset
|
73 print line.rstrip() |
747401086a38
get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23409
diff
changeset
|
74 else: |
747401086a38
get-with-headers: support parsing and pretty printing JSON
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23409
diff
changeset
|
75 sys.stdout.write(data) |
12182
1121af239761
tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10905
diff
changeset
|
76 |
18400
f1118507174b
get-with-headers: add a --headeronly switch
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
18393
diff
changeset
|
77 if twice and response.getheader('ETag', None): |
f1118507174b
get-with-headers: add a --headeronly switch
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
18393
diff
changeset
|
78 tag = response.getheader('ETag') |
12182
1121af239761
tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10905
diff
changeset
|
79 |
1121af239761
tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10905
diff
changeset
|
80 return response.status |
1121af239761
tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10905
diff
changeset
|
81 |
1121af239761
tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10905
diff
changeset
|
82 status = request(sys.argv[1], sys.argv[2], sys.argv[3:]) |
1121af239761
tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10905
diff
changeset
|
83 if twice: |
1121af239761
tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10905
diff
changeset
|
84 status = request(sys.argv[1], sys.argv[2], sys.argv[3:]) |
1121af239761
tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10905
diff
changeset
|
85 |
1121af239761
tests: extend get-with-headers to support cache testing
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10905
diff
changeset
|
86 if 200 <= status <= 305: |
5561
22713dce19f6
hgweb: return meaningful HTTP status codes instead of nonsense
Bryan O'Sullivan <bos@serpentine.com>
parents:
2532
diff
changeset
|
87 sys.exit(0) |
22713dce19f6
hgweb: return meaningful HTTP status codes instead of nonsense
Bryan O'Sullivan <bos@serpentine.com>
parents:
2532
diff
changeset
|
88 sys.exit(1) |