Merge lp:~leonardr/lazr.restful/fix-media-type-misspelling into lp:lazr.restful

Proposed by Leonard Richardson
Status: Merged
Approved by: Gavin Panella
Approved revision: 90
Merged at revision: not available
Proposed branch: lp:~leonardr/lazr.restful/fix-media-type-misspelling
Merge into: lp:lazr.restful
Diff against target: 330 lines
7 files modified
src/lazr/restful/NEWS.txt (+5/-0)
src/lazr/restful/_bytestorage.py (+3/-3)
src/lazr/restful/_resource.py (+14/-8)
src/lazr/restful/example/base/tests/entry.txt (+14/-7)
src/lazr/restful/example/base/tests/wadl.txt (+39/-10)
src/lazr/restful/templates/wadl-root.pt (+3/-3)
src/lazr/restful/version.txt (+1/-1)
To merge this branch: bzr merge lp:~leonardr/lazr.restful/fix-media-type-misspelling
Reviewer Review Type Date Requested Status
Gavin Panella Approve
Review via email: mp+13711@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Leonard Richardson (leonardr) wrote :

This branch fixes bug 457146 by correcting a misspelling of the WADL media type.

The complication is that if we simply correct the misspelling, old versions of lazr.restfulclient will stop working (they'll be served JSON representations instead of WADL). So we need to treat old clients the same way we did before.

I changed all references to the old media type to the new media type, and all code that pivots on the old media type to operate on either the old or new media type. I was a little worried that my changes to the WADL template itself would break old versions of lazr.restfulclient, but a test with an actual old version showed that it didn't matter.

I added tests to wadl.txt that show how to get WADL representations using the misspelled media type. Just to make extra sure, I also ran the entire wadl.txt suite before correcting the misspelling, to make sure that all the old code still worked.

Revision history for this message
Gavin Panella (allenap) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/lazr/restful/NEWS.txt'
--- src/lazr/restful/NEWS.txt 2009-10-20 17:07:56 +0000
+++ src/lazr/restful/NEWS.txt 2009-10-21 15:00:30 +0000
@@ -2,6 +2,11 @@
2NEWS for lazr.restful2NEWS for lazr.restful
3=====================3=====================
44
50.9.15 (2009-10-21)
6===================
7
8Corrected a misspelling of the WADL media type.
9
50.9.14 (2009-10-20)100.9.14 (2009-10-20)
6===================11===================
712
813
=== modified file 'src/lazr/restful/_bytestorage.py'
--- src/lazr/restful/_bytestorage.py 2009-03-26 17:25:22 +0000
+++ src/lazr/restful/_bytestorage.py 2009-10-21 15:00:30 +0000
@@ -59,10 +59,10 @@
5959
60 def do_GET(self):60 def do_GET(self):
61 """See `IByteStorageResource`."""61 """See `IByteStorageResource`."""
62 if self.getPreferredSupportedContentType() == self.WADL_TYPE:62 media_type = self.getPreferredSupportedContentType()
63 if media_type in [self.WADL_TYPE, self.DEPRECATED_WADL_TYPE]:
63 result = self.toWADL().encode("utf-8")64 result = self.toWADL().encode("utf-8")
64 self.request.response.setHeader(65 self.request.response.setHeader('Content-Type', media_type)
65 'Content-Type', self.WADL_TYPE)
66 return result66 return result
67 if not self.context.is_stored:67 if not self.context.is_stored:
68 # No stored document exists here yet.68 # No stored document exists here yet.
6969
=== modified file 'src/lazr/restful/_resource.py'
--- src/lazr/restful/_resource.py 2009-10-20 17:00:23 +0000
+++ src/lazr/restful/_resource.py 2009-10-21 15:00:30 +0000
@@ -171,10 +171,15 @@
171 implements(IHTTPResource)171 implements(IHTTPResource)
172172
173 # Some interesting media types.173 # Some interesting media types.
174 WADL_TYPE = 'application/vd.sun.wadl+xml'174 WADL_TYPE = 'application/vnd.sun.wadl+xml'
175 JSON_TYPE = 'application/json'175 JSON_TYPE = 'application/json'
176 XHTML_TYPE = 'application/xhtml+xml'176 XHTML_TYPE = 'application/xhtml+xml'
177177
178 # This misspelling of the WADL media type was used for a while,
179 # and lazr.restful still supports it to avoid breaking clients
180 # that depend on it.
181 DEPRECATED_WADL_TYPE = 'application/vd.sun.wadl+xml'
182
178 # A preparsed template file for WADL representations of resources.183 # A preparsed template file for WADL representations of resources.
179 WADL_TEMPLATE = LazrPageTemplateFile('templates/wadl-resource.pt')184 WADL_TEMPLATE = LazrPageTemplateFile('templates/wadl-resource.pt')
180185
@@ -183,7 +188,7 @@
183188
184 # All resources serve WADL and JSON representations. Only entry189 # All resources serve WADL and JSON representations. Only entry
185 # resources serve XHTML representations.190 # resources serve XHTML representations.
186 SUPPORTED_CONTENT_TYPES = [WADL_TYPE, JSON_TYPE]191 SUPPORTED_CONTENT_TYPES = [WADL_TYPE, DEPRECATED_WADL_TYPE, JSON_TYPE]
187192
188 def __init__(self, context, request):193 def __init__(self, context, request):
189 self.context = context194 self.context = context
@@ -311,7 +316,7 @@
311 if etag is not None:316 if etag is not None:
312 return etag317 return etag
313318
314 if media_type == self.WADL_TYPE:319 if media_type in [self.WADL_TYPE, self.DEPRECATED_WADL_TYPE]:
315 # The WADL representation of a resource only changes when320 # The WADL representation of a resource only changes when
316 # the software itself changes. Thus, we don't need any321 # the software itself changes. Thus, we don't need any
317 # special information for its ETag core.322 # special information for its ETag core.
@@ -1221,6 +1226,7 @@
1221 implements(IEntryResource, IJSONPublishable)1226 implements(IEntryResource, IJSONPublishable)
12221227
1223 SUPPORTED_CONTENT_TYPES = [HTTPResource.WADL_TYPE,1228 SUPPORTED_CONTENT_TYPES = [HTTPResource.WADL_TYPE,
1229 HTTPResource.DEPRECATED_WADL_TYPE,
1224 HTTPResource.XHTML_TYPE,1230 HTTPResource.XHTML_TYPE,
1225 HTTPResource.JSON_TYPE]1231 HTTPResource.JSON_TYPE]
12261232
@@ -1405,7 +1411,7 @@
14051411
1406 def _representation(self, media_type):1412 def _representation(self, media_type):
1407 """Return a representation of this entry, of the given media type."""1413 """Return a representation of this entry, of the given media type."""
1408 if media_type == self.WADL_TYPE:1414 if media_type in [self.WADL_TYPE, self.DEPRECATED_WADL_TYPE]:
1409 return self.toWADL().encode("utf-8")1415 return self.toWADL().encode("utf-8")
1410 elif media_type == self.JSON_TYPE:1416 elif media_type == self.JSON_TYPE:
1411 return simplejson.dumps(self, cls=ResourceJSONEncoder)1417 return simplejson.dumps(self, cls=ResourceJSONEncoder)
@@ -1446,10 +1452,10 @@
1446 if entries is None:1452 if entries is None:
1447 raise NotFound(self, self.collection_name)1453 raise NotFound(self, self.collection_name)
14481454
1449 if self.getPreferredSupportedContentType() == self.WADL_TYPE:1455 media_type = self.getPreferredSupportedContentType()
1456 if media_type in [self.DEPRECATED_WADL_TYPE, self.WADL_TYPE]:
1450 result = self.toWADL().encode("utf-8")1457 result = self.toWADL().encode("utf-8")
1451 self.request.response.setHeader(1458 self.request.response.setHeader('Content-Type', media_type)
1452 'Content-Type', self.WADL_TYPE)
1453 return result1459 return result
14541460
1455 result = self.batch(entries)1461 result = self.batch(entries)
@@ -1540,7 +1546,7 @@
1540 if media_type is None:1546 if media_type is None:
1541 # The conditional GET succeeded. Serve nothing.1547 # The conditional GET succeeded. Serve nothing.
1542 return ""1548 return ""
1543 elif media_type == self.WADL_TYPE:1549 elif media_type in [self.WADL_TYPE, self.DEPRECATED_WADL_TYPE]:
1544 result = self.toWADL().encode("utf-8")1550 result = self.toWADL().encode("utf-8")
1545 elif media_type == self.JSON_TYPE:1551 elif media_type == self.JSON_TYPE:
1546 # Serve a JSON map containing links to all the top-level1552 # Serve a JSON map containing links to all the top-level
15471553
=== modified file 'src/lazr/restful/example/base/tests/entry.txt'
--- src/lazr/restful/example/base/tests/entry.txt 2009-09-01 13:10:07 +0000
+++ src/lazr/restful/example/base/tests/entry.txt 2009-10-21 15:00:30 +0000
@@ -52,8 +52,8 @@
52 >>> negotiated_type('application/xhtml+xml')52 >>> negotiated_type('application/xhtml+xml')
53 'application/xhtml+xml'53 'application/xhtml+xml'
5454
55 >>> negotiated_type('application/vd.sun.wadl+xml')55 >>> negotiated_type('application/vnd.sun.wadl+xml')
56 'application/vd.sun.wadl+xml'56 'application/vnd.sun.wadl+xml'
5757
58 >>> negotiated_type(None)58 >>> negotiated_type(None)
59 'application/json'59 'application/json'
@@ -61,18 +61,18 @@
61 >>> negotiated_type('text/html')61 >>> negotiated_type('text/html')
62 'application/json'62 'application/json'
6363
64 >>> negotiated_type('application/json, application/vd.sun.wadl+xml')64 >>> negotiated_type('application/json, application/vnd.sun.wadl+xml')
65 'application/json'65 'application/json'
6666
67 >>> negotiated_type('application/json, application/xhtml+xml')67 >>> negotiated_type('application/json, application/xhtml+xml')
68 'application/json'68 'application/json'
6969
70 >>> negotiated_type('application/vd.sun.wadl+xml, text/html, '70 >>> negotiated_type('application/vnd.sun.wadl+xml, text/html, '
71 ... 'application/json')71 ... 'application/json')
72 'application/vd.sun.wadl+xml'72 'application/vnd.sun.wadl+xml'
7373
74 >>> negotiated_type('application/json;q=0.5, application/vd.sun.wadl+xml')74 >>> negotiated_type('application/json;q=0.5, application/vnd.sun.wadl+xml')
75 'application/vd.sun.wadl+xml'75 'application/vnd.sun.wadl+xml'
7676
77 >>> negotiated_type('application/json;q=0, application/xhtml+xml;q=0.05,'77 >>> negotiated_type('application/json;q=0, application/xhtml+xml;q=0.05,'
78 ... 'application/vd.sun.wadl+xml;q=0.1')78 ... 'application/vd.sun.wadl+xml;q=0.1')
@@ -95,6 +95,13 @@
95 ... 'application/json;q=0.5, application/xhtml+xml;q=0,')95 ... 'application/json;q=0.5, application/xhtml+xml;q=0,')
96 'application/xhtml+xml'96 'application/xhtml+xml'
9797
98Earlier versions of lazr.restful served a misspelling of the WADL
99media type. For purposes of backwards compatibility, lazr.restful
100will still serve this media type if it's requested.
101
102 >>> negotiated_type('application/vd.sun.wadl+xml')
103 'application/vd.sun.wadl+xml'
104
98XHTML representations105XHTML representations
99=====================106=====================
100107
101108
=== modified file 'src/lazr/restful/example/base/tests/wadl.txt'
--- src/lazr/restful/example/base/tests/wadl.txt 2009-07-07 18:30:11 +0000
+++ src/lazr/restful/example/base/tests/wadl.txt 2009-10-21 15:00:30 +0000
@@ -18,7 +18,7 @@
18 >>> webservice = WebServiceCaller(domain='cookbooks.dev')18 >>> webservice = WebServiceCaller(domain='cookbooks.dev')
19 >>> entry_url = quote("/cookbooks/The Joy of Cooking")19 >>> entry_url = quote("/cookbooks/The Joy of Cooking")
20 >>> wadl = webservice.get(20 >>> wadl = webservice.get(
21 ... entry_url, 'application/vd.sun.wadl+xml').body21 ... entry_url, 'application/vnd.sun.wadl+xml').body
2222
23It's an XML document.23It's an XML document.
2424
@@ -112,7 +112,7 @@
112<resources> tag that contains a <resource> tag.112<resources> tag that contains a <resource> tag.
113113
114 >>> wadl = webservice.get('/cookbooks',114 >>> wadl = webservice.get('/cookbooks',
115 ... 'application/vd.sun.wadl+xml').body115 ... 'application/vnd.sun.wadl+xml').body
116 >>> validate(wadl)116 >>> validate(wadl)
117 True117 True
118118
@@ -145,7 +145,7 @@
145the representation of a top-level collection.145the representation of a top-level collection.
146146
147 >>> wadl = webservice.get(entry_url + '/recipes',147 >>> wadl = webservice.get(entry_url + '/recipes',
148 ... 'application/vd.sun.wadl+xml').body148 ... 'application/vnd.sun.wadl+xml').body
149 >>> validate(wadl)149 >>> validate(wadl)
150 True150 True
151151
@@ -194,7 +194,7 @@
194194
195 >>> wadl = webservice.get(195 >>> wadl = webservice.get(
196 ... entry_url + '/cover',196 ... entry_url + '/cover',
197 ... 'application/vd.sun.wadl+xml').body197 ... 'application/vnd.sun.wadl+xml').body
198 >>> validate(wadl)198 >>> validate(wadl)
199 True199 True
200200
@@ -237,7 +237,7 @@
237resources. It's a big document.237resources. It's a big document.
238238
239 >>> wadl = webservice.get(239 >>> wadl = webservice.get(
240 ... '/', 'application/vd.sun.wadl+xml').body240 ... '/', 'application/vnd.sun.wadl+xml').body
241 >>> validate(wadl)241 >>> validate(wadl)
242 True242 True
243 >>> tree = etree.fromstring(wadl)243 >>> tree = etree.fromstring(wadl)
@@ -294,7 +294,7 @@
294 >>> json_repr.attrib['href']294 >>> json_repr.attrib['href']
295 '#service-root-json'295 '#service-root-json'
296 >>> wadl_repr.attrib['mediaType']296 >>> wadl_repr.attrib['mediaType']
297 'application/vd.sun.wadl+xml'297 'application/vnd.sun.wadl+xml'
298298
299The details of the 'service-root-json' representation are given299The details of the 'service-root-json' representation are given
300immediately afterwards:300immediately afterwards:
@@ -425,7 +425,7 @@
425 <method name="GET" id="CookbookCollection-get">425 <method name="GET" id="CookbookCollection-get">
426 <response>426 <response>
427 <representation href="http://.../#cookbook-page"/>427 <representation href="http://.../#cookbook-page"/>
428 <representation mediaType="application/vd.sun.wadl+xml"428 <representation mediaType="application/vnd.sun.wadl+xml"
429 id="CookbookCollection-wadl"/>429 id="CookbookCollection-wadl"/>
430 </response>430 </response>
431 </method>431 </method>
@@ -458,7 +458,7 @@
458 <response>458 <response>
459 <representation459 <representation
460 href="http://.../#message-full"/>460 href="http://.../#message-full"/>
461 <representation mediaType="application/vd.sun.wadl+xml"461 <representation mediaType="application/vnd.sun.wadl+xml"
462 id="message-wadl"/>462 id="message-wadl"/>
463 </response>463 </response>
464 </method>464 </method>
@@ -577,7 +577,7 @@
577 'http://...#cookbook-page'577 'http://...#cookbook-page'
578578
579 >>> wadl_rep.attrib['mediaType']579 >>> wadl_rep.attrib['mediaType']
580 'application/vd.sun.wadl+xml'580 'application/vnd.sun.wadl+xml'
581 >>> wadl_rep.attrib['id']581 >>> wadl_rep.attrib['id']
582 'cookbooks-wadl'582 'cookbooks-wadl'
583583
@@ -951,7 +951,7 @@
951 >>> wadl.attrib['id']951 >>> wadl.attrib['id']
952 'cookbook-wadl'952 'cookbook-wadl'
953 >>> wadl.attrib['mediaType']953 >>> wadl.attrib['mediaType']
954 'application/vd.sun.wadl+xml'954 'application/vnd.sun.wadl+xml'
955955
956Note that the JSON representation is just a hyperlink to the956Note that the JSON representation is just a hyperlink to the
957representation defined earlier.957representation defined earlier.
@@ -1175,3 +1175,32 @@
1175 >>> prev_type = single_list_value(prev)1175 >>> prev_type = single_list_value(prev)
1176 >>> prev_type.attrib['resource_type']1176 >>> prev_type.attrib['resource_type']
1177 '#cookbook-page-resource'1177 '#cookbook-page-resource'
1178
1179Misspelled media type
1180=====================
1181
1182Earlier versions of lazr.restful served WADL documents with a
1183misspelled media type. For purposes of backwards compatibility, a
1184client can still request this media type, and lazr.restful will serve
1185a standard WADL document with a misspelled Content-Type.
1186
1187 >>> misspelling = 'application/vd.sun.wadl+xml'
1188 >>> misspelled_response = webservice.get("/", misspelling)
1189 >>> misspelled_response.getHeader("Content-Type") == misspelling
1190 True
1191
1192 >>> wadl_from_misspelled_response = misspelled_response.body
1193 >>> validate(wadl_from_misspelled_response)
1194 True
1195
1196This works with any kind of resource you might request the WADL for:
1197the service root, an entry resource, or a hosted binary file resource.
1198
1199 >>> misspelled_response = webservice.get(entry_url, misspelling)
1200 >>> misspelled_response.getHeader("Content-Type") == misspelling
1201 True
1202
1203 >>> misspelled_response = webservice.get(
1204 ... entry_url + "/cover", misspelling)
1205 >>> misspelled_response.getHeader("Content-Type") == misspelling
1206 True
11781207
=== modified file 'src/lazr/restful/templates/wadl-root.pt'
--- src/lazr/restful/templates/wadl-root.pt 2009-10-15 15:32:57 +0000
+++ src/lazr/restful/templates/wadl-root.pt 2009-10-21 15:00:30 +0000
@@ -24,7 +24,7 @@
24 <method name="GET" id="service-root-get">24 <method name="GET" id="service-root-get">
25 <response>25 <response>
26 <representation href="#service-root-json" />26 <representation href="#service-root-json" />
27 <representation mediaType="application/vd.sun.wadl+xml"27 <representation mediaType="application/vnd.sun.wadl+xml"
28 id="service-root-wadl" />28 id="service-root-wadl" />
29 </response>29 </response>
30 </method>30 </method>
@@ -64,7 +64,7 @@
64 tal:attributes="64 tal:attributes="
65 href entry_schema/wadl_entry_interface:entry_page_representation_link"65 href entry_schema/wadl_entry_interface:entry_page_representation_link"
66 />66 />
67 <representation mediaType="application/vd.sun.wadl+xml"67 <representation mediaType="application/vnd.sun.wadl+xml"
68 tal:attributes="id string:${context/wadl_collection:collection_type}-wadl" />68 tal:attributes="id string:${context/wadl_collection:collection_type}-wadl" />
69 </response>69 </response>
70 </method>70 </method>
@@ -133,7 +133,7 @@
133 tal:attributes="href context/wadl_entry:full_representation_link" />133 tal:attributes="href context/wadl_entry:full_representation_link" />
134 <representation mediaType="application/xhtml+xml"134 <representation mediaType="application/xhtml+xml"
135 tal:attributes="id string:${context/wadl_entry:singular_type}-xhtml" />135 tal:attributes="id string:${context/wadl_entry:singular_type}-xhtml" />
136 <representation mediaType="application/vd.sun.wadl+xml"136 <representation mediaType="application/vnd.sun.wadl+xml"
137 tal:attributes="id string:${context/wadl_entry:singular_type}-wadl" />137 tal:attributes="id string:${context/wadl_entry:singular_type}-wadl" />
138 </response>138 </response>
139 </method>139 </method>
140140
=== modified file 'src/lazr/restful/version.txt'
--- src/lazr/restful/version.txt 2009-10-20 17:07:56 +0000
+++ src/lazr/restful/version.txt 2009-10-21 15:00:30 +0000
@@ -1,1 +1,1 @@
10.9.1410.9.15

Subscribers

People subscribed via source and target branches