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
1=== modified file 'src/lazr/restful/NEWS.txt'
2--- src/lazr/restful/NEWS.txt 2009-10-20 17:07:56 +0000
3+++ src/lazr/restful/NEWS.txt 2009-10-21 15:00:30 +0000
4@@ -2,6 +2,11 @@
5 NEWS for lazr.restful
6 =====================
7
8+0.9.15 (2009-10-21)
9+===================
10+
11+Corrected a misspelling of the WADL media type.
12+
13 0.9.14 (2009-10-20)
14 ===================
15
16
17=== modified file 'src/lazr/restful/_bytestorage.py'
18--- src/lazr/restful/_bytestorage.py 2009-03-26 17:25:22 +0000
19+++ src/lazr/restful/_bytestorage.py 2009-10-21 15:00:30 +0000
20@@ -59,10 +59,10 @@
21
22 def do_GET(self):
23 """See `IByteStorageResource`."""
24- if self.getPreferredSupportedContentType() == self.WADL_TYPE:
25+ media_type = self.getPreferredSupportedContentType()
26+ if media_type in [self.WADL_TYPE, self.DEPRECATED_WADL_TYPE]:
27 result = self.toWADL().encode("utf-8")
28- self.request.response.setHeader(
29- 'Content-Type', self.WADL_TYPE)
30+ self.request.response.setHeader('Content-Type', media_type)
31 return result
32 if not self.context.is_stored:
33 # No stored document exists here yet.
34
35=== modified file 'src/lazr/restful/_resource.py'
36--- src/lazr/restful/_resource.py 2009-10-20 17:00:23 +0000
37+++ src/lazr/restful/_resource.py 2009-10-21 15:00:30 +0000
38@@ -171,10 +171,15 @@
39 implements(IHTTPResource)
40
41 # Some interesting media types.
42- WADL_TYPE = 'application/vd.sun.wadl+xml'
43+ WADL_TYPE = 'application/vnd.sun.wadl+xml'
44 JSON_TYPE = 'application/json'
45 XHTML_TYPE = 'application/xhtml+xml'
46
47+ # This misspelling of the WADL media type was used for a while,
48+ # and lazr.restful still supports it to avoid breaking clients
49+ # that depend on it.
50+ DEPRECATED_WADL_TYPE = 'application/vd.sun.wadl+xml'
51+
52 # A preparsed template file for WADL representations of resources.
53 WADL_TEMPLATE = LazrPageTemplateFile('templates/wadl-resource.pt')
54
55@@ -183,7 +188,7 @@
56
57 # All resources serve WADL and JSON representations. Only entry
58 # resources serve XHTML representations.
59- SUPPORTED_CONTENT_TYPES = [WADL_TYPE, JSON_TYPE]
60+ SUPPORTED_CONTENT_TYPES = [WADL_TYPE, DEPRECATED_WADL_TYPE, JSON_TYPE]
61
62 def __init__(self, context, request):
63 self.context = context
64@@ -311,7 +316,7 @@
65 if etag is not None:
66 return etag
67
68- if media_type == self.WADL_TYPE:
69+ if media_type in [self.WADL_TYPE, self.DEPRECATED_WADL_TYPE]:
70 # The WADL representation of a resource only changes when
71 # the software itself changes. Thus, we don't need any
72 # special information for its ETag core.
73@@ -1221,6 +1226,7 @@
74 implements(IEntryResource, IJSONPublishable)
75
76 SUPPORTED_CONTENT_TYPES = [HTTPResource.WADL_TYPE,
77+ HTTPResource.DEPRECATED_WADL_TYPE,
78 HTTPResource.XHTML_TYPE,
79 HTTPResource.JSON_TYPE]
80
81@@ -1405,7 +1411,7 @@
82
83 def _representation(self, media_type):
84 """Return a representation of this entry, of the given media type."""
85- if media_type == self.WADL_TYPE:
86+ if media_type in [self.WADL_TYPE, self.DEPRECATED_WADL_TYPE]:
87 return self.toWADL().encode("utf-8")
88 elif media_type == self.JSON_TYPE:
89 return simplejson.dumps(self, cls=ResourceJSONEncoder)
90@@ -1446,10 +1452,10 @@
91 if entries is None:
92 raise NotFound(self, self.collection_name)
93
94- if self.getPreferredSupportedContentType() == self.WADL_TYPE:
95+ media_type = self.getPreferredSupportedContentType()
96+ if media_type in [self.DEPRECATED_WADL_TYPE, self.WADL_TYPE]:
97 result = self.toWADL().encode("utf-8")
98- self.request.response.setHeader(
99- 'Content-Type', self.WADL_TYPE)
100+ self.request.response.setHeader('Content-Type', media_type)
101 return result
102
103 result = self.batch(entries)
104@@ -1540,7 +1546,7 @@
105 if media_type is None:
106 # The conditional GET succeeded. Serve nothing.
107 return ""
108- elif media_type == self.WADL_TYPE:
109+ elif media_type in [self.WADL_TYPE, self.DEPRECATED_WADL_TYPE]:
110 result = self.toWADL().encode("utf-8")
111 elif media_type == self.JSON_TYPE:
112 # Serve a JSON map containing links to all the top-level
113
114=== modified file 'src/lazr/restful/example/base/tests/entry.txt'
115--- src/lazr/restful/example/base/tests/entry.txt 2009-09-01 13:10:07 +0000
116+++ src/lazr/restful/example/base/tests/entry.txt 2009-10-21 15:00:30 +0000
117@@ -52,8 +52,8 @@
118 >>> negotiated_type('application/xhtml+xml')
119 'application/xhtml+xml'
120
121- >>> negotiated_type('application/vd.sun.wadl+xml')
122- 'application/vd.sun.wadl+xml'
123+ >>> negotiated_type('application/vnd.sun.wadl+xml')
124+ 'application/vnd.sun.wadl+xml'
125
126 >>> negotiated_type(None)
127 'application/json'
128@@ -61,18 +61,18 @@
129 >>> negotiated_type('text/html')
130 'application/json'
131
132- >>> negotiated_type('application/json, application/vd.sun.wadl+xml')
133+ >>> negotiated_type('application/json, application/vnd.sun.wadl+xml')
134 'application/json'
135
136 >>> negotiated_type('application/json, application/xhtml+xml')
137 'application/json'
138
139- >>> negotiated_type('application/vd.sun.wadl+xml, text/html, '
140+ >>> negotiated_type('application/vnd.sun.wadl+xml, text/html, '
141 ... 'application/json')
142- 'application/vd.sun.wadl+xml'
143+ 'application/vnd.sun.wadl+xml'
144
145- >>> negotiated_type('application/json;q=0.5, application/vd.sun.wadl+xml')
146- 'application/vd.sun.wadl+xml'
147+ >>> negotiated_type('application/json;q=0.5, application/vnd.sun.wadl+xml')
148+ 'application/vnd.sun.wadl+xml'
149
150 >>> negotiated_type('application/json;q=0, application/xhtml+xml;q=0.05,'
151 ... 'application/vd.sun.wadl+xml;q=0.1')
152@@ -95,6 +95,13 @@
153 ... 'application/json;q=0.5, application/xhtml+xml;q=0,')
154 'application/xhtml+xml'
155
156+Earlier versions of lazr.restful served a misspelling of the WADL
157+media type. For purposes of backwards compatibility, lazr.restful
158+will still serve this media type if it's requested.
159+
160+ >>> negotiated_type('application/vd.sun.wadl+xml')
161+ 'application/vd.sun.wadl+xml'
162+
163 XHTML representations
164 =====================
165
166
167=== modified file 'src/lazr/restful/example/base/tests/wadl.txt'
168--- src/lazr/restful/example/base/tests/wadl.txt 2009-07-07 18:30:11 +0000
169+++ src/lazr/restful/example/base/tests/wadl.txt 2009-10-21 15:00:30 +0000
170@@ -18,7 +18,7 @@
171 >>> webservice = WebServiceCaller(domain='cookbooks.dev')
172 >>> entry_url = quote("/cookbooks/The Joy of Cooking")
173 >>> wadl = webservice.get(
174- ... entry_url, 'application/vd.sun.wadl+xml').body
175+ ... entry_url, 'application/vnd.sun.wadl+xml').body
176
177 It's an XML document.
178
179@@ -112,7 +112,7 @@
180 <resources> tag that contains a <resource> tag.
181
182 >>> wadl = webservice.get('/cookbooks',
183- ... 'application/vd.sun.wadl+xml').body
184+ ... 'application/vnd.sun.wadl+xml').body
185 >>> validate(wadl)
186 True
187
188@@ -145,7 +145,7 @@
189 the representation of a top-level collection.
190
191 >>> wadl = webservice.get(entry_url + '/recipes',
192- ... 'application/vd.sun.wadl+xml').body
193+ ... 'application/vnd.sun.wadl+xml').body
194 >>> validate(wadl)
195 True
196
197@@ -194,7 +194,7 @@
198
199 >>> wadl = webservice.get(
200 ... entry_url + '/cover',
201- ... 'application/vd.sun.wadl+xml').body
202+ ... 'application/vnd.sun.wadl+xml').body
203 >>> validate(wadl)
204 True
205
206@@ -237,7 +237,7 @@
207 resources. It's a big document.
208
209 >>> wadl = webservice.get(
210- ... '/', 'application/vd.sun.wadl+xml').body
211+ ... '/', 'application/vnd.sun.wadl+xml').body
212 >>> validate(wadl)
213 True
214 >>> tree = etree.fromstring(wadl)
215@@ -294,7 +294,7 @@
216 >>> json_repr.attrib['href']
217 '#service-root-json'
218 >>> wadl_repr.attrib['mediaType']
219- 'application/vd.sun.wadl+xml'
220+ 'application/vnd.sun.wadl+xml'
221
222 The details of the 'service-root-json' representation are given
223 immediately afterwards:
224@@ -425,7 +425,7 @@
225 <method name="GET" id="CookbookCollection-get">
226 <response>
227 <representation href="http://.../#cookbook-page"/>
228- <representation mediaType="application/vd.sun.wadl+xml"
229+ <representation mediaType="application/vnd.sun.wadl+xml"
230 id="CookbookCollection-wadl"/>
231 </response>
232 </method>
233@@ -458,7 +458,7 @@
234 <response>
235 <representation
236 href="http://.../#message-full"/>
237- <representation mediaType="application/vd.sun.wadl+xml"
238+ <representation mediaType="application/vnd.sun.wadl+xml"
239 id="message-wadl"/>
240 </response>
241 </method>
242@@ -577,7 +577,7 @@
243 'http://...#cookbook-page'
244
245 >>> wadl_rep.attrib['mediaType']
246- 'application/vd.sun.wadl+xml'
247+ 'application/vnd.sun.wadl+xml'
248 >>> wadl_rep.attrib['id']
249 'cookbooks-wadl'
250
251@@ -951,7 +951,7 @@
252 >>> wadl.attrib['id']
253 'cookbook-wadl'
254 >>> wadl.attrib['mediaType']
255- 'application/vd.sun.wadl+xml'
256+ 'application/vnd.sun.wadl+xml'
257
258 Note that the JSON representation is just a hyperlink to the
259 representation defined earlier.
260@@ -1175,3 +1175,32 @@
261 >>> prev_type = single_list_value(prev)
262 >>> prev_type.attrib['resource_type']
263 '#cookbook-page-resource'
264+
265+Misspelled media type
266+=====================
267+
268+Earlier versions of lazr.restful served WADL documents with a
269+misspelled media type. For purposes of backwards compatibility, a
270+client can still request this media type, and lazr.restful will serve
271+a standard WADL document with a misspelled Content-Type.
272+
273+ >>> misspelling = 'application/vd.sun.wadl+xml'
274+ >>> misspelled_response = webservice.get("/", misspelling)
275+ >>> misspelled_response.getHeader("Content-Type") == misspelling
276+ True
277+
278+ >>> wadl_from_misspelled_response = misspelled_response.body
279+ >>> validate(wadl_from_misspelled_response)
280+ True
281+
282+This works with any kind of resource you might request the WADL for:
283+the service root, an entry resource, or a hosted binary file resource.
284+
285+ >>> misspelled_response = webservice.get(entry_url, misspelling)
286+ >>> misspelled_response.getHeader("Content-Type") == misspelling
287+ True
288+
289+ >>> misspelled_response = webservice.get(
290+ ... entry_url + "/cover", misspelling)
291+ >>> misspelled_response.getHeader("Content-Type") == misspelling
292+ True
293
294=== modified file 'src/lazr/restful/templates/wadl-root.pt'
295--- src/lazr/restful/templates/wadl-root.pt 2009-10-15 15:32:57 +0000
296+++ src/lazr/restful/templates/wadl-root.pt 2009-10-21 15:00:30 +0000
297@@ -24,7 +24,7 @@
298 <method name="GET" id="service-root-get">
299 <response>
300 <representation href="#service-root-json" />
301- <representation mediaType="application/vd.sun.wadl+xml"
302+ <representation mediaType="application/vnd.sun.wadl+xml"
303 id="service-root-wadl" />
304 </response>
305 </method>
306@@ -64,7 +64,7 @@
307 tal:attributes="
308 href entry_schema/wadl_entry_interface:entry_page_representation_link"
309 />
310- <representation mediaType="application/vd.sun.wadl+xml"
311+ <representation mediaType="application/vnd.sun.wadl+xml"
312 tal:attributes="id string:${context/wadl_collection:collection_type}-wadl" />
313 </response>
314 </method>
315@@ -133,7 +133,7 @@
316 tal:attributes="href context/wadl_entry:full_representation_link" />
317 <representation mediaType="application/xhtml+xml"
318 tal:attributes="id string:${context/wadl_entry:singular_type}-xhtml" />
319- <representation mediaType="application/vd.sun.wadl+xml"
320+ <representation mediaType="application/vnd.sun.wadl+xml"
321 tal:attributes="id string:${context/wadl_entry:singular_type}-wadl" />
322 </response>
323 </method>
324
325=== modified file 'src/lazr/restful/version.txt'
326--- src/lazr/restful/version.txt 2009-10-20 17:07:56 +0000
327+++ src/lazr/restful/version.txt 2009-10-21 15:00:30 +0000
328@@ -1,1 +1,1 @@
329-0.9.14
330+0.9.15

Subscribers

People subscribed via source and target branches