root / trunk / twisted / web2 / iweb.py

Revision 25888, 8.2 kB (checked in by exarkun, 6 months ago)

Merge iresource-3416-2

Author: exarkun
Reviewer: thijs, therve
Fixes: #3416

Add twisted.web.iweb.IRequest defining the interface provided by request objects
in Twisted Web.

Line 
1 # -*- test-case-name: twisted.web2.test -*-
2 # Copyright (c) 2008 Twisted Matrix Laboratories.
3 # See LICENSE for details.
4
5 """
6 I contain the interfaces for several web related objects including IRequest
7 and IResource.  I am based heavily on ideas from C{nevow.inevow}.
8 """
9
10 from zope.interface import Attribute, Interface, interface
11
12 # server.py interfaces
13 class IResource(Interface):
14     """
15     An HTTP resource.
16
17     I serve 2 main purposes: one is to provide a standard representation for
18     what HTTP specification calls an 'entity', and the other is to provide an
19     mechanism for mapping URLs to content.
20     """
21
22     def locateChild(req, segments):
23         """
24         Locate another object which can be adapted to IResource.
25
26         @return: A 2-tuple of (resource, remaining-path-segments),
27                  or a deferred which will fire the above.
28                 
29                  Causes the object publishing machinery to continue on
30                  with specified resource and segments, calling the
31                  appropriate method on the specified resource.
32                 
33                  If you return (self, L{server.StopTraversal}), this
34                  instructs web2 to immediately stop the lookup stage,
35                  and switch to the rendering stage, leaving the
36                  remaining path alone for your render function to
37                  handle.
38         """
39
40     def renderHTTP(req):
41         """
42         Return an IResponse or a deferred which will fire an
43         IResponse. This response will be written to the web browser
44         which initiated the request.
45         """
46
47 # Is there a better way to do this than this funky extra class?
48 _default = object()
49 class SpecialAdaptInterfaceClass(interface.InterfaceClass):
50     # A special adapter for IResource to handle the extra step of adapting
51     # from IOldNevowResource-providing resources.
52     def __call__(self, other, alternate=_default):
53         result = super(SpecialAdaptInterfaceClass, self).__call__(other, alternate)
54         if result is not alternate:
55             return result
56        
57         result = IOldNevowResource(other, alternate)
58         if result is not alternate:
59             result = IResource(result)
60             return result
61         if alternate is not _default:
62             return alternate
63         raise TypeError('Could not adapt', other, self)
64 IResource.__class__ = SpecialAdaptInterfaceClass
65
66 class IOldNevowResource(Interface):
67     # Shared interface with inevow.IResource
68     """
69     I am a web resource.
70     """
71
72     def locateChild(ctx, segments):
73         """
74         Locate another object which can be adapted to IResource
75         Return a tuple of resource, path segments
76         """
77
78     def renderHTTP(ctx):
79         """
80         Return a string or a deferred which will fire a string. This string
81         will be written to the web browser which initiated this request.
82
83         Unlike iweb.IResource, this expects the incoming data to have already been read
84         and parsed into request.args and request.content, and expects to return a
85         string instead of a response object.
86         """
87
88 class ICanHandleException(Interface):
89    
90     # Shared interface with inevow.ICanHandleException
91     def renderHTTP_exception(request, failure):
92         """
93         Render an exception to the given request object.
94         """
95
96     def renderInlineException(request, reason):
97         """
98         Return stan representing the exception, to be printed in the page,
99         not replacing the page."""
100
101
102 # http.py interfaces
103 class IResponse(Interface):
104     """
105     I'm a response.
106     """
107     code = Attribute("The HTTP response code")
108     headers = Attribute("A http_headers.Headers instance of headers to send")
109     stream = Attribute("A stream.IByteStream of outgoing data, or else None.")
110
111 class IRequest(Interface):
112     """
113     I'm a request for a web resource.
114     """
115
116     method = Attribute("The HTTP method from the request line, e.g. GET")
117     uri = Attribute("The raw URI from the request line. May or may not include host.")
118     clientproto = Attribute("Protocol from the request line, e.g. HTTP/1.1")
119    
120     headers = Attribute("A http_headers.Headers instance of incoming headers.")
121     stream = Attribute("A stream.IByteStream of incoming data.")
122    
123     def writeResponse(response):
124         """
125         Write an IResponse object to the client.
126         """
127        
128     chanRequest = Attribute("The ChannelRequest. I wonder if this is public really?")
129
130
131 from twisted.web.iweb import IRequest as IOldRequest
132
133
134 class IChanRequestCallbacks(Interface):
135     """
136     The bits that are required of a Request for interfacing with a
137     IChanRequest object
138     """
139
140     def __init__(chanRequest, command, path, version, contentLength, inHeaders):
141         """
142         Create a new Request object.
143         
144         @param chanRequest: the IChanRequest object creating this request
145         @param command: the HTTP command e.g. GET
146         @param path: the HTTP path e.g. /foo/bar.html
147         @param version: the parsed HTTP version e.g. (1,1)
148         @param contentLength: how much data to expect, or None if unknown
149         @param inHeaders: the request headers"""
150
151     def process():
152         """
153         Process the request. Called as soon as it's possibly reasonable
154         to return a response. L{handleContentComplete} may or may not
155         have been called already.
156         """
157        
158     def handleContentChunk(data):
159         """
160         Called when a piece of incoming data has been received.
161         """
162        
163     def handleContentComplete():
164         """
165         Called when the incoming data stream is finished.
166         """
167        
168     def connectionLost(reason):
169         """
170         Called if the connection was lost.
171         """
172        
173    
174 class IChanRequest(Interface):
175    
176     def writeIntermediateResponse(code, headers=None):
177         """
178         Write a non-terminating response.
179         
180         Intermediate responses cannot contain data.
181         If the channel does not support intermediate responses, do nothing.
182         
183         @param code: The response code. Should be in the 1xx range.
184         @type code: int
185         @param headers: the headers to send in the response
186         @type headers: C{twisted.web.http_headers.Headers}
187         """
188    
189     def writeHeaders(code, headers):
190         """
191         Write a final response.
192
193         @param code: The response code. Should not be in the 1xx range.
194         @type code: int
195         @param headers: the headers to send in the response. They will
196             be augmented with any connection-oriented headers as
197             necessary for the protocol.
198         @type headers: C{twisted.web.http_headers.Headers}
199         """
200        
201     def write(data):
202         """
203         Write some data.
204
205         @param data: the data bytes
206         @type data: str
207         """
208    
209     def finish():
210         """
211         Finish the request, and clean up the connection if necessary.
212         """
213    
214     def abortConnection():
215         """
216         Forcibly abort the connection without cleanly closing.
217         
218         Use if, for example, you can't write all the data you promised.
219         """
220
221     def registerProducer(producer, streaming):
222         """
223         Register a producer with the standard API.
224         """
225    
226     def unregisterProducer():
227         """
228         Unregister a producer.
229         """
230
231     def getHostInfo():
232         """
233         Returns a tuple of (address, socket user connected to,
234         boolean, was it secure).  Note that this should not necessarily
235         always return the actual local socket information from
236         twisted. E.g. in a CGI, it should use the variables coming
237         from the invoking script.
238         """
239
240     def getRemoteHost():
241         """
242         Returns an address of the remote host.
243
244         Like L{getHostInfo}, this information may come from the real
245         socket, or may come from additional information, depending on
246         the transport.
247         """
248
249     persistent = Attribute("""Whether this request supports HTTP connection persistence. May be set to False. Should not be set to other values.""")
250
251
252 class ISite(Interface):
253     pass
254
255 __all__ = ['ICanHandleException', 'IChanRequest', 'IChanRequestCallbacks', 'IOldNevowResource', 'IOldRequest', 'IRequest', 'IResource', 'IResponse', 'ISite']
Note: See TracBrowser for help on using the browser.